From 7e047ef5fe2d52e83020e856b1bf2556a6a2ce98 Mon Sep 17 00:00:00 2001 From: David Howells Date: Mon, 26 Jun 2006 00:24:50 -0700 Subject: [PATCH] keys: sort out key quota system Add the ability for key creation to overrun the user's quota in some circumstances - notably when a session keyring is created and assigned to a process that didn't previously have one. This means it's still possible to log in, should PAM require the creation of a new session keyring, and fix an overburdened key quota. Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 79c16e31c88..13384fef0d6 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -4264,7 +4264,8 @@ static int selinux_setprocattr(struct task_struct *p, #ifdef CONFIG_KEYS -static int selinux_key_alloc(struct key *k, struct task_struct *tsk) +static int selinux_key_alloc(struct key *k, struct task_struct *tsk, + unsigned long flags) { struct task_security_struct *tsec = tsk->security; struct key_security_struct *ksec; @@ -4513,8 +4514,10 @@ static __init int selinux_init(void) #ifdef CONFIG_KEYS /* Add security information to initial keyrings */ - security_key_alloc(&root_user_keyring, current); - security_key_alloc(&root_session_keyring, current); + security_key_alloc(&root_user_keyring, current, + KEY_ALLOC_NOT_IN_QUOTA); + security_key_alloc(&root_session_keyring, current, + KEY_ALLOC_NOT_IN_QUOTA); #endif return 0; -- cgit v1.2.3-70-g09d2 From 4eb582cf1fbd7b9e5f466e3718a59c957e75254e Mon Sep 17 00:00:00 2001 From: Michael LeMay Date: Mon, 26 Jun 2006 00:24:57 -0700 Subject: [PATCH] keys: add a way to store the appropriate context for newly-created keys Add a /proc//attr/keycreate entry that stores the appropriate context for newly-created keys. Modify the selinux_key_alloc hook to make use of the new entry. Update the flask headers to include a new "setkeycreate" permission for processes. Update the flask headers to include a new "create" permission for keys. Use the create permission to restrict which SIDs each task can assign to newly-created keys. Add a new parameter to the security hook "security_key_alloc" to indicate whether it is being invoked by the kernel, or from userspace. If it is being invoked by the kernel, the security hook should never fail. Update the documentation to reflect these changes. Signed-off-by: Michael LeMay Signed-off-by: James Morris Signed-off-by: David Howells Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/keys.txt | 27 ++++++++++++--------- fs/proc/base.c | 6 +++++ security/selinux/hooks.c | 35 +++++++++++++++++++++++----- security/selinux/include/av_perm_to_string.h | 2 ++ security/selinux/include/av_permissions.h | 3 ++- security/selinux/include/objsec.h | 1 + 6 files changed, 56 insertions(+), 18 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/Documentation/keys.txt b/Documentation/keys.txt index 70e83cf664a..61c0fad2fe2 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt @@ -241,25 +241,30 @@ The security class "key" has been added to SELinux so that mandatory access controls can be applied to keys created within various contexts. This support is preliminary, and is likely to change quite significantly in the near future. Currently, all of the basic permissions explained above are provided in SELinux -as well; SE Linux is simply invoked after all basic permission checks have been +as well; SELinux is simply invoked after all basic permission checks have been performed. -Each key is labeled with the same context as the task to which it belongs. -Typically, this is the same task that was running when the key was created. -The default keyrings are handled differently, but in a way that is very -intuitive: +The value of the file /proc/self/attr/keycreate influences the labeling of +newly-created keys. If the contents of that file correspond to an SELinux +security context, then the key will be assigned that context. Otherwise, the +key will be assigned the current context of the task that invoked the key +creation request. Tasks must be granted explicit permission to assign a +particular context to newly-created keys, using the "create" permission in the +key security class. - (*) The user and user session keyrings that are created when the user logs in - are currently labeled with the context of the login manager. - - (*) The keyrings associated with new threads are each labeled with the context - of their associated thread, and both session and process keyrings are - handled similarly. +The default keyrings associated with users will be labeled with the default +context of the user if and only if the login programs have been instrumented to +properly initialize keycreate during the login process. Otherwise, they will +be labeled with the context of the login program itself. Note, however, that the default keyrings associated with the root user are labeled with the default kernel context, since they are created early in the boot process, before root has a chance to log in. +The keyrings associated with new threads are each labeled with the context of +their associated thread, and both session and process keyrings are handled +similarly. + ================ NEW PROCFS FILES diff --git a/fs/proc/base.c b/fs/proc/base.c index 6afff725a8c..c4a1ff371b8 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -121,6 +121,7 @@ enum pid_directory_inos { PROC_TGID_ATTR_PREV, PROC_TGID_ATTR_EXEC, PROC_TGID_ATTR_FSCREATE, + PROC_TGID_ATTR_KEYCREATE, #endif #ifdef CONFIG_AUDITSYSCALL PROC_TGID_LOGINUID, @@ -162,6 +163,7 @@ enum pid_directory_inos { PROC_TID_ATTR_PREV, PROC_TID_ATTR_EXEC, PROC_TID_ATTR_FSCREATE, + PROC_TID_ATTR_KEYCREATE, #endif #ifdef CONFIG_AUDITSYSCALL PROC_TID_LOGINUID, @@ -275,6 +277,7 @@ static struct pid_entry tgid_attr_stuff[] = { E(PROC_TGID_ATTR_PREV, "prev", S_IFREG|S_IRUGO), E(PROC_TGID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), E(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO), + E(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO), {0,0,NULL,0} }; static struct pid_entry tid_attr_stuff[] = { @@ -282,6 +285,7 @@ static struct pid_entry tid_attr_stuff[] = { E(PROC_TID_ATTR_PREV, "prev", S_IFREG|S_IRUGO), E(PROC_TID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), E(PROC_TID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO), + E(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO), {0,0,NULL,0} }; #endif @@ -1801,6 +1805,8 @@ static struct dentry *proc_pident_lookup(struct inode *dir, case PROC_TGID_ATTR_EXEC: case PROC_TID_ATTR_FSCREATE: case PROC_TGID_ATTR_FSCREATE: + case PROC_TID_ATTR_KEYCREATE: + case PROC_TGID_ATTR_KEYCREATE: inode->i_fop = &proc_pid_attr_operations; break; #endif diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 13384fef0d6..0d8b27513bd 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1099,6 +1099,17 @@ static int may_create(struct inode *dir, FILESYSTEM__ASSOCIATE, &ad); } +/* Check whether a task can create a key. */ +static int may_create_key(u32 ksid, + struct task_struct *ctx) +{ + struct task_security_struct *tsec; + + tsec = ctx->security; + + return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL); +} + #define MAY_LINK 0 #define MAY_UNLINK 1 #define MAY_RMDIR 2 @@ -4150,6 +4161,8 @@ static int selinux_getprocattr(struct task_struct *p, sid = tsec->exec_sid; else if (!strcmp(name, "fscreate")) sid = tsec->create_sid; + else if (!strcmp(name, "keycreate")) + sid = tsec->keycreate_sid; else return -EINVAL; @@ -4182,6 +4195,8 @@ static int selinux_setprocattr(struct task_struct *p, error = task_has_perm(current, p, PROCESS__SETEXEC); else if (!strcmp(name, "fscreate")) error = task_has_perm(current, p, PROCESS__SETFSCREATE); + else if (!strcmp(name, "keycreate")) + error = task_has_perm(current, p, PROCESS__SETKEYCREATE); else if (!strcmp(name, "current")) error = task_has_perm(current, p, PROCESS__SETCURRENT); else @@ -4211,7 +4226,12 @@ static int selinux_setprocattr(struct task_struct *p, tsec->exec_sid = sid; else if (!strcmp(name, "fscreate")) tsec->create_sid = sid; - else if (!strcmp(name, "current")) { + else if (!strcmp(name, "keycreate")) { + error = may_create_key(sid, p); + if (error) + return error; + tsec->keycreate_sid = sid; + } else if (!strcmp(name, "current")) { struct av_decision avd; if (sid == 0) @@ -4275,7 +4295,10 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk, return -ENOMEM; ksec->obj = k; - ksec->sid = tsec->sid; + if (tsec->keycreate_sid) + ksec->sid = tsec->keycreate_sid; + else + ksec->sid = tsec->sid; k->security = ksec; return 0; @@ -4514,10 +4537,10 @@ static __init int selinux_init(void) #ifdef CONFIG_KEYS /* Add security information to initial keyrings */ - security_key_alloc(&root_user_keyring, current, - KEY_ALLOC_NOT_IN_QUOTA); - security_key_alloc(&root_session_keyring, current, - KEY_ALLOC_NOT_IN_QUOTA); + selinux_key_alloc(&root_user_keyring, current, + KEY_ALLOC_NOT_IN_QUOTA); + selinux_key_alloc(&root_session_keyring, current, + KEY_ALLOC_NOT_IN_QUOTA); #endif return 0; diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index bc020bde6c8..e777578ccd9 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -72,6 +72,7 @@ S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") + S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate") S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") S_(SECCLASS_MSG, MSG__SEND, "send") S_(SECCLASS_MSG, MSG__RECEIVE, "receive") @@ -248,3 +249,4 @@ S_(SECCLASS_KEY, KEY__SEARCH, "search") S_(SECCLASS_KEY, KEY__LINK, "link") S_(SECCLASS_KEY, KEY__SETATTR, "setattr") + S_(SECCLASS_KEY, KEY__CREATE, "create") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 1205227a3a3..1e1678023b6 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -467,6 +467,7 @@ #define PROCESS__EXECMEM 0x02000000UL #define PROCESS__EXECSTACK 0x04000000UL #define PROCESS__EXECHEAP 0x08000000UL +#define PROCESS__SETKEYCREATE 0x10000000UL #define IPC__CREATE 0x00000001UL #define IPC__DESTROY 0x00000002UL @@ -966,4 +967,4 @@ #define KEY__SEARCH 0x00000008UL #define KEY__LINK 0x00000010UL #define KEY__SETATTR 0x00000020UL - +#define KEY__CREATE 0x00000040UL diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 8f5547ad185..191b3e4484c 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -32,6 +32,7 @@ struct task_security_struct { u32 sid; /* current SID */ u32 exec_sid; /* exec SID */ u32 create_sid; /* fscreate SID */ + u32 keycreate_sid; /* keycreate SID */ u32 ptrace_sid; /* SID of ptrace parent */ }; -- cgit v1.2.3-70-g09d2 From 42c3e03ef6b298813557cdb997bd6db619cd65a2 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 26 Jun 2006 00:26:03 -0700 Subject: [PATCH] SELinux: Add sockcreate node to procattr API Below is a patch to add a new /proc/self/attr/sockcreate A process may write a context into this interface and all subsequent sockets created will be labeled with that context. This is the same idea as the fscreate interface where a process can specify the label of a file about to be created. At this time one envisioned user of this will be xinetd. It will be able to better label sockets for the actual services. At this time all sockets take the label of the creating process, so all xinitd sockets would just be labeled the same. I tested this by creating a tcp sender and listener. The sender was able to write to this new proc file and then create sockets with the specified label. I am able to be sure the new label was used since the avc denial messages kicked out by the kernel included both the new security permission setsockcreate and all the socket denials were for the new label, not the label of the running process. Signed-off-by: Eric Paris Signed-off-by: James Morris Cc: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/base.c | 6 ++++++ security/selinux/hooks.c | 22 +++++++++++++++++----- security/selinux/include/av_perm_to_string.h | 1 + security/selinux/include/av_permissions.h | 1 + security/selinux/include/objsec.h | 1 + 5 files changed, 26 insertions(+), 5 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/fs/proc/base.c b/fs/proc/base.c index 43871c85729..6ba7785319d 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -132,6 +132,7 @@ enum pid_directory_inos { PROC_TGID_ATTR_EXEC, PROC_TGID_ATTR_FSCREATE, PROC_TGID_ATTR_KEYCREATE, + PROC_TGID_ATTR_SOCKCREATE, #endif #ifdef CONFIG_AUDITSYSCALL PROC_TGID_LOGINUID, @@ -174,6 +175,7 @@ enum pid_directory_inos { PROC_TID_ATTR_EXEC, PROC_TID_ATTR_FSCREATE, PROC_TID_ATTR_KEYCREATE, + PROC_TID_ATTR_SOCKCREATE, #endif #ifdef CONFIG_AUDITSYSCALL PROC_TID_LOGINUID, @@ -291,6 +293,7 @@ static struct pid_entry tgid_attr_stuff[] = { E(PROC_TGID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), E(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO), E(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO), + E(PROC_TGID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO), {0,0,NULL,0} }; static struct pid_entry tid_attr_stuff[] = { @@ -299,6 +302,7 @@ static struct pid_entry tid_attr_stuff[] = { E(PROC_TID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), E(PROC_TID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO), E(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO), + E(PROC_TID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO), {0,0,NULL,0} }; #endif @@ -1764,6 +1768,8 @@ static struct dentry *proc_pident_lookup(struct inode *dir, case PROC_TGID_ATTR_FSCREATE: case PROC_TID_ATTR_KEYCREATE: case PROC_TGID_ATTR_KEYCREATE: + case PROC_TID_ATTR_SOCKCREATE: + case PROC_TGID_ATTR_SOCKCREATE: inode->i_fop = &proc_pid_attr_operations; break; #endif diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0d8b27513bd..ac7f2b2e392 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1532,8 +1532,9 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) /* Default to the current task SID. */ bsec->sid = tsec->sid; - /* Reset create SID on execve. */ + /* Reset create and sockcreate SID on execve. */ tsec->create_sid = 0; + tsec->sockcreate_sid = 0; if (tsec->exec_sid) { newsid = tsec->exec_sid; @@ -2585,9 +2586,10 @@ static int selinux_task_alloc_security(struct task_struct *tsk) tsec2->osid = tsec1->osid; tsec2->sid = tsec1->sid; - /* Retain the exec and create SIDs across fork */ + /* Retain the exec, create, and sock SIDs across fork */ tsec2->exec_sid = tsec1->exec_sid; tsec2->create_sid = tsec1->create_sid; + tsec2->sockcreate_sid = tsec1->sockcreate_sid; /* Retain ptracer SID across fork, if any. This will be reset by the ptrace hook upon any @@ -2937,12 +2939,14 @@ static int selinux_socket_create(int family, int type, { int err = 0; struct task_security_struct *tsec; + u32 newsid; if (kern) goto out; tsec = current->security; - err = avc_has_perm(tsec->sid, tsec->sid, + newsid = tsec->sockcreate_sid ? : tsec->sid; + err = avc_has_perm(tsec->sid, newsid, socket_type_to_security_class(family, type, protocol), SOCKET__CREATE, NULL); @@ -2955,12 +2959,14 @@ static void selinux_socket_post_create(struct socket *sock, int family, { struct inode_security_struct *isec; struct task_security_struct *tsec; + u32 newsid; isec = SOCK_INODE(sock)->i_security; tsec = current->security; + newsid = tsec->sockcreate_sid ? : tsec->sid; isec->sclass = socket_type_to_security_class(family, type, protocol); - isec->sid = kern ? SECINITSID_KERNEL : tsec->sid; + isec->sid = kern ? SECINITSID_KERNEL : newsid; isec->initialized = 1; return; @@ -4163,6 +4169,8 @@ static int selinux_getprocattr(struct task_struct *p, sid = tsec->create_sid; else if (!strcmp(name, "keycreate")) sid = tsec->keycreate_sid; + else if (!strcmp(name, "sockcreate")) + sid = tsec->sockcreate_sid; else return -EINVAL; @@ -4197,6 +4205,8 @@ static int selinux_setprocattr(struct task_struct *p, error = task_has_perm(current, p, PROCESS__SETFSCREATE); else if (!strcmp(name, "keycreate")) error = task_has_perm(current, p, PROCESS__SETKEYCREATE); + else if (!strcmp(name, "sockcreate")) + error = task_has_perm(current, p, PROCESS__SETSOCKCREATE); else if (!strcmp(name, "current")) error = task_has_perm(current, p, PROCESS__SETCURRENT); else @@ -4231,7 +4241,9 @@ static int selinux_setprocattr(struct task_struct *p, if (error) return error; tsec->keycreate_sid = sid; - } else if (!strcmp(name, "current")) { + } else if (!strcmp(name, "sockcreate")) + tsec->sockcreate_sid = sid; + else if (!strcmp(name, "current")) { struct av_decision avd; if (sid == 0) diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index e777578ccd9..7c9b5838083 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -73,6 +73,7 @@ S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate") + S_(SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, "setsockcreate") S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") S_(SECCLASS_MSG, MSG__SEND, "send") S_(SECCLASS_MSG, MSG__RECEIVE, "receive") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 1e1678023b6..69fd4b48202 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -468,6 +468,7 @@ #define PROCESS__EXECSTACK 0x04000000UL #define PROCESS__EXECHEAP 0x08000000UL #define PROCESS__SETKEYCREATE 0x10000000UL +#define PROCESS__SETSOCKCREATE 0x20000000UL #define IPC__CREATE 0x00000001UL #define IPC__DESTROY 0x00000002UL diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 191b3e4484c..cf54a304169 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -33,6 +33,7 @@ struct task_security_struct { u32 exec_sid; /* exec SID */ u32 create_sid; /* fscreate SID */ u32 keycreate_sid; /* keycreate SID */ + u32 sockcreate_sid; /* fscreate SID */ u32 ptrace_sid; /* SID of ptrace parent */ }; -- cgit v1.2.3-70-g09d2 From 28eba5bf9d4bf3ba4d58d985abf3a2903b7f2125 Mon Sep 17 00:00:00 2001 From: Michael LeMay Date: Tue, 27 Jun 2006 02:53:42 -0700 Subject: [PATCH] selinux: inherit /proc/self/attr/keycreate across fork Update SELinux to cause the keycreate process attribute held in /proc/self/attr/keycreate to be inherited across a fork and reset upon execve. This is consistent with the handling of the other process attributes provided by SELinux and also makes it simpler to adapt logon programs to properly handle the keycreate attribute. Signed-off-by: Michael LeMay Signed-off-by: David Howells Acked-by: Stephen Smalley Acked-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ac7f2b2e392..28832e68980 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1532,8 +1532,9 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) /* Default to the current task SID. */ bsec->sid = tsec->sid; - /* Reset create and sockcreate SID on execve. */ + /* Reset fs, key, and sock SIDs on execve. */ tsec->create_sid = 0; + tsec->keycreate_sid = 0; tsec->sockcreate_sid = 0; if (tsec->exec_sid) { @@ -2586,9 +2587,10 @@ static int selinux_task_alloc_security(struct task_struct *tsk) tsec2->osid = tsec1->osid; tsec2->sid = tsec1->sid; - /* Retain the exec, create, and sock SIDs across fork */ + /* Retain the exec, fs, key, and sock SIDs across fork */ tsec2->exec_sid = tsec1->exec_sid; tsec2->create_sid = tsec1->create_sid; + tsec2->keycreate_sid = tsec1->keycreate_sid; tsec2->sockcreate_sid = tsec1->sockcreate_sid; /* Retain ptracer SID across fork, if any. -- cgit v1.2.3-70-g09d2