aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/key.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/key.c')
-rw-r--r--security/keys/key.c57
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
21static kmem_cache_t *key_jar; 23static kmem_cache_t *key_jar;
22static key_serial_t key_serial_next = 3;
23struct rb_root key_serial_tree; /* tree of keys indexed by serial */ 24struct rb_root key_serial_tree; /* tree of keys indexed by serial */
24DEFINE_SPINLOCK(key_serial_lock); 25DEFINE_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 */
175static inline void key_alloc_serial(struct key *key) 176static 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: 209serial_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: 232insert_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 */
249struct key *key_alloc(struct key_type *type, const char *desc, 250struct 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:
332security_error: 335security_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:
345no_memory_3: 348no_memory_3:
346 kmem_cache_free(key_jar, key); 349 kmem_cache_free(key_jar, key);
347no_memory_2: 350no_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