documentation: convert the Documentation directory to UTF-8
[sfrench/cifs-2.6.git] / security / keys / process_keys.c
index 217a0bef3c82b341db5c07d414b7385a8f4a00fb..b6f86808475a0aedfb28e9d677fda7db553f006b 100644 (file)
@@ -27,7 +27,7 @@ static DEFINE_MUTEX(key_session_mutex);
 struct key_user root_key_user = {
        .usage          = ATOMIC_INIT(3),
        .consq          = LIST_HEAD_INIT(root_key_user.consq),
-       .lock           = SPIN_LOCK_UNLOCKED,
+       .lock           = __SPIN_LOCK_UNLOCKED(root_key_user.lock),
        .nkeys          = ATOMIC_INIT(2),
        .nikeys         = ATOMIC_INIT(2),
        .uid            = 0,
@@ -67,7 +67,8 @@ struct key root_session_keyring = {
 /*
  * allocate the keyrings to be associated with a UID
  */
-int alloc_uid_keyring(struct user_struct *user)
+int alloc_uid_keyring(struct user_struct *user,
+                     struct task_struct *ctx)
 {
        struct key *uid_keyring, *session_keyring;
        char buf[20];
@@ -76,7 +77,8 @@ int alloc_uid_keyring(struct user_struct *user)
        /* concoct a default session keyring */
        sprintf(buf, "_uid_ses.%u", user->uid);
 
-       session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, NULL);
+       session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
+                                       KEY_ALLOC_IN_QUOTA, NULL);
        if (IS_ERR(session_keyring)) {
                ret = PTR_ERR(session_keyring);
                goto error;
@@ -86,8 +88,8 @@ int alloc_uid_keyring(struct user_struct *user)
         * keyring */
        sprintf(buf, "_uid.%u", user->uid);
 
-       uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0,
-                                   session_keyring);
+       uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
+                                   KEY_ALLOC_IN_QUOTA, session_keyring);
        if (IS_ERR(uid_keyring)) {
                key_put(session_keyring);
                ret = PTR_ERR(uid_keyring);
@@ -143,7 +145,8 @@ int install_thread_keyring(struct task_struct *tsk)
 
        sprintf(buf, "_tid.%u", tsk->pid);
 
-       keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
+       keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+                               KEY_ALLOC_QUOTA_OVERRUN, NULL);
        if (IS_ERR(keyring)) {
                ret = PTR_ERR(keyring);
                goto error;
@@ -177,7 +180,8 @@ int install_process_keyring(struct task_struct *tsk)
        if (!tsk->signal->process_keyring) {
                sprintf(buf, "_pid.%u", tsk->tgid);
 
-               keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
+               keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+                                       KEY_ALLOC_QUOTA_OVERRUN, NULL);
                if (IS_ERR(keyring)) {
                        ret = PTR_ERR(keyring);
                        goto error;
@@ -208,6 +212,7 @@ error:
 static int install_session_keyring(struct task_struct *tsk,
                                   struct key *keyring)
 {
+       unsigned long flags;
        struct key *old;
        char buf[20];
 
@@ -217,7 +222,12 @@ static int install_session_keyring(struct task_struct *tsk,
        if (!keyring) {
                sprintf(buf, "_ses.%u", tsk->tgid);
 
-               keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
+               flags = KEY_ALLOC_QUOTA_OVERRUN;
+               if (tsk->signal->session_keyring)
+                       flags = KEY_ALLOC_IN_QUOTA;
+
+               keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+                                       flags, NULL);
                if (IS_ERR(keyring))
                        return PTR_ERR(keyring);
        }
@@ -390,6 +400,8 @@ key_ref_t search_process_keyrings(struct key_type *type,
        struct request_key_auth *rka;
        key_ref_t key_ref, ret, err;
 
+       might_sleep();
+
        /* 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;
         * otherwise we want to return a sample error (probably -EACCES) if
@@ -495,27 +507,35 @@ key_ref_t search_process_keyrings(struct key_type *type,
         */
        if (context->request_key_auth &&
            context == current &&
-           type != &key_type_request_key_auth &&
-           key_validate(context->request_key_auth) == 0
+           type != &key_type_request_key_auth
            ) {
-               rka = context->request_key_auth->payload.data;
+               /* defend against the auth key being revoked */
+               down_read(&context->request_key_auth->sem);
 
-               key_ref = search_process_keyrings(type, description, match,
-                                                 rka->context);
+               if (key_validate(context->request_key_auth) == 0) {
+                       rka = context->request_key_auth->payload.data;
 
-               if (!IS_ERR(key_ref))
-                       goto found;
+                       key_ref = search_process_keyrings(type, description,
+                                                         match, rka->context);
 
-               switch (PTR_ERR(key_ref)) {
-               case -EAGAIN: /* no key */
-                       if (ret)
+                       up_read(&context->request_key_auth->sem);
+
+                       if (!IS_ERR(key_ref))
+                               goto found;
+
+                       switch (PTR_ERR(key_ref)) {
+                       case -EAGAIN: /* no key */
+                               if (ret)
+                                       break;
+                       case -ENOKEY: /* negative key */
+                               ret = key_ref;
                                break;
-               case -ENOKEY: /* negative key */
-                       ret = key_ref;
-                       break;
-               default:
-                       err = key_ref;
-                       break;
+                       default:
+                               err = key_ref;
+                               break;
+                       }
+               } else {
+                       up_read(&context->request_key_auth->sem);
                }
        }
 
@@ -717,7 +737,8 @@ long join_session_keyring(const char *name)
        keyring = find_keyring_by_name(name, 0);
        if (PTR_ERR(keyring) == -ENOKEY) {
                /* not found - try and create a new one */
-               keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL);
+               keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk,
+                                       KEY_ALLOC_IN_QUOTA, NULL);
                if (IS_ERR(keyring)) {
                        ret = PTR_ERR(keyring);
                        goto error2;