keys: allow clients to set key perms in key_create_or_update()
Arun Raghavan [Tue, 29 Apr 2008 08:01:28 +0000 (01:01 -0700)]
The key_create_or_update() function provided by the keyring code has a default
set of permissions that are always applied to the key when created.  This
might not be desirable to all clients.

Here's a patch that adds a "perm" parameter to the function to address this,
which can be set to KEY_PERM_UNDEF to revert to the current behaviour.

Signed-off-by: Arun Raghavan <arunsr@cse.iitk.ac.in>
Signed-off-by: David Howells <dhowells@redhat.com>
Cc: Satyam Sharma <ssatyam@cse.iitk.ac.in>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

include/linux/key.h
security/keys/key.c
security/keys/keyctl.c

index 163f864..8b0bd33 100644 (file)
@@ -67,6 +67,8 @@ struct key;
 #define KEY_OTH_SETATTR        0x00000020
 #define KEY_OTH_ALL    0x0000003f
 
+#define KEY_PERM_UNDEF 0xffffffff
+
 struct seq_file;
 struct user_struct;
 struct signal_struct;
@@ -232,6 +234,7 @@ extern key_ref_t key_create_or_update(key_ref_t keyring,
                                      const char *description,
                                      const void *payload,
                                      size_t plen,
+                                     key_perm_t perm,
                                      unsigned long flags);
 
 extern int key_update(key_ref_t key,
index 654d23b..d98c619 100644 (file)
@@ -757,11 +757,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 +806,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,
index 56e963b..993be63 100644 (file)
@@ -112,7 +112,8 @@ asmlinkage long sys_add_key(const char __user *_type,
        /* create or update the requested key and add it to the target
         * keyring */
        key_ref = key_create_or_update(keyring_ref, type, description,
-                                      payload, plen, KEY_ALLOC_IN_QUOTA);
+                                      payload, plen, KEY_PERM_UNDEF,
+                                      KEY_ALLOC_IN_QUOTA);
        if (!IS_ERR(key_ref)) {
                ret = key_ref_to_ptr(key_ref)->serial;
                key_ref_put(key_ref);