diff options
Diffstat (limited to 'security/keys/key.c')
-rw-r--r-- | security/keys/key.c | 57 |
1 files changed, 30 insertions, 27 deletions
diff --git a/security/keys/key.c b/security/keys/key.c index 51f851557389..80de8c3e9cc3 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -11,15 +11,16 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/poison.h> | ||
14 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
16 | #include <linux/security.h> | 17 | #include <linux/security.h> |
17 | #include <linux/workqueue.h> | 18 | #include <linux/workqueue.h> |
19 | #include <linux/random.h> | ||
18 | #include <linux/err.h> | 20 | #include <linux/err.h> |
19 | #include "internal.h" | 21 | #include "internal.h" |
20 | 22 | ||
21 | static kmem_cache_t *key_jar; | 23 | static kmem_cache_t *key_jar; |
22 | static key_serial_t key_serial_next = 3; | ||
23 | struct rb_root key_serial_tree; /* tree of keys indexed by serial */ | 24 | struct rb_root key_serial_tree; /* tree of keys indexed by serial */ |
24 | DEFINE_SPINLOCK(key_serial_lock); | 25 | DEFINE_SPINLOCK(key_serial_lock); |
25 | 26 | ||
@@ -169,22 +170,23 @@ static void __init __key_insert_serial(struct key *key) | |||
169 | /*****************************************************************************/ | 170 | /*****************************************************************************/ |
170 | /* | 171 | /* |
171 | * assign a key the next unique serial number | 172 | * assign a key the next unique serial number |
172 | * - we work through all the serial numbers between 2 and 2^31-1 in turn and | 173 | * - these are assigned randomly to avoid security issues through covert |
173 | * then wrap | 174 | * channel problems |
174 | */ | 175 | */ |
175 | static inline void key_alloc_serial(struct key *key) | 176 | static inline void key_alloc_serial(struct key *key) |
176 | { | 177 | { |
177 | struct rb_node *parent, **p; | 178 | struct rb_node *parent, **p; |
178 | struct key *xkey; | 179 | struct key *xkey; |
179 | 180 | ||
180 | spin_lock(&key_serial_lock); | 181 | /* propose a random serial number and look for a hole for it in the |
181 | |||
182 | /* propose a likely serial number and look for a hole for it in the | ||
183 | * serial number tree */ | 182 | * serial number tree */ |
184 | key->serial = key_serial_next; | 183 | do { |
185 | if (key->serial < 3) | 184 | get_random_bytes(&key->serial, sizeof(key->serial)); |
186 | key->serial = 3; | 185 | |
187 | key_serial_next = key->serial + 1; | 186 | key->serial >>= 1; /* negative numbers are not permitted */ |
187 | } while (key->serial < 3); | ||
188 | |||
189 | spin_lock(&key_serial_lock); | ||
188 | 190 | ||
189 | parent = NULL; | 191 | parent = NULL; |
190 | p = &key_serial_tree.rb_node; | 192 | p = &key_serial_tree.rb_node; |
@@ -204,12 +206,11 @@ static inline void key_alloc_serial(struct key *key) | |||
204 | 206 | ||
205 | /* we found a key with the proposed serial number - walk the tree from | 207 | /* we found a key with the proposed serial number - walk the tree from |
206 | * that point looking for the next unused serial number */ | 208 | * that point looking for the next unused serial number */ |
207 | serial_exists: | 209 | serial_exists: |
208 | for (;;) { | 210 | for (;;) { |
209 | key->serial = key_serial_next; | 211 | key->serial++; |
210 | if (key->serial < 2) | 212 | if (key->serial < 2) |
211 | key->serial = 2; | 213 | key->serial = 2; |
212 | key_serial_next = key->serial + 1; | ||
213 | 214 | ||
214 | if (!rb_parent(parent)) | 215 | if (!rb_parent(parent)) |
215 | p = &key_serial_tree.rb_node; | 216 | p = &key_serial_tree.rb_node; |
@@ -228,7 +229,7 @@ static inline void key_alloc_serial(struct key *key) | |||
228 | } | 229 | } |
229 | 230 | ||
230 | /* we've found a suitable hole - arrange for this key to occupy it */ | 231 | /* we've found a suitable hole - arrange for this key to occupy it */ |
231 | insert_here: | 232 | insert_here: |
232 | rb_link_node(&key->serial_node, parent, p); | 233 | rb_link_node(&key->serial_node, parent, p); |
233 | rb_insert_color(&key->serial_node, &key_serial_tree); | 234 | rb_insert_color(&key->serial_node, &key_serial_tree); |
234 | 235 | ||
@@ -248,7 +249,7 @@ static inline void key_alloc_serial(struct key *key) | |||
248 | */ | 249 | */ |
249 | struct key *key_alloc(struct key_type *type, const char *desc, | 250 | struct key *key_alloc(struct key_type *type, const char *desc, |
250 | uid_t uid, gid_t gid, struct task_struct *ctx, | 251 | uid_t uid, gid_t gid, struct task_struct *ctx, |
251 | key_perm_t perm, int not_in_quota) | 252 | key_perm_t perm, unsigned long flags) |
252 | { | 253 | { |
253 | struct key_user *user = NULL; | 254 | struct key_user *user = NULL; |
254 | struct key *key; | 255 | struct key *key; |
@@ -269,12 +270,14 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
269 | 270 | ||
270 | /* check that the user's quota permits allocation of another key and | 271 | /* check that the user's quota permits allocation of another key and |
271 | * its description */ | 272 | * its description */ |
272 | if (!not_in_quota) { | 273 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { |
273 | spin_lock(&user->lock); | 274 | spin_lock(&user->lock); |
274 | if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || | 275 | if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) { |
275 | user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES | 276 | if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || |
276 | ) | 277 | user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES |
277 | goto no_quota; | 278 | ) |
279 | goto no_quota; | ||
280 | } | ||
278 | 281 | ||
279 | user->qnkeys++; | 282 | user->qnkeys++; |
280 | user->qnbytes += quotalen; | 283 | user->qnbytes += quotalen; |
@@ -308,7 +311,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
308 | key->payload.data = NULL; | 311 | key->payload.data = NULL; |
309 | key->security = NULL; | 312 | key->security = NULL; |
310 | 313 | ||
311 | if (!not_in_quota) | 314 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) |
312 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; | 315 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; |
313 | 316 | ||
314 | memset(&key->type_data, 0, sizeof(key->type_data)); | 317 | memset(&key->type_data, 0, sizeof(key->type_data)); |
@@ -318,7 +321,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
318 | #endif | 321 | #endif |
319 | 322 | ||
320 | /* let the security module know about the key */ | 323 | /* let the security module know about the key */ |
321 | ret = security_key_alloc(key, ctx); | 324 | ret = security_key_alloc(key, ctx, flags); |
322 | if (ret < 0) | 325 | if (ret < 0) |
323 | goto security_error; | 326 | goto security_error; |
324 | 327 | ||
@@ -332,7 +335,7 @@ error: | |||
332 | security_error: | 335 | security_error: |
333 | kfree(key->description); | 336 | kfree(key->description); |
334 | kmem_cache_free(key_jar, key); | 337 | kmem_cache_free(key_jar, key); |
335 | if (!not_in_quota) { | 338 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { |
336 | spin_lock(&user->lock); | 339 | spin_lock(&user->lock); |
337 | user->qnkeys--; | 340 | user->qnkeys--; |
338 | user->qnbytes -= quotalen; | 341 | user->qnbytes -= quotalen; |
@@ -345,7 +348,7 @@ security_error: | |||
345 | no_memory_3: | 348 | no_memory_3: |
346 | kmem_cache_free(key_jar, key); | 349 | kmem_cache_free(key_jar, key); |
347 | no_memory_2: | 350 | no_memory_2: |
348 | if (!not_in_quota) { | 351 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { |
349 | spin_lock(&user->lock); | 352 | spin_lock(&user->lock); |
350 | user->qnkeys--; | 353 | user->qnkeys--; |
351 | user->qnbytes -= quotalen; | 354 | user->qnbytes -= quotalen; |
@@ -761,7 +764,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
761 | const char *description, | 764 | const char *description, |
762 | const void *payload, | 765 | const void *payload, |
763 | size_t plen, | 766 | size_t plen, |
764 | int not_in_quota) | 767 | unsigned long flags) |
765 | { | 768 | { |
766 | struct key_type *ktype; | 769 | struct key_type *ktype; |
767 | struct key *keyring, *key = NULL; | 770 | struct key *keyring, *key = NULL; |
@@ -822,7 +825,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
822 | 825 | ||
823 | /* allocate a new key */ | 826 | /* allocate a new key */ |
824 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, | 827 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, |
825 | current, perm, not_in_quota); | 828 | current, perm, flags); |
826 | if (IS_ERR(key)) { | 829 | if (IS_ERR(key)) { |
827 | key_ref = ERR_PTR(PTR_ERR(key)); | 830 | key_ref = ERR_PTR(PTR_ERR(key)); |
828 | goto error_3; | 831 | goto error_3; |
@@ -986,7 +989,7 @@ void unregister_key_type(struct key_type *ktype) | |||
986 | if (key->type == ktype) { | 989 | if (key->type == ktype) { |
987 | if (ktype->destroy) | 990 | if (ktype->destroy) |
988 | ktype->destroy(key); | 991 | ktype->destroy(key); |
989 | memset(&key->payload, 0xbd, sizeof(key->payload)); | 992 | memset(&key->payload, KEY_DESTROY, sizeof(key->payload)); |
990 | } | 993 | } |
991 | } | 994 | } |
992 | 995 | ||