]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - security/keys/key.c
fat: ->i_pos race fix
[linux-2.6-omap-h63xx.git] / security / keys / key.c
index 654d23baf3525ceee6134f75039a4d450fc1edd9..14948cf83ef6acc6ea19811465201ff5ae8660f0 100644 (file)
@@ -1,6 +1,6 @@
 /* Basic authentication token and access key management
  *
- * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-2008 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -27,6 +27,11 @@ DEFINE_SPINLOCK(key_serial_lock);
 struct rb_root key_user_tree; /* tree of quota records indexed by UID */
 DEFINE_SPINLOCK(key_user_lock);
 
+unsigned int key_quota_root_maxkeys = 200;     /* root's key count quota */
+unsigned int key_quota_root_maxbytes = 20000;  /* root's key space quota */
+unsigned int key_quota_maxkeys = 200;          /* general key count quota */
+unsigned int key_quota_maxbytes = 20000;       /* general key space quota */
+
 static LIST_HEAD(key_types_list);
 static DECLARE_RWSEM(key_types_sem);
 
@@ -137,36 +142,6 @@ void key_user_put(struct key_user *user)
 
 } /* end key_user_put() */
 
-/*****************************************************************************/
-/*
- * insert a key with a fixed serial number
- */
-static void __init __key_insert_serial(struct key *key)
-{
-       struct rb_node *parent, **p;
-       struct key *xkey;
-
-       parent = NULL;
-       p = &key_serial_tree.rb_node;
-
-       while (*p) {
-               parent = *p;
-               xkey = rb_entry(parent, struct key, serial_node);
-
-               if (key->serial < xkey->serial)
-                       p = &(*p)->rb_left;
-               else if (key->serial > xkey->serial)
-                       p = &(*p)->rb_right;
-               else
-                       BUG();
-       }
-
-       /* we've found a suitable hole - arrange for this key to occupy it */
-       rb_link_node(&key->serial_node, parent, p);
-       rb_insert_color(&key->serial_node, &key_serial_tree);
-
-} /* end __key_insert_serial() */
-
 /*****************************************************************************/
 /*
  * assign a key the next unique serial number
@@ -266,11 +241,16 @@ 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)) {
+               unsigned maxkeys = (uid == 0) ?
+                       key_quota_root_maxkeys : key_quota_maxkeys;
+               unsigned maxbytes = (uid == 0) ?
+                       key_quota_root_maxbytes : key_quota_maxbytes;
+
                spin_lock(&user->lock);
                if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
-                       if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
-                           user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
-                           )
+                       if (user->qnkeys + 1 >= maxkeys ||
+                           user->qnbytes + quotalen >= maxbytes ||
+                           user->qnbytes + quotalen < user->qnbytes)
                                goto no_quota;
                }
 
@@ -375,11 +355,14 @@ int key_payload_reserve(struct key *key, size_t datalen)
 
        /* contemplate the quota adjustment */
        if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
+               unsigned maxbytes = (key->user->uid == 0) ?
+                       key_quota_root_maxbytes : key_quota_maxbytes;
+
                spin_lock(&key->user->lock);
 
                if (delta > 0 &&
-                   key->user->qnbytes + delta > KEYQUOTA_MAX_BYTES
-                   ) {
+                   (key->user->qnbytes + delta >= maxbytes ||
+                    key->user->qnbytes + delta < key->user->qnbytes)) {
                        ret = -EDQUOT;
                }
                else {
@@ -757,11 +740,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
                               const char *description,
                               const void *payload,
                               size_t plen,
+                              key_perm_t perm,
                               unsigned long flags)
 {
        struct key_type *ktype;
        struct key *keyring, *key = NULL;
-       key_perm_t perm;
        key_ref_t key_ref;
        int ret;
 
@@ -806,15 +789,17 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
                        goto found_matching_key;
        }
 
-       /* decide on the permissions we want */
-       perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
-       perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
+       /* if the client doesn't provide, decide on the permissions we want */
+       if (perm == KEY_PERM_UNDEF) {
+               perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
+               perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
 
-       if (ktype->read)
-               perm |= KEY_POS_READ | KEY_USR_READ;
+               if (ktype->read)
+                       perm |= KEY_POS_READ | KEY_USR_READ;
 
-       if (ktype == &key_type_keyring || ktype->update)
-               perm |= KEY_USR_WRITE;
+               if (ktype == &key_type_keyring || ktype->update)
+                       perm |= KEY_USR_WRITE;
+       }
 
        /* allocate a new key */
        key = key_alloc(ktype, description, current->fsuid, current->fsgid,
@@ -1018,17 +1003,4 @@ void __init key_init(void)
        rb_insert_color(&root_key_user.node,
                        &key_user_tree);
 
-       /* record root's user standard keyrings */
-       key_check(&root_user_keyring);
-       key_check(&root_session_keyring);
-
-       __key_insert_serial(&root_user_keyring);
-       __key_insert_serial(&root_session_keyring);
-
-       keyring_publish_name(&root_user_keyring);
-       keyring_publish_name(&root_session_keyring);
-
-       /* link the two root keyrings together */
-       key_link(&root_session_keyring, &root_user_keyring);
-
 } /* end key_init() */