X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=security%2Fkeys%2Fkey.c;h=b6061fa29da7fc7eb5278530ebb26769dc4ebcde;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=80de8c3e9cc3ea49c79e6525b0ce17b22076ac3e;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/security/keys/key.c b/security/keys/key.c index 80de8c3e9..b6061fa29 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -11,16 +11,15 @@ #include #include -#include #include #include #include #include -#include #include #include "internal.h" static kmem_cache_t *key_jar; +static key_serial_t key_serial_next = 3; struct rb_root key_serial_tree; /* tree of keys indexed by serial */ DEFINE_SPINLOCK(key_serial_lock); @@ -170,24 +169,23 @@ static void __init __key_insert_serial(struct key *key) /*****************************************************************************/ /* * assign a key the next unique serial number - * - these are assigned randomly to avoid security issues through covert - * channel problems + * - we work through all the serial numbers between 2 and 2^31-1 in turn and + * then wrap */ static inline void key_alloc_serial(struct key *key) { struct rb_node *parent, **p; struct key *xkey; - /* propose a random serial number and look for a hole for it in the - * serial number tree */ - do { - get_random_bytes(&key->serial, sizeof(key->serial)); - - key->serial >>= 1; /* negative numbers are not permitted */ - } while (key->serial < 3); - spin_lock(&key_serial_lock); + /* propose a likely serial number and look for a hole for it in the + * serial number tree */ + key->serial = key_serial_next; + if (key->serial < 3) + key->serial = 3; + key_serial_next = key->serial + 1; + parent = NULL; p = &key_serial_tree.rb_node; @@ -206,18 +204,19 @@ static inline void key_alloc_serial(struct key *key) /* we found a key with the proposed serial number - walk the tree from * that point looking for the next unused serial number */ -serial_exists: + serial_exists: for (;;) { - key->serial++; + key->serial = key_serial_next; if (key->serial < 2) key->serial = 2; + key_serial_next = key->serial + 1; - if (!rb_parent(parent)) + if (!parent->rb_parent) p = &key_serial_tree.rb_node; - else if (rb_parent(parent)->rb_left == parent) - p = &(rb_parent(parent)->rb_left); + else if (parent->rb_parent->rb_left == parent) + p = &parent->rb_parent->rb_left; else - p = &(rb_parent(parent)->rb_right); + p = &parent->rb_parent->rb_right; parent = rb_next(parent); if (!parent) @@ -229,7 +228,7 @@ serial_exists: } /* we've found a suitable hole - arrange for this key to occupy it */ -insert_here: + insert_here: rb_link_node(&key->serial_node, parent, p); rb_insert_color(&key->serial_node, &key_serial_tree); @@ -248,8 +247,8 @@ insert_here: * instantiate the key or discard it before returning */ struct key *key_alloc(struct key_type *type, const char *desc, - uid_t uid, gid_t gid, struct task_struct *ctx, - key_perm_t perm, unsigned long flags) + uid_t uid, gid_t gid, key_perm_t perm, + int not_in_quota) { struct key_user *user = NULL; struct key *key; @@ -270,14 +269,12 @@ struct key *key_alloc(struct key_type *type, const char *desc, /* check that the user's quota permits allocation of another key and * its description */ - if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { + if (!not_in_quota) { spin_lock(&user->lock); - if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) { - if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || - user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES - ) - goto no_quota; - } + if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || + user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES + ) + goto no_quota; user->qnkeys++; user->qnbytes += quotalen; @@ -311,7 +308,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->payload.data = NULL; key->security = NULL; - if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) + if (!not_in_quota) key->flags |= 1 << KEY_FLAG_IN_QUOTA; memset(&key->type_data, 0, sizeof(key->type_data)); @@ -321,7 +318,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, #endif /* let the security module know about the key */ - ret = security_key_alloc(key, ctx, flags); + ret = security_key_alloc(key); if (ret < 0) goto security_error; @@ -335,7 +332,7 @@ error: security_error: kfree(key->description); kmem_cache_free(key_jar, key); - if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { + if (!not_in_quota) { spin_lock(&user->lock); user->qnkeys--; user->qnbytes -= quotalen; @@ -348,7 +345,7 @@ security_error: no_memory_3: kmem_cache_free(key_jar, key); no_memory_2: - if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { + if (!not_in_quota) { spin_lock(&user->lock); user->qnkeys--; user->qnbytes -= quotalen; @@ -764,7 +761,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, const char *description, const void *payload, size_t plen, - unsigned long flags) + int not_in_quota) { struct key_type *ktype; struct key *keyring, *key = NULL; @@ -825,7 +822,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, /* allocate a new key */ key = key_alloc(ktype, description, current->fsuid, current->fsgid, - current, perm, flags); + perm, not_in_quota); if (IS_ERR(key)) { key_ref = ERR_PTR(PTR_ERR(key)); goto error_3; @@ -910,10 +907,6 @@ void key_revoke(struct key *key) * it */ down_write(&key->sem); set_bit(KEY_FLAG_REVOKED, &key->flags); - - if (key->type->revoke) - key->type->revoke(key); - up_write(&key->sem); } /* end key_revoke() */ @@ -989,7 +982,7 @@ void unregister_key_type(struct key_type *ktype) if (key->type == ktype) { if (ktype->destroy) ktype->destroy(key); - memset(&key->payload, KEY_DESTROY, sizeof(key->payload)); + memset(&key->payload, 0xbd, sizeof(key->payload)); } }