kconfig: fix default value for choice input
[pandora-kernel.git] / security / keys / process_keys.c
index 566b1cc..f694061 100644 (file)
 #include <linux/keyctl.h>
 #include <linux/fs.h>
 #include <linux/err.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
 /* session keyring create vs join semaphore */
-static DECLARE_MUTEX(key_session_sem);
+static DEFINE_MUTEX(key_session_mutex);
 
 /* the root user's tracking struct */
 struct key_user root_key_user = {
@@ -270,9 +271,14 @@ int copy_thread_group_keys(struct task_struct *tsk)
 int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
 {
        key_check(tsk->thread_keyring);
+       key_check(tsk->request_key_auth);
 
        /* no thread keyring yet */
        tsk->thread_keyring = NULL;
+
+       /* copy the request_key() authorisation for this thread */
+       key_get(tsk->request_key_auth);
+
        return 0;
 
 } /* end copy_keys() */
@@ -290,11 +296,12 @@ void exit_thread_group_keys(struct signal_struct *tg)
 
 /*****************************************************************************/
 /*
- * dispose of keys upon thread exit
+ * dispose of per-thread keys upon thread exit
  */
 void exit_keys(struct task_struct *tsk)
 {
        key_put(tsk->thread_keyring);
+       key_put(tsk->request_key_auth);
 
 } /* end exit_keys() */
 
@@ -382,7 +389,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
                                  struct task_struct *context)
 {
        struct request_key_auth *rka;
-       key_ref_t key_ref, ret, err, instkey_ref;
+       key_ref_t key_ref, ret, err;
 
        /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
         * searchable, but we failed to find a key or we found a negative key;
@@ -461,30 +468,12 @@ key_ref_t search_process_keyrings(struct key_type *type,
                        err = key_ref;
                        break;
                }
-
-               /* if this process has a session keyring and that has an
-                * instantiation authorisation key in the bottom level, then we
-                * also search the keyrings of the process mentioned there */
-               if (context != current)
-                       goto no_key;
-
-               rcu_read_lock();
-               instkey_ref = __keyring_search_one(
-                       make_key_ref(rcu_dereference(
-                                            context->signal->session_keyring),
-                                    1),
-                       &key_type_request_key_auth, NULL, 0);
-               rcu_read_unlock();
-
-               if (IS_ERR(instkey_ref))
-                       goto no_key;
-
-               rka = key_ref_to_ptr(instkey_ref)->payload.data;
-
-               key_ref = search_process_keyrings(type, description, match,
-                                                 rka->context);
-               key_ref_put(instkey_ref);
-
+       }
+       /* or search the user-session keyring */
+       else {
+               key_ref = keyring_search_aux(
+                       make_key_ref(context->user->session_keyring, 1),
+                       context, type, description, match);
                if (!IS_ERR(key_ref))
                        goto found;
 
@@ -500,11 +489,21 @@ key_ref_t search_process_keyrings(struct key_type *type,
                        break;
                }
        }
-       /* or search the user-session keyring */
-       else {
-               key_ref = keyring_search_aux(
-                       make_key_ref(context->user->session_keyring, 1),
-                       context, type, description, match);
+
+       /* if this process has an instantiation authorisation key, then we also
+        * search the keyrings of the process mentioned there
+        * - we don't permit access to request_key auth keys via this method
+        */
+       if (context->request_key_auth &&
+           context == current &&
+           type != &key_type_request_key_auth &&
+           key_validate(context->request_key_auth) == 0
+           ) {
+               rka = context->request_key_auth->payload.data;
+
+               key_ref = search_process_keyrings(type, description, match,
+                                                 rka->context);
+
                if (!IS_ERR(key_ref))
                        goto found;
 
@@ -521,8 +520,6 @@ key_ref_t search_process_keyrings(struct key_type *type,
                }
        }
 
-
-no_key:
        /* no key - decide on the error we're going to go for */
        key_ref = ret ? ret : err;
 
@@ -628,6 +625,15 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
                key = ERR_PTR(-EINVAL);
                goto error;
 
+       case KEY_SPEC_REQKEY_AUTH_KEY:
+               key = context->request_key_auth;
+               if (!key)
+                       goto error;
+
+               atomic_inc(&key->usage);
+               key_ref = make_key_ref(key, 1);
+               break;
+
        default:
                key_ref = ERR_PTR(-EINVAL);
                if (id < 1)
@@ -706,7 +712,7 @@ long join_session_keyring(const char *name)
        }
 
        /* allow the user to join or create a named keyring */
-       down(&key_session_sem);
+       mutex_lock(&key_session_mutex);
 
        /* look for an existing keyring of this name */
        keyring = find_keyring_by_name(name, 0);
@@ -732,7 +738,7 @@ long join_session_keyring(const char *name)
        key_put(keyring);
 
 error2:
-       up(&key_session_sem);
+       mutex_unlock(&key_session_mutex);
 error:
        return ret;