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
Unified · Split
| @@ -221,11 +221,20 @@ out: · 220 unmodified lines | ||
| 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) |
| @@ -115,8 +115,13 @@ struct fsverity_operations { · 114 unmodified lines | ||
| 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 */ |