summaryrefslogtreecommitdiff
path: root/security/keys/process_keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r--security/keys/process_keys.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 4739cfbb41b7..5c23afb31ece 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -17,6 +17,7 @@
#include <linux/fs.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/security.h>
#include <linux/user_namespace.h>
#include <asm/uaccess.h>
#include "internal.h"
@@ -768,3 +769,51 @@ error:
abort_creds(new);
return ret;
}
+
+/*
+ * Replace a process's session keyring when that process resumes userspace on
+ * behalf of one of its children
+ */
+void key_replace_session_keyring(void)
+{
+ const struct cred *old;
+ struct cred *new;
+
+ if (!current->replacement_session_keyring)
+ return;
+
+ write_lock_irq(&tasklist_lock);
+ new = current->replacement_session_keyring;
+ current->replacement_session_keyring = NULL;
+ write_unlock_irq(&tasklist_lock);
+
+ if (!new)
+ return;
+
+ old = current_cred();
+ new-> uid = old-> uid;
+ new-> euid = old-> euid;
+ new-> suid = old-> suid;
+ new->fsuid = old->fsuid;
+ new-> gid = old-> gid;
+ new-> egid = old-> egid;
+ new-> sgid = old-> sgid;
+ new->fsgid = old->fsgid;
+ new->user = get_uid(old->user);
+ new->group_info = get_group_info(old->group_info);
+
+ new->securebits = old->securebits;
+ new->cap_inheritable = old->cap_inheritable;
+ new->cap_permitted = old->cap_permitted;
+ new->cap_effective = old->cap_effective;
+ new->cap_bset = old->cap_bset;
+
+ new->jit_keyring = old->jit_keyring;
+ new->thread_keyring = key_get(old->thread_keyring);
+ new->tgcred->tgid = old->tgcred->tgid;
+ new->tgcred->process_keyring = key_get(old->tgcred->process_keyring);
+
+ security_transfer_creds(new, old);
+
+ commit_creds(new);
+}