CRED: Make execve() take advantage of copy-on-write credentials
[safe/jmp/linux-2.6] / kernel / cred.c
index cb6b5ed..e6fcdd6 100644 (file)
@@ -68,7 +68,7 @@ static void release_tgcred_rcu(struct rcu_head *rcu)
 /*
  * Release a set of thread group credentials.
  */
-void release_tgcred(struct cred *cred)
+static void release_tgcred(struct cred *cred)
 {
 #ifdef CONFIG_KEYS
        struct thread_group_cred *tgcred = cred->tgcred;
@@ -164,6 +164,50 @@ error:
 EXPORT_SYMBOL(prepare_creds);
 
 /*
+ * Prepare credentials for current to perform an execve()
+ * - The caller must hold current->cred_exec_mutex
+ */
+struct cred *prepare_exec_creds(void)
+{
+       struct thread_group_cred *tgcred = NULL;
+       struct cred *new;
+
+#ifdef CONFIG_KEYS
+       tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
+       if (!tgcred)
+               return NULL;
+#endif
+
+       new = prepare_creds();
+       if (!new) {
+               kfree(tgcred);
+               return new;
+       }
+
+#ifdef CONFIG_KEYS
+       /* newly exec'd tasks don't get a thread keyring */
+       key_put(new->thread_keyring);
+       new->thread_keyring = NULL;
+
+       /* create a new per-thread-group creds for all this set of threads to
+        * share */
+       memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred));
+
+       atomic_set(&tgcred->usage, 1);
+       spin_lock_init(&tgcred->lock);
+
+       /* inherit the session keyring; new process keyring */
+       key_get(tgcred->session_keyring);
+       tgcred->process_keyring = NULL;
+
+       release_tgcred(new);
+       new->tgcred = tgcred;
+#endif
+
+       return new;
+}
+
+/*
  * prepare new credentials for the usermode helper dispatcher
  */
 struct cred *prepare_usermodehelper_creds(void)