aboutsummaryrefslogtreecommitdiffstats
path: root/security/capability.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-09-02 04:14:21 -0400
committerJames Morris <jmorris@namei.org>2009-09-02 07:29:22 -0400
commitee18d64c1f632043a02e6f5ba5e045bb26a5465f (patch)
tree80b5a4d530ec7d5fd69799920f0db7b78aba6b9d /security/capability.c
parentd0420c83f39f79afb82010c2d2cafd150eef651b (diff)
KEYS: Add a keyctl to install a process's session keyring on its parent [try #6]
Add a keyctl to install a process's session keyring onto its parent. This replaces the parent's session keyring. Because the COW credential code does not permit one process to change another process's credentials directly, the change is deferred until userspace next starts executing again. Normally this will be after a wait*() syscall. To support this, three new security hooks have been provided: cred_alloc_blank() to allocate unset security creds, cred_transfer() to fill in the blank security creds and key_session_to_parent() - which asks the LSM if the process may replace its parent's session keyring. The replacement may only happen if the process has the same ownership details as its parent, and the process has LINK permission on the session keyring, and the session keyring is owned by the process, and the LSM permits it. Note that this requires alteration to each architecture's notify_resume path. This has been done for all arches barring blackfin, m68k* and xtensa, all of which need assembly alteration to support TIF_NOTIFY_RESUME. This allows the replacement to be performed at the point the parent process resumes userspace execution. This allows the userspace AFS pioctl emulation to fully emulate newpag() and the VIOCSETTOK and VIOCSETTOK2 pioctls, all of which require the ability to alter the parent process's PAG membership. However, since kAFS doesn't use PAGs per se, but rather dumps the keys into the session keyring, the session keyring of the parent must be replaced if, for example, VIOCSETTOK is passed the newpag flag. This can be tested with the following program: #include <stdio.h> #include <stdlib.h> #include <keyutils.h> #define KEYCTL_SESSION_TO_PARENT 18 #define OSERROR(X, S) do { if ((long)(X) == -1) { perror(S); exit(1); } } while(0) int main(int argc, char **argv) { key_serial_t keyring, key; long ret; keyring = keyctl_join_session_keyring(argv[1]); OSERROR(keyring, "keyctl_join_session_keyring"); key = add_key("user", "a", "b", 1, keyring); OSERROR(key, "add_key"); ret = keyctl(KEYCTL_SESSION_TO_PARENT); OSERROR(ret, "KEYCTL_SESSION_TO_PARENT"); return 0; } Compiled and linked with -lkeyutils, you should see something like: [dhowells@andromeda ~]$ keyctl show Session Keyring -3 --alswrv 4043 4043 keyring: _ses 355907932 --alswrv 4043 -1 \_ keyring: _uid.4043 [dhowells@andromeda ~]$ /tmp/newpag [dhowells@andromeda ~]$ keyctl show Session Keyring -3 --alswrv 4043 4043 keyring: _ses 1055658746 --alswrv 4043 4043 \_ user: a [dhowells@andromeda ~]$ /tmp/newpag hello [dhowells@andromeda ~]$ keyctl show Session Keyring -3 --alswrv 4043 4043 keyring: hello 340417692 --alswrv 4043 4043 \_ user: a Where the test program creates a new session keyring, sticks a user key named 'a' into it and then installs it on its parent. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/capability.c')
-rw-r--r--security/capability.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/security/capability.c b/security/capability.c
index 06400cf07757..93a2ffe65905 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -373,6 +373,11 @@ static int cap_task_create(unsigned long clone_flags)
373 return 0; 373 return 0;
374} 374}
375 375
376static int cap_cred_alloc_blank(struct cred *cred, gfp_t gfp)
377{
378 return 0;
379}
380
376static void cap_cred_free(struct cred *cred) 381static void cap_cred_free(struct cred *cred)
377{ 382{
378} 383}
@@ -386,6 +391,10 @@ static void cap_cred_commit(struct cred *new, const struct cred *old)
386{ 391{
387} 392}
388 393
394static void cap_cred_transfer(struct cred *new, const struct cred *old)
395{
396}
397
389static int cap_kernel_act_as(struct cred *new, u32 secid) 398static int cap_kernel_act_as(struct cred *new, u32 secid)
390{ 399{
391 return 0; 400 return 0;
@@ -836,6 +845,13 @@ static int cap_key_getsecurity(struct key *key, char **_buffer)
836 return 0; 845 return 0;
837} 846}
838 847
848static int cap_key_session_to_parent(const struct cred *cred,
849 const struct cred *parent_cred,
850 struct key *key)
851{
852 return 0;
853}
854
839#endif /* CONFIG_KEYS */ 855#endif /* CONFIG_KEYS */
840 856
841#ifdef CONFIG_AUDIT 857#ifdef CONFIG_AUDIT
@@ -961,9 +977,11 @@ void security_fixup_ops(struct security_operations *ops)
961 set_to_cap_if_null(ops, file_receive); 977 set_to_cap_if_null(ops, file_receive);
962 set_to_cap_if_null(ops, dentry_open); 978 set_to_cap_if_null(ops, dentry_open);
963 set_to_cap_if_null(ops, task_create); 979 set_to_cap_if_null(ops, task_create);
980 set_to_cap_if_null(ops, cred_alloc_blank);
964 set_to_cap_if_null(ops, cred_free); 981 set_to_cap_if_null(ops, cred_free);
965 set_to_cap_if_null(ops, cred_prepare); 982 set_to_cap_if_null(ops, cred_prepare);
966 set_to_cap_if_null(ops, cred_commit); 983 set_to_cap_if_null(ops, cred_commit);
984 set_to_cap_if_null(ops, cred_transfer);
967 set_to_cap_if_null(ops, kernel_act_as); 985 set_to_cap_if_null(ops, kernel_act_as);
968 set_to_cap_if_null(ops, kernel_create_files_as); 986 set_to_cap_if_null(ops, kernel_create_files_as);
969 set_to_cap_if_null(ops, kernel_module_request); 987 set_to_cap_if_null(ops, kernel_module_request);
@@ -1063,6 +1081,7 @@ void security_fixup_ops(struct security_operations *ops)
1063 set_to_cap_if_null(ops, key_free); 1081 set_to_cap_if_null(ops, key_free);
1064 set_to_cap_if_null(ops, key_permission); 1082 set_to_cap_if_null(ops, key_permission);
1065 set_to_cap_if_null(ops, key_getsecurity); 1083 set_to_cap_if_null(ops, key_getsecurity);
1084 set_to_cap_if_null(ops, key_session_to_parent);
1066#endif /* CONFIG_KEYS */ 1085#endif /* CONFIG_KEYS */
1067#ifdef CONFIG_AUDIT 1086#ifdef CONFIG_AUDIT
1068 set_to_cap_if_null(ops, audit_rule_init); 1087 set_to_cap_if_null(ops, audit_rule_init);