diff options
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/gc.c | 9 | ||||
-rw-r--r-- | security/keys/keyring.c | 2 | ||||
-rw-r--r-- | security/keys/proc.c | 1 | ||||
-rw-r--r-- | security/keys/process_keys.c | 1 | ||||
-rw-r--r-- | security/keys/request_key.c | 22 | ||||
-rw-r--r-- | security/keys/user_defined.c | 3 |
6 files changed, 25 insertions, 13 deletions
diff --git a/security/keys/gc.c b/security/keys/gc.c index 19902319d097..a46e825cbf02 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -77,10 +77,10 @@ static bool key_gc_keyring(struct key *keyring, time_t limit) goto dont_gc; /* scan the keyring looking for dead keys */ - klist = rcu_dereference_check(keyring->payload.subscriptions, - lockdep_is_held(&key_serial_lock)); + rcu_read_lock(); + klist = rcu_dereference(keyring->payload.subscriptions); if (!klist) - goto dont_gc; + goto unlock_dont_gc; for (loop = klist->nkeys - 1; loop >= 0; loop--) { key = klist->keys[loop]; @@ -89,11 +89,14 @@ static bool key_gc_keyring(struct key *keyring, time_t limit) goto do_gc; } +unlock_dont_gc: + rcu_read_unlock(); dont_gc: kleave(" = false"); return false; do_gc: + rcu_read_unlock(); key_gc_cursor = keyring->serial; key_get(keyring); spin_unlock(&key_serial_lock); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index ce7c44b857d0..2fb2bc9712ae 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -199,7 +199,7 @@ static long keyring_read(const struct key *keyring, int loop, ret; ret = 0; - klist = rcu_dereference(keyring->payload.subscriptions); + klist = keyring->payload.subscriptions; if (klist) { /* calculate how much data we could return */ diff --git a/security/keys/proc.c b/security/keys/proc.c index 81bf98d67c6b..068b66ea2f1b 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> -#include <linux/slab.h> #include <linux/fs.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 5c23afb31ece..06c2ccf26ed3 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> -#include <linux/slab.h> #include <linux/keyctl.h> #include <linux/fs.h> #include <linux/err.h> diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 03fe63ed55bd..d737cea5347c 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -68,7 +68,8 @@ static int call_sbin_request_key(struct key_construction *cons, { const struct cred *cred = current_cred(); key_serial_t prkey, sskey; - struct key *key = cons->key, *authkey = cons->authkey, *keyring; + struct key *key = cons->key, *authkey = cons->authkey, *keyring, + *session; char *argv[9], *envp[3], uid_str[12], gid_str[12]; char key_str[12], keyring_str[3][12]; char desc[20]; @@ -112,10 +113,12 @@ static int call_sbin_request_key(struct key_construction *cons, if (cred->tgcred->process_keyring) prkey = cred->tgcred->process_keyring->serial; - if (cred->tgcred->session_keyring) - sskey = rcu_dereference(cred->tgcred->session_keyring)->serial; - else - sskey = cred->user->session_keyring->serial; + rcu_read_lock(); + session = rcu_dereference(cred->tgcred->session_keyring); + if (!session) + session = cred->user->session_keyring; + sskey = session->serial; + rcu_read_unlock(); sprintf(keyring_str[2], "%d", sskey); @@ -336,8 +339,10 @@ static int construct_alloc_key(struct key_type *type, key_already_present: mutex_unlock(&key_construction_mutex); - if (dest_keyring) + if (dest_keyring) { + __key_link(dest_keyring, key_ref_to_ptr(key_ref)); up_write(&dest_keyring->sem); + } mutex_unlock(&user->cons_lock); key_put(key); *_key = key = key_ref_to_ptr(key_ref); @@ -428,6 +433,11 @@ struct key *request_key_and_link(struct key_type *type, if (!IS_ERR(key_ref)) { key = key_ref_to_ptr(key_ref); + if (dest_keyring) { + construct_get_dest_keyring(&dest_keyring); + key_link(dest_keyring, key); + key_put(dest_keyring); + } } else if (PTR_ERR(key_ref) != -EAGAIN) { key = ERR_CAST(key_ref); } else { diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 7c687d568221..e9aa07929656 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c @@ -199,7 +199,8 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen) struct user_key_payload *upayload; long ret; - upayload = rcu_dereference(key->payload.data); + upayload = rcu_dereference_protected( + key->payload.data, rwsem_is_locked(&((struct key *)key)->sem)); ret = upayload->datalen; /* we can return the data as is */ |