Skip to content

Commit 777afe4

Browse files
committed
fscrypt: use smp_load_acquire() for ->s_master_keys
Normally smp_store_release() or cmpxchg_release() is paired with smp_load_acquire(). Sometimes smp_load_acquire() can be replaced with the more lightweight READ_ONCE(). However, for this to be safe, all the published memory must only be accessed in a way that involves the pointer itself. This may not be the case if allocating the object also involves initializing a static or global variable, for example. super_block::s_master_keys is a keyring, which is internal to and is allocated by the keyrings subsystem. By using READ_ONCE() for it, we're relying on internal implementation details of the keyrings subsystem. Remove this fragile assumption by using smp_load_acquire() instead. (Note: I haven't seen any real-world problems here. This change is just fixing the code to be guaranteed correct and less fragile.) Fixes: 22d94f4 ("fscrypt: add FS_IOC_ADD_ENCRYPTION_KEY ioctl") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Eric Biggers <[email protected]>
1 parent 97c6327 commit 777afe4

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

fs/crypto/keyring.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,11 @@ static int allocate_filesystem_keyring(struct super_block *sb)
213213
if (IS_ERR(keyring))
214214
return PTR_ERR(keyring);
215215

216-
/* Pairs with READ_ONCE() in fscrypt_find_master_key() */
216+
/*
217+
* Pairs with the smp_load_acquire() in fscrypt_find_master_key().
218+
* I.e., here we publish ->s_master_keys with a RELEASE barrier so that
219+
* concurrent tasks can ACQUIRE it.
220+
*/
217221
smp_store_release(&sb->s_master_keys, keyring);
218222
return 0;
219223
}
@@ -234,8 +238,13 @@ struct key *fscrypt_find_master_key(struct super_block *sb,
234238
struct key *keyring;
235239
char description[FSCRYPT_MK_DESCRIPTION_SIZE];
236240

237-
/* pairs with smp_store_release() in allocate_filesystem_keyring() */
238-
keyring = READ_ONCE(sb->s_master_keys);
241+
/*
242+
* Pairs with the smp_store_release() in allocate_filesystem_keyring().
243+
* I.e., another task can publish ->s_master_keys concurrently,
244+
* executing a RELEASE barrier. We need to use smp_load_acquire() here
245+
* to safely ACQUIRE the memory the other task published.
246+
*/
247+
keyring = smp_load_acquire(&sb->s_master_keys);
239248
if (keyring == NULL)
240249
return ERR_PTR(-ENOKEY); /* No keyring yet, so no keys yet. */
241250

0 commit comments

Comments
 (0)