[PATCH] selinux: add hooks for key subsystem
[safe/jmp/linux-2.6] / security / keys / key.c
index 99781b7..14a15ab 100644 (file)
@@ -1,6 +1,6 @@
 /* key.c: basic authentication token and access key management
  *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -211,12 +211,12 @@ static inline void key_alloc_serial(struct key *key)
                        key->serial = 2;
                key_serial_next = key->serial + 1;
 
-               if (!parent->rb_parent)
+               if (!rb_parent(parent))
                        p = &key_serial_tree.rb_node;
-               else if (parent->rb_parent->rb_left == parent)
-                       p = &parent->rb_parent->rb_left;
+               else if (rb_parent(parent)->rb_left == parent)
+                       p = &(rb_parent(parent)->rb_left);
                else
-                       p = &parent->rb_parent->rb_right;
+                       p = &(rb_parent(parent)->rb_right);
 
                parent = rb_next(parent);
                if (!parent)
@@ -247,8 +247,8 @@ static inline void key_alloc_serial(struct key *key)
  *   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, key_perm_t perm,
-                     int not_in_quota)
+                     uid_t uid, gid_t gid, struct task_struct *ctx,
+                     key_perm_t perm, int not_in_quota)
 {
        struct key_user *user = NULL;
        struct key *key;
@@ -271,7 +271,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
         * its description */
        if (!not_in_quota) {
                spin_lock(&user->lock);
-               if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS &&
+               if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
                    user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
                    )
                        goto no_quota;
@@ -318,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);
+       ret = security_key_alloc(key, ctx);
        if (ret < 0)
                goto security_error;
 
@@ -785,6 +785,10 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 
        key_check(keyring);
 
+       key_ref = ERR_PTR(-ENOTDIR);
+       if (keyring->type != &key_type_keyring)
+               goto error_2;
+
        down_write(&keyring->sem);
 
        /* if we're going to allocate a new key, we're going to have
@@ -795,12 +799,16 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
                goto error_3;
        }
 
-       /* search for an existing key of the same type and description in the
-        * destination keyring
+       /* if it's possible to update this type of key, search for an existing
+        * key of the same type and description in the destination keyring and
+        * update that instead if possible
         */
-       key_ref = __keyring_search_one(keyring_ref, ktype, description, 0);
-       if (!IS_ERR(key_ref))
-               goto found_matching_key;
+       if (ktype->update) {
+               key_ref = __keyring_search_one(keyring_ref, ktype, description,
+                                              0);
+               if (!IS_ERR(key_ref))
+                       goto found_matching_key;
+       }
 
        /* decide on the permissions we want */
        perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
@@ -814,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,
-                       perm, not_in_quota);
+                       current, perm, not_in_quota);
        if (IS_ERR(key)) {
                key_ref = ERR_PTR(PTR_ERR(key));
                goto error_3;