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 | void fsverity_set_info(struct inode *inode, struct fsverity_info *vi) | 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. | 224 | * Multiple tasks may race to set ->i_verity_info, so use |
| 225 | * This pairs with the READ_ONCE() in fsverity_get_info(). | 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 | fsverity_free_info(vi); | 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 | void fsverity_free_info(struct fsverity_info *vi) | 240 | void fsverity_free_info(struct fsverity_info *vi) |
| @@ -115,8 +115,13 @@ struct fsverity_operations { · 114 unmodified lines | |||
| 115 | 115 | ||
| 116 | static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) | 116 | static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) |
| 117 | { | 117 | { |
| 118 | /* pairs with the cmpxchg() in fsverity_set_info() */ | 118 | /* |
| 119 | return READ_ONCE(inode->i_verity_info); | 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 | /* enable.c */ | 127 | /* enable.c */ |