Merge branch 'for-v3.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/paulg...
[linux-flexiantxendom0-3.2.10.git] / kernel / cred.c
index 3a9d6dd..e70683d 100644 (file)
@@ -1,4 +1,4 @@
-/* Task credentials management - see Documentation/credentials.txt
+/* Task credentials management - see Documentation/security/credentials.txt
  *
  * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
@@ -8,7 +8,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the Licence, or (at your option) any later version.
  */
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/cred.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
@@ -16,6 +16,7 @@
 #include <linux/keyctl.h>
 #include <linux/init_task.h>
 #include <linux/security.h>
+#include <linux/binfmts.h>
 #include <linux/cn_proc.h>
 
 #if 0
@@ -35,7 +36,7 @@ static struct kmem_cache *cred_jar;
 static struct thread_group_cred init_tgcred = {
        .usage  = ATOMIC_INIT(2),
        .tgid   = 0,
-       .lock   = SPIN_LOCK_UNLOCKED,
+       .lock   = __SPIN_LOCK_UNLOCKED(init_cred.tgcred.lock),
 };
 #endif
 
@@ -49,11 +50,12 @@ struct cred init_cred = {
        .magic                  = CRED_MAGIC,
 #endif
        .securebits             = SECUREBITS_DEFAULT,
-       .cap_inheritable        = CAP_INIT_INH_SET,
+       .cap_inheritable        = CAP_EMPTY_SET,
        .cap_permitted          = CAP_FULL_SET,
-       .cap_effective          = CAP_INIT_EFF_SET,
-       .cap_bset               = CAP_INIT_BSET,
+       .cap_effective          = CAP_FULL_SET,
+       .cap_bset               = CAP_FULL_SET,
        .user                   = INIT_USER,
+       .user_ns                = &init_user_ns,
        .group_info             = &init_groups,
 #ifdef CONFIG_KEYS
        .tgcred                 = &init_tgcred,
@@ -384,6 +386,8 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
        struct cred *new;
        int ret;
 
+       p->replacement_session_keyring = NULL;
+
        if (
 #ifdef CONFIG_KEYS
                !p->cred->thread_keyring &&
@@ -410,6 +414,11 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
                        goto error_put;
        }
 
+       /* cache user_ns in cred.  Doesn't need a refcount because it will
+        * stay pinned by cred->user
+        */
+       new->user_ns = new->user->user_ns;
+
 #ifdef CONFIG_KEYS
        /* new threads get their own thread keyrings if their parent already
         * had one */
@@ -502,10 +511,8 @@ int commit_creds(struct cred *new)
                key_fsgid_changed(task);
 
        /* do it
-        * - What if a process setreuid()'s and this brings the
-        *   new uid over his NPROC rlimit?  We can check this now
-        *   cheaply with the new uid cache, so if it matters
-        *   we should be checking for it.  -DaveM
+        * RLIMIT_NPROC limits on user->processes have already been checked
+        * in set_user().
         */
        alter_cred_subscribers(new, 2);
        if (new->user != old->user)
@@ -640,6 +647,9 @@ void __init cred_init(void)
  */
 struct cred *prepare_kernel_cred(struct task_struct *daemon)
 {
+#ifdef CONFIG_KEYS
+       struct thread_group_cred *tgcred;
+#endif
        const struct cred *old;
        struct cred *new;
 
@@ -647,6 +657,14 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
        if (!new)
                return NULL;
 
+#ifdef CONFIG_KEYS
+       tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
+       if (!tgcred) {
+               kmem_cache_free(cred_jar, new);
+               return NULL;
+       }
+#endif
+
        kdebug("prepare_kernel_cred() alloc %p", new);
 
        if (daemon)
@@ -663,8 +681,11 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
        get_group_info(new->group_info);
 
 #ifdef CONFIG_KEYS
-       atomic_inc(&init_tgcred.usage);
-       new->tgcred = &init_tgcred;
+       atomic_set(&tgcred->usage, 1);
+       spin_lock_init(&tgcred->lock);
+       tgcred->process_keyring = NULL;
+       tgcred->session_keyring = NULL;
+       new->tgcred = tgcred;
        new->request_key_auth = NULL;
        new->thread_keyring = NULL;
        new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;