fscrypt: Replace mk_users keyring with simple list
Subsystems (2)
Eric Biggers
maintainerPATCH 1/1 fscrypt: Replace mk_users keyring with simple list
commit 696c030e1e3438955aba443b308ee8b6faa3983e upstream.
Change mk_users (the set of user claims to an fscrypt master key) from a 'struct key' keyring to a simple linked list.
It's still a collection of 'struct key' for quota tracking. It was originally thought to be natural that a collection of 'struct key' should be held in a 'struct key' keyring. In reality, it's just been causing problems, similar to how using 'struct key' for the filesystem keyring caused problems and was removed in commit d7e7b9af104c ("fscrypt: stop using keyrings subsystem for fscrypt_master_key").
Commit d3a7bd420076 ("fscrypt: clear keyring before calling key_put()") fixed mk_users cleanup to be synchronous. But that apparently wasn't
enough: the keyring subsystem's redundant locking is still generating lockdep false positives due to the interaction with filesystem reclaim.
With the simple list, the redundant locking and lockdep issue goes away.
Of course, searching a linked list is linear-time whereas the 'struct key' keyring used a fancy constant-time associative array. But that's fine here, since in practice there's just one entry in the list. In fact the new code is much faster in practice, since it's much smaller and doesn't have to convert the kuid_t into a string to search for it.
--- fs/crypto/fscrypt_private.h | 32 ++++-- fs/crypto/keyring.c | 212 ++++++++++++++++-------------------- 2 files changed, 113 insertions(+), 131 deletions(-)
fs/crypto/fscrypt_private.h +22 -10
@@ -403,6 +403,19 @@ fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key,/* keyring.c */ +/* +* fscrypt_master_key_user - a user's claim to a master key +*/ +struct fscrypt_master_key_user { +struct list_head link; +kuid_t uid; +/* +* This 'struct key' contains no secret. It exists solely to charge the +* appropriate user's key quota. +*/ +struct key *quota_key; +}; +/* * fscrypt_master_key_secret - secret key material of an in-use master key */
@@ -489,19 +502,18 @@ struct fscrypt_master_key {struct fscrypt_key_specifier mk_spec;/* -* Keyring which contains a key of type 'key_type_fscrypt_user' for each -* user who has added this key. Normally each key will be added by just -* one user, but it's possible that multiple users share a key, and in -* that case we need to keep track of those users so that one user can't -* remove the key before the others want it removed too. +* List of user claims to this key (struct fscrypt_master_key_user). +* Normally each key will be added by just one user, but it's possible +* that multiple users share a key, and in that case we need to keep +* track of those users so that one user can't remove the key before the +* others want it removed too. * -* This is NULL for v1 policy keys; those can only be added by root. +* Used only for v2 policy keys. v1 policy keys can be added only by +* root, so user tracking doesn't apply to them. * -* Locking: protected by ->mk_sem. (We don't just rely on the keyrings -* subsystem semaphore ->mk_users->sem, as we need support for atomic -* search+insert along with proper synchronization with ->mk_secret.) +* Locking: protected by ->mk_sem. */ -struct key *mk_users; +struct list_head mk_users;/* * List of inodes that were unlocked using this key. This allows the
fs/crypto/keyring.c +91 -121
331 lines not on this page · raw message
base-commit: acccef89f184a697fee1c96a1dc9cccbba36937b
Signature · 1 line
2.55.0
Quoted 4 lines
commit
696c030e1e3438955aba443b308ee8b6faa3983eupstream.Change
mk_users(the set of user claims to an fscrypt master key) from a 'struct key' keyring to a simple linked list.
Queued for 5.10, thanks.
Signature · 2 lines
Thanks, Sasha