Skip to content

Commit 4f1e308

Browse files
committed
Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux
Pull fscrypt fix from Eric Biggers: "Fix a bug where when a filesystem was being unmounted, the fscrypt keyring was destroyed before inodes have been released by the Landlock LSM. This bug was found by syzbot" * tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux: fscrypt: check for NULL keyring in fscrypt_put_master_key_activeref() fscrypt: improve fscrypt_destroy_keyring() documentation fscrypt: destroy keyring after security_sb_delete()
2 parents 7d31677 + 4bcf6f8 commit 4f1e308

File tree

2 files changed

+25
-13
lines changed

2 files changed

+25
-13
lines changed

fs/crypto/keyring.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ void fscrypt_put_master_key_activeref(struct super_block *sb,
9292
* destroying any subkeys embedded in it.
9393
*/
9494

95+
if (WARN_ON(!sb->s_master_keys))
96+
return;
9597
spin_lock(&sb->s_master_keys->lock);
9698
hlist_del_rcu(&mk->mk_node);
9799
spin_unlock(&sb->s_master_keys->lock);
@@ -207,10 +209,11 @@ static int allocate_filesystem_keyring(struct super_block *sb)
207209
* Release all encryption keys that have been added to the filesystem, along
208210
* with the keyring that contains them.
209211
*
210-
* This is called at unmount time. The filesystem's underlying block device(s)
211-
* are still available at this time; this is important because after user file
212-
* accesses have been allowed, this function may need to evict keys from the
213-
* keyslots of an inline crypto engine, which requires the block device(s).
212+
* This is called at unmount time, after all potentially-encrypted inodes have
213+
* been evicted. The filesystem's underlying block device(s) are still
214+
* available at this time; this is important because after user file accesses
215+
* have been allowed, this function may need to evict keys from the keyslots of
216+
* an inline crypto engine, which requires the block device(s).
214217
*/
215218
void fscrypt_destroy_keyring(struct super_block *sb)
216219
{
@@ -227,12 +230,12 @@ void fscrypt_destroy_keyring(struct super_block *sb)
227230

228231
hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) {
229232
/*
230-
* Since all inodes were already evicted, every key
231-
* remaining in the keyring should have an empty inode
232-
* list, and should only still be in the keyring due to
233-
* the single active ref associated with ->mk_secret.
234-
* There should be no structural refs beyond the one
235-
* associated with the active ref.
233+
* Since all potentially-encrypted inodes were already
234+
* evicted, every key remaining in the keyring should
235+
* have an empty inode list, and should only still be in
236+
* the keyring due to the single active ref associated
237+
* with ->mk_secret. There should be no structural refs
238+
* beyond the one associated with the active ref.
236239
*/
237240
WARN_ON(refcount_read(&mk->mk_active_refs) != 1);
238241
WARN_ON(refcount_read(&mk->mk_struct_refs) != 1);

fs/super.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -475,13 +475,22 @@ void generic_shutdown_super(struct super_block *sb)
475475

476476
cgroup_writeback_umount();
477477

478-
/* evict all inodes with zero refcount */
478+
/* Evict all inodes with zero refcount. */
479479
evict_inodes(sb);
480-
/* only nonzero refcount inodes can have marks */
480+
481+
/*
482+
* Clean up and evict any inodes that still have references due
483+
* to fsnotify or the security policy.
484+
*/
481485
fsnotify_sb_delete(sb);
482-
fscrypt_destroy_keyring(sb);
483486
security_sb_delete(sb);
484487

488+
/*
489+
* Now that all potentially-encrypted inodes have been evicted,
490+
* the fscrypt keyring can be destroyed.
491+
*/
492+
fscrypt_destroy_keyring(sb);
493+
485494
if (sb->s_dio_done_wq) {
486495
destroy_workqueue(sb->s_dio_done_wq);
487496
sb->s_dio_done_wq = NULL;

0 commit comments

Comments
 (0)