Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt

Pull fsverity update from Eric Biggers:
"One fix for fs/verity/ to strengthen a memory barrier which might be
too weak. This mirrors a similar fix in fs/crypto/"

* tag 'fsverity-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt:
fs-verity: use smp_load_acquire() for ->i_verity_info

+19 -5
+12 -3
fs/verity/open.c
··· 221 221 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi) 222 222 { 223 223 /* 224 - * Multiple processes may race to set ->i_verity_info, so use cmpxchg. 225 - * This pairs with the READ_ONCE() in fsverity_get_info(). 224 + * Multiple tasks may race to set ->i_verity_info, so use 225 + * cmpxchg_release(). This pairs with the smp_load_acquire() in 226 + * fsverity_get_info(). I.e., here we publish ->i_verity_info with a 227 + * RELEASE barrier so that other tasks can ACQUIRE it. 226 228 */ 227 - if (cmpxchg(&inode->i_verity_info, NULL, vi) != NULL) 229 + if (cmpxchg_release(&inode->i_verity_info, NULL, vi) != NULL) { 230 + /* Lost the race, so free the fsverity_info we allocated. */ 228 231 fsverity_free_info(vi); 232 + /* 233 + * Afterwards, the caller may access ->i_verity_info directly, 234 + * so make sure to ACQUIRE the winning fsverity_info. 235 + */ 236 + (void)fsverity_get_info(inode); 237 + } 229 238 } 230 239 231 240 void fsverity_free_info(struct fsverity_info *vi)
+7 -2
include/linux/fsverity.h
··· 115 115 116 116 static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) 117 117 { 118 - /* pairs with the cmpxchg() in fsverity_set_info() */ 119 - return READ_ONCE(inode->i_verity_info); 118 + /* 119 + * Pairs with the cmpxchg_release() in fsverity_set_info(). 120 + * I.e., another task may publish ->i_verity_info concurrently, 121 + * executing a RELEASE barrier. We need to use smp_load_acquire() here 122 + * to safely ACQUIRE the memory the other task published. 123 + */ 124 + return smp_load_acquire(&inode->i_verity_info); 120 125 } 121 126 122 127 /* enable.c */