Commit ddb99e11 authored by Elena Reshetova's avatar Elena Reshetova Committed by James Morris

security, keys: convert key_user.usage from atomic_t to refcount_t

refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.
Signed-off-by: default avatarElena Reshetova <elena.reshetova@intel.com>
Signed-off-by: default avatarHans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarDavid Windsor <dwindsor@gmail.com>
Acked-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarJames Morris <james.l.morris@oracle.com>
parent fff29291
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/key-type.h> #include <linux/key-type.h>
#include <linux/task_work.h> #include <linux/task_work.h>
#include <linux/keyctl.h> #include <linux/keyctl.h>
#include <linux/refcount.h>
struct iovec; struct iovec;
...@@ -53,7 +54,7 @@ struct key_user { ...@@ -53,7 +54,7 @@ struct key_user {
struct rb_node node; struct rb_node node;
struct mutex cons_lock; /* construction initiation lock */ struct mutex cons_lock; /* construction initiation lock */
spinlock_t lock; spinlock_t lock;
atomic_t usage; /* for accessing qnkeys & qnbytes */ refcount_t usage; /* for accessing qnkeys & qnbytes */
atomic_t nkeys; /* number of keys */ atomic_t nkeys; /* number of keys */
atomic_t nikeys; /* number of instantiated keys */ atomic_t nikeys; /* number of instantiated keys */
kuid_t uid; kuid_t uid;
......
...@@ -93,7 +93,7 @@ struct key_user *key_user_lookup(kuid_t uid) ...@@ -93,7 +93,7 @@ struct key_user *key_user_lookup(kuid_t uid)
/* if we get here, then the user record still hadn't appeared on the /* if we get here, then the user record still hadn't appeared on the
* second pass - so we use the candidate record */ * second pass - so we use the candidate record */
atomic_set(&candidate->usage, 1); refcount_set(&candidate->usage, 1);
atomic_set(&candidate->nkeys, 0); atomic_set(&candidate->nkeys, 0);
atomic_set(&candidate->nikeys, 0); atomic_set(&candidate->nikeys, 0);
candidate->uid = uid; candidate->uid = uid;
...@@ -110,7 +110,7 @@ struct key_user *key_user_lookup(kuid_t uid) ...@@ -110,7 +110,7 @@ struct key_user *key_user_lookup(kuid_t uid)
/* okay - we found a user record for this UID */ /* okay - we found a user record for this UID */
found: found:
atomic_inc(&user->usage); refcount_inc(&user->usage);
spin_unlock(&key_user_lock); spin_unlock(&key_user_lock);
kfree(candidate); kfree(candidate);
out: out:
...@@ -122,7 +122,7 @@ struct key_user *key_user_lookup(kuid_t uid) ...@@ -122,7 +122,7 @@ struct key_user *key_user_lookup(kuid_t uid)
*/ */
void key_user_put(struct key_user *user) void key_user_put(struct key_user *user)
{ {
if (atomic_dec_and_lock(&user->usage, &key_user_lock)) { if (refcount_dec_and_lock(&user->usage, &key_user_lock)) {
rb_erase(&user->node, &key_user_tree); rb_erase(&user->node, &key_user_tree);
spin_unlock(&key_user_lock); spin_unlock(&key_user_lock);
......
...@@ -340,7 +340,7 @@ static int proc_key_users_show(struct seq_file *m, void *v) ...@@ -340,7 +340,7 @@ static int proc_key_users_show(struct seq_file *m, void *v)
seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n", seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n",
from_kuid_munged(seq_user_ns(m), user->uid), from_kuid_munged(seq_user_ns(m), user->uid),
atomic_read(&user->usage), refcount_read(&user->usage),
atomic_read(&user->nkeys), atomic_read(&user->nkeys),
atomic_read(&user->nikeys), atomic_read(&user->nikeys),
user->qnkeys, user->qnkeys,
......
...@@ -30,7 +30,7 @@ static DEFINE_MUTEX(key_user_keyring_mutex); ...@@ -30,7 +30,7 @@ static DEFINE_MUTEX(key_user_keyring_mutex);
/* The root user's tracking struct */ /* The root user's tracking struct */
struct key_user root_key_user = { struct key_user root_key_user = {
.usage = ATOMIC_INIT(3), .usage = REFCOUNT_INIT(3),
.cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock), .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock),
.lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock),
.nkeys = ATOMIC_INIT(2), .nkeys = ATOMIC_INIT(2),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment