Merge branch 'master' into for-2.6.35
[safe/jmp/linux-2.6] / security / keys / request_key.c
index 0488b0a..d737cea 100644 (file)
@@ -66,10 +66,10 @@ static int call_sbin_request_key(struct key_construction *cons,
                                 const char *op,
                                 void *aux)
 {
-       struct task_struct *tsk = current;
        const struct cred *cred = current_cred();
        key_serial_t prkey, sskey;
-       struct key *key = cons->key, *authkey = cons->authkey, *keyring;
+       struct key *key = cons->key, *authkey = cons->authkey, *keyring,
+               *session;
        char *argv[9], *envp[3], uid_str[12], gid_str[12];
        char key_str[12], keyring_str[3][12];
        char desc[20];
@@ -84,8 +84,10 @@ static int call_sbin_request_key(struct key_construction *cons,
        /* allocate a new session keyring */
        sprintf(desc, "_req.%u", key->serial);
 
-       keyring = keyring_alloc(desc, current_fsuid(), current_fsgid(), current,
+       cred = get_current_cred();
+       keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred,
                                KEY_ALLOC_QUOTA_OVERRUN, NULL);
+       put_cred(cred);
        if (IS_ERR(keyring)) {
                ret = PTR_ERR(keyring);
                goto error_alloc;
@@ -105,22 +107,18 @@ static int call_sbin_request_key(struct key_construction *cons,
 
        /* we specify the process's default keyrings */
        sprintf(keyring_str[0], "%d",
-               cred->thread_keyring ?
-               cred->thread_keyring->serial : 0);
+               cred->thread_keyring ? cred->thread_keyring->serial : 0);
 
        prkey = 0;
-       if (tsk->signal->process_keyring)
-               prkey = tsk->signal->process_keyring->serial;
+       if (cred->tgcred->process_keyring)
+               prkey = cred->tgcred->process_keyring->serial;
 
-       sprintf(keyring_str[1], "%d", prkey);
-
-       if (tsk->signal->session_keyring) {
-               rcu_read_lock();
-               sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
-               rcu_read_unlock();
-       } else {
-               sskey = cred->user->session_keyring->serial;
-       }
+       rcu_read_lock();
+       session = rcu_dereference(cred->tgcred->session_keyring);
+       if (!session)
+               session = cred->user->session_keyring;
+       sskey = session->serial;
+       rcu_read_unlock();
 
        sprintf(keyring_str[2], "%d", sskey);
 
@@ -161,8 +159,8 @@ error_link:
        key_put(keyring);
 
 error_alloc:
-       kleave(" = %d", ret);
        complete_request_key(cons, ret);
+       kleave(" = %d", ret);
        return ret;
 }
 
@@ -222,7 +220,7 @@ static int construct_key(struct key *key, const void *callout_info,
 static void construct_get_dest_keyring(struct key **_dest_keyring)
 {
        struct request_key_auth *rka;
-       struct task_struct *tsk = current;
+       const struct cred *cred = current_cred();
        struct key *dest_keyring = *_dest_keyring, *authkey;
 
        kenter("%p", dest_keyring);
@@ -234,11 +232,11 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
        } else {
                /* use a default keyring; falling through the cases until we
                 * find one that we actually have */
-               switch (tsk->cred->jit_keyring) {
+               switch (cred->jit_keyring) {
                case KEY_REQKEY_DEFL_DEFAULT:
                case KEY_REQKEY_DEFL_REQUESTOR_KEYRING:
-                       if (tsk->cred->request_key_auth) {
-                               authkey = tsk->cred->request_key_auth;
+                       if (cred->request_key_auth) {
+                               authkey = cred->request_key_auth;
                                down_read(&authkey->sem);
                                rka = authkey->payload.data;
                                if (!test_bit(KEY_FLAG_REVOKED,
@@ -251,19 +249,19 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
                        }
 
                case KEY_REQKEY_DEFL_THREAD_KEYRING:
-                       dest_keyring = key_get(tsk->cred->thread_keyring);
+                       dest_keyring = key_get(cred->thread_keyring);
                        if (dest_keyring)
                                break;
 
                case KEY_REQKEY_DEFL_PROCESS_KEYRING:
-                       dest_keyring = key_get(tsk->signal->process_keyring);
+                       dest_keyring = key_get(cred->tgcred->process_keyring);
                        if (dest_keyring)
                                break;
 
                case KEY_REQKEY_DEFL_SESSION_KEYRING:
                        rcu_read_lock();
                        dest_keyring = key_get(
-                               rcu_dereference(tsk->signal->session_keyring));
+                               rcu_dereference(cred->tgcred->session_keyring));
                        rcu_read_unlock();
 
                        if (dest_keyring)
@@ -271,11 +269,11 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
 
                case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
                        dest_keyring =
-                               key_get(tsk->cred->user->session_keyring);
+                               key_get(cred->user->session_keyring);
                        break;
 
                case KEY_REQKEY_DEFL_USER_KEYRING:
-                       dest_keyring = key_get(tsk->cred->user->uid_keyring);
+                       dest_keyring = key_get(cred->user->uid_keyring);
                        break;
 
                case KEY_REQKEY_DEFL_GROUP_KEYRING:
@@ -301,6 +299,7 @@ static int construct_alloc_key(struct key_type *type,
                               struct key_user *user,
                               struct key **_key)
 {
+       const struct cred *cred = current_cred();
        struct key *key;
        key_ref_t key_ref;
 
@@ -308,30 +307,31 @@ static int construct_alloc_key(struct key_type *type,
 
        mutex_lock(&user->cons_lock);
 
-       key = key_alloc(type, description,
-                       current_fsuid(), current_fsgid(), current, KEY_POS_ALL,
-                       flags);
+       key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred,
+                       KEY_POS_ALL, flags);
        if (IS_ERR(key))
                goto alloc_failed;
 
        set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
 
-       down_write(&dest_keyring->sem);
+       if (dest_keyring)
+               down_write(&dest_keyring->sem);
 
        /* attach the key to the destination keyring under lock, but we do need
         * to do another check just in case someone beat us to it whilst we
         * waited for locks */
        mutex_lock(&key_construction_mutex);
 
-       key_ref = search_process_keyrings(type, description, type->match,
-                                         current);
+       key_ref = search_process_keyrings(type, description, type->match, cred);
        if (!IS_ERR(key_ref))
                goto key_already_present;
 
-       __key_link(dest_keyring, key);
+       if (dest_keyring)
+               __key_link(dest_keyring, key);
 
        mutex_unlock(&key_construction_mutex);
-       up_write(&dest_keyring->sem);
+       if (dest_keyring)
+               up_write(&dest_keyring->sem);
        mutex_unlock(&user->cons_lock);
        *_key = key;
        kleave(" = 0 [%d]", key_serial(key));
@@ -339,8 +339,10 @@ static int construct_alloc_key(struct key_type *type,
 
 key_already_present:
        mutex_unlock(&key_construction_mutex);
-       if (dest_keyring)
+       if (dest_keyring) {
+               __key_link(dest_keyring, key_ref_to_ptr(key_ref));
                up_write(&dest_keyring->sem);
+       }
        mutex_unlock(&user->cons_lock);
        key_put(key);
        *_key = key = key_ref_to_ptr(key_ref);
@@ -369,7 +371,9 @@ static struct key *construct_key_and_link(struct key_type *type,
        struct key *key;
        int ret;
 
-       user = key_user_lookup(current_fsuid());
+       kenter("");
+
+       user = key_user_lookup(current_fsuid(), current_user_ns());
        if (!user)
                return ERR_PTR(-ENOMEM);
 
@@ -382,17 +386,21 @@ static struct key *construct_key_and_link(struct key_type *type,
        if (ret == 0) {
                ret = construct_key(key, callout_info, callout_len, aux,
                                    dest_keyring);
-               if (ret < 0)
+               if (ret < 0) {
+                       kdebug("cons failed");
                        goto construction_failed;
+               }
        }
 
        key_put(dest_keyring);
+       kleave(" = key %d", key_serial(key));
        return key;
 
 construction_failed:
        key_negate_and_link(key, key_negative_timeout, NULL, NULL);
        key_put(key);
        key_put(dest_keyring);
+       kleave(" = %d", ret);
        return ERR_PTR(ret);
 }
 
@@ -411,6 +419,7 @@ struct key *request_key_and_link(struct key_type *type,
                                 struct key *dest_keyring,
                                 unsigned long flags)
 {
+       const struct cred *cred = current_cred();
        struct key *key;
        key_ref_t key_ref;
 
@@ -420,10 +429,15 @@ struct key *request_key_and_link(struct key_type *type,
 
        /* search all the process keyrings for a key */
        key_ref = search_process_keyrings(type, description, type->match,
-                                         current);
+                                         cred);
 
        if (!IS_ERR(key_ref)) {
                key = key_ref_to_ptr(key_ref);
+               if (dest_keyring) {
+                       construct_get_dest_keyring(&dest_keyring);
+                       key_link(dest_keyring, key);
+                       key_put(dest_keyring);
+               }
        } else if (PTR_ERR(key_ref) != -EAGAIN) {
                key = ERR_CAST(key_ref);
        } else  {