diff options
author | Serge E. Hallyn <serue@us.ibm.com> | 2009-02-26 19:27:38 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-02-26 20:35:06 -0500 |
commit | 1d1e97562e5e2ac60fb7b25437ba619f95f67fab (patch) | |
tree | 68a9c52ecbff0782dd9b9438685afc3b40b6f707 /security/keys/key.c | |
parent | be38e0fd5f90a91d09e0a85ffb294b70a7be6259 (diff) |
keys: distinguish per-uid keys in different namespaces
per-uid keys were looked by uid only. Use the user namespace
to distinguish the same uid in different namespaces.
This does not address key_permission. So a task can for instance
try to join a keyring owned by the same uid in another namespace.
That will be handled by a separate patch.
Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys/key.c')
-rw-r--r-- | security/keys/key.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index f76c8a546fd3..4a1297d1ada4 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/workqueue.h> | 18 | #include <linux/workqueue.h> |
19 | #include <linux/random.h> | 19 | #include <linux/random.h> |
20 | #include <linux/err.h> | 20 | #include <linux/err.h> |
21 | #include <linux/user_namespace.h> | ||
21 | #include "internal.h" | 22 | #include "internal.h" |
22 | 23 | ||
23 | static struct kmem_cache *key_jar; | 24 | static struct kmem_cache *key_jar; |
@@ -60,7 +61,7 @@ void __key_check(const struct key *key) | |||
60 | * get the key quota record for a user, allocating a new record if one doesn't | 61 | * get the key quota record for a user, allocating a new record if one doesn't |
61 | * already exist | 62 | * already exist |
62 | */ | 63 | */ |
63 | struct key_user *key_user_lookup(uid_t uid) | 64 | struct key_user *key_user_lookup(uid_t uid, struct user_namespace *user_ns) |
64 | { | 65 | { |
65 | struct key_user *candidate = NULL, *user; | 66 | struct key_user *candidate = NULL, *user; |
66 | struct rb_node *parent = NULL; | 67 | struct rb_node *parent = NULL; |
@@ -79,6 +80,10 @@ struct key_user *key_user_lookup(uid_t uid) | |||
79 | p = &(*p)->rb_left; | 80 | p = &(*p)->rb_left; |
80 | else if (uid > user->uid) | 81 | else if (uid > user->uid) |
81 | p = &(*p)->rb_right; | 82 | p = &(*p)->rb_right; |
83 | else if (user_ns < user->user_ns) | ||
84 | p = &(*p)->rb_left; | ||
85 | else if (user_ns > user->user_ns) | ||
86 | p = &(*p)->rb_right; | ||
82 | else | 87 | else |
83 | goto found; | 88 | goto found; |
84 | } | 89 | } |
@@ -106,6 +111,7 @@ struct key_user *key_user_lookup(uid_t uid) | |||
106 | atomic_set(&candidate->nkeys, 0); | 111 | atomic_set(&candidate->nkeys, 0); |
107 | atomic_set(&candidate->nikeys, 0); | 112 | atomic_set(&candidate->nikeys, 0); |
108 | candidate->uid = uid; | 113 | candidate->uid = uid; |
114 | candidate->user_ns = get_user_ns(user_ns); | ||
109 | candidate->qnkeys = 0; | 115 | candidate->qnkeys = 0; |
110 | candidate->qnbytes = 0; | 116 | candidate->qnbytes = 0; |
111 | spin_lock_init(&candidate->lock); | 117 | spin_lock_init(&candidate->lock); |
@@ -136,6 +142,7 @@ void key_user_put(struct key_user *user) | |||
136 | if (atomic_dec_and_lock(&user->usage, &key_user_lock)) { | 142 | if (atomic_dec_and_lock(&user->usage, &key_user_lock)) { |
137 | rb_erase(&user->node, &key_user_tree); | 143 | rb_erase(&user->node, &key_user_tree); |
138 | spin_unlock(&key_user_lock); | 144 | spin_unlock(&key_user_lock); |
145 | put_user_ns(user->user_ns); | ||
139 | 146 | ||
140 | kfree(user); | 147 | kfree(user); |
141 | } | 148 | } |
@@ -234,7 +241,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
234 | quotalen = desclen + type->def_datalen; | 241 | quotalen = desclen + type->def_datalen; |
235 | 242 | ||
236 | /* get hold of the key tracking for this user */ | 243 | /* get hold of the key tracking for this user */ |
237 | user = key_user_lookup(uid); | 244 | user = key_user_lookup(uid, cred->user->user_ns); |
238 | if (!user) | 245 | if (!user) |
239 | goto no_memory_1; | 246 | goto no_memory_1; |
240 | 247 | ||