Skip to content

Commit 5577416

Browse files
committed
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
2 parents 690b256 + f3db0be commit 5577416

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

fs/verity/open.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,20 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
221221
void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
222222
{
223223
/*
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.
226228
*/
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. */
228231
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+
}
229238
}
230239

231240
void fsverity_free_info(struct fsverity_info *vi)

include/linux/fsverity.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,13 @@ struct fsverity_operations {
115115

116116
static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
117117
{
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);
120125
}
121126

122127
/* enable.c */

0 commit comments

Comments
 (0)