From ccc3e6d9c9aea07a0b60b2b0bfc5b05a704b66d5 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 24 Sep 2013 10:35:16 +0100 Subject: KEYS: Define a __key_get() wrapper to use rather than atomic_inc() Define a __key_get() wrapper to use rather than atomic_inc() on the key usage count as this makes it easier to hook in refcount error debugging. Signed-off-by: David Howells --- Documentation/security/keys.txt | 13 ++++++++----- include/linux/key.h | 10 +++++++--- security/keys/key.c | 2 +- security/keys/keyring.c | 6 +++--- security/keys/process_keys.c | 16 ++++++++-------- 5 files changed, 27 insertions(+), 20 deletions(-) diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 9ede67084f0..a4c33f1a7c6 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt @@ -960,14 +960,17 @@ payload contents" for more information. the argument will not be parsed. -(*) Extra references can be made to a key by calling the following function: +(*) Extra references can be made to a key by calling one of the following + functions: + struct key *__key_get(struct key *key); struct key *key_get(struct key *key); - These need to be disposed of by calling key_put() when they've been - finished with. The key pointer passed in will be returned. If the pointer - is NULL or CONFIG_KEYS is not set then the key will not be dereferenced and - no increment will take place. + Keys so references will need to be disposed of by calling key_put() when + they've been finished with. The key pointer passed in will be returned. + + In the case of key_get(), if the pointer is NULL or CONFIG_KEYS is not set + then the key will not be dereferenced and no increment will take place. (*) A key's serial number can be obtained by calling: diff --git a/include/linux/key.h b/include/linux/key.h index d573e820a23..ef596c7af58 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -219,13 +219,17 @@ extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); extern void key_put(struct key *key); -static inline struct key *key_get(struct key *key) +static inline struct key *__key_get(struct key *key) { - if (key) - atomic_inc(&key->usage); + atomic_inc(&key->usage); return key; } +static inline struct key *key_get(struct key *key) +{ + return key ? __key_get(key) : key; +} + static inline void key_ref_put(key_ref_t key_ref) { key_put(key_ref_to_ptr(key_ref)); diff --git a/security/keys/key.c b/security/keys/key.c index 7e6bc396bb2..1e23cc28810 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -644,7 +644,7 @@ found: /* this races with key_put(), but that doesn't matter since key_put() * doesn't actually change the key */ - atomic_inc(&key->usage); + __key_get(key); error: spin_unlock(&key_serial_lock); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index b42f2d4f7f8..87eff32b53f 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -479,7 +479,7 @@ not_this_keyring: /* we found a viable match */ found: - atomic_inc(&key->usage); + __key_get(key); key->last_used_at = ctx->now.tv_sec; keyring->last_used_at = ctx->now.tv_sec; while (sp > 0) @@ -573,7 +573,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref, return ERR_PTR(-ENOKEY); found: - atomic_inc(&key->usage); + __key_get(key); keyring->last_used_at = key->last_used_at = current_kernel_time().tv_sec; rcu_read_unlock(); @@ -909,7 +909,7 @@ void __key_link(struct key *keyring, struct key *key, klist = rcu_dereference_locked_keyring(keyring); - atomic_inc(&key->usage); + __key_get(key); keyring->last_used_at = key->last_used_at = current_kernel_time().tv_sec; diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index e68a3e0e7aa..68548ea6fe0 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -235,7 +235,7 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) if (IS_ERR(keyring)) return PTR_ERR(keyring); } else { - atomic_inc(&keyring->usage); + __key_get(keyring); } /* install the keyring */ @@ -544,7 +544,7 @@ try_again: } key = ctx.cred->thread_keyring; - atomic_inc(&key->usage); + __key_get(key); key_ref = make_key_ref(key, 1); break; @@ -562,7 +562,7 @@ try_again: } key = ctx.cred->process_keyring; - atomic_inc(&key->usage); + __key_get(key); key_ref = make_key_ref(key, 1); break; @@ -593,7 +593,7 @@ try_again: rcu_read_lock(); key = rcu_dereference(ctx.cred->session_keyring); - atomic_inc(&key->usage); + __key_get(key); rcu_read_unlock(); key_ref = make_key_ref(key, 1); break; @@ -606,7 +606,7 @@ try_again: } key = ctx.cred->user->uid_keyring; - atomic_inc(&key->usage); + __key_get(key); key_ref = make_key_ref(key, 1); break; @@ -618,7 +618,7 @@ try_again: } key = ctx.cred->user->session_keyring; - atomic_inc(&key->usage); + __key_get(key); key_ref = make_key_ref(key, 1); break; @@ -632,7 +632,7 @@ try_again: if (!key) goto error; - atomic_inc(&key->usage); + __key_get(key); key_ref = make_key_ref(key, 1); break; @@ -648,7 +648,7 @@ try_again: } else { rka = ctx.cred->request_key_auth->payload.data; key = rka->dest_keyring; - atomic_inc(&key->usage); + __key_get(key); } up_read(&ctx.cred->request_key_auth->sem); if (!key) -- cgit v1.2.3