Commit 4eb582cf authored by Michael LeMay's avatar Michael LeMay Committed by Linus Torvalds

[PATCH] keys: add a way to store the appropriate context for newly-created keys

Add a /proc/<pid>/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: default avatarMichael LeMay <mdlemay@epoch.ncsc.mil>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 06ec7be5
...@@ -241,25 +241,30 @@ The security class "key" has been added to SELinux so that mandatory access ...@@ -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 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. 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 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. performed.
Each key is labeled with the same context as the task to which it belongs. The value of the file /proc/self/attr/keycreate influences the labeling of
Typically, this is the same task that was running when the key was created. newly-created keys. If the contents of that file correspond to an SELinux
The default keyrings are handled differently, but in a way that is very security context, then the key will be assigned that context. Otherwise, the
intuitive: 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 The default keyrings associated with users will be labeled with the default
are currently labeled with the context of the login manager. 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
(*) The keyrings associated with new threads are each labeled with the context be labeled with the context of the login program itself.
of their associated thread, and both session and process keyrings are
handled similarly.
Note, however, that the default keyrings associated with the root user are 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 labeled with the default kernel context, since they are created early in the
boot process, before root has a chance to log in. 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 NEW PROCFS FILES
......
...@@ -121,6 +121,7 @@ enum pid_directory_inos { ...@@ -121,6 +121,7 @@ enum pid_directory_inos {
PROC_TGID_ATTR_PREV, PROC_TGID_ATTR_PREV,
PROC_TGID_ATTR_EXEC, PROC_TGID_ATTR_EXEC,
PROC_TGID_ATTR_FSCREATE, PROC_TGID_ATTR_FSCREATE,
PROC_TGID_ATTR_KEYCREATE,
#endif #endif
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
PROC_TGID_LOGINUID, PROC_TGID_LOGINUID,
...@@ -162,6 +163,7 @@ enum pid_directory_inos { ...@@ -162,6 +163,7 @@ enum pid_directory_inos {
PROC_TID_ATTR_PREV, PROC_TID_ATTR_PREV,
PROC_TID_ATTR_EXEC, PROC_TID_ATTR_EXEC,
PROC_TID_ATTR_FSCREATE, PROC_TID_ATTR_FSCREATE,
PROC_TID_ATTR_KEYCREATE,
#endif #endif
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
PROC_TID_LOGINUID, PROC_TID_LOGINUID,
...@@ -275,6 +277,7 @@ static struct pid_entry tgid_attr_stuff[] = { ...@@ -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_PREV, "prev", S_IFREG|S_IRUGO),
E(PROC_TGID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), 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_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
E(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
{0,0,NULL,0} {0,0,NULL,0}
}; };
static struct pid_entry tid_attr_stuff[] = { static struct pid_entry tid_attr_stuff[] = {
...@@ -282,6 +285,7 @@ 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_PREV, "prev", S_IFREG|S_IRUGO),
E(PROC_TID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), 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_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
E(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
{0,0,NULL,0} {0,0,NULL,0}
}; };
#endif #endif
...@@ -1801,6 +1805,8 @@ static struct dentry *proc_pident_lookup(struct inode *dir, ...@@ -1801,6 +1805,8 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
case PROC_TGID_ATTR_EXEC: case PROC_TGID_ATTR_EXEC:
case PROC_TID_ATTR_FSCREATE: case PROC_TID_ATTR_FSCREATE:
case PROC_TGID_ATTR_FSCREATE: case PROC_TGID_ATTR_FSCREATE:
case PROC_TID_ATTR_KEYCREATE:
case PROC_TGID_ATTR_KEYCREATE:
inode->i_fop = &proc_pid_attr_operations; inode->i_fop = &proc_pid_attr_operations;
break; break;
#endif #endif
......
...@@ -1099,6 +1099,17 @@ static int may_create(struct inode *dir, ...@@ -1099,6 +1099,17 @@ static int may_create(struct inode *dir,
FILESYSTEM__ASSOCIATE, &ad); 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_LINK 0
#define MAY_UNLINK 1 #define MAY_UNLINK 1
#define MAY_RMDIR 2 #define MAY_RMDIR 2
...@@ -4150,6 +4161,8 @@ static int selinux_getprocattr(struct task_struct *p, ...@@ -4150,6 +4161,8 @@ static int selinux_getprocattr(struct task_struct *p,
sid = tsec->exec_sid; sid = tsec->exec_sid;
else if (!strcmp(name, "fscreate")) else if (!strcmp(name, "fscreate"))
sid = tsec->create_sid; sid = tsec->create_sid;
else if (!strcmp(name, "keycreate"))
sid = tsec->keycreate_sid;
else else
return -EINVAL; return -EINVAL;
...@@ -4182,6 +4195,8 @@ static int selinux_setprocattr(struct task_struct *p, ...@@ -4182,6 +4195,8 @@ static int selinux_setprocattr(struct task_struct *p,
error = task_has_perm(current, p, PROCESS__SETEXEC); error = task_has_perm(current, p, PROCESS__SETEXEC);
else if (!strcmp(name, "fscreate")) else if (!strcmp(name, "fscreate"))
error = task_has_perm(current, p, PROCESS__SETFSCREATE); 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")) else if (!strcmp(name, "current"))
error = task_has_perm(current, p, PROCESS__SETCURRENT); error = task_has_perm(current, p, PROCESS__SETCURRENT);
else else
...@@ -4211,7 +4226,12 @@ static int selinux_setprocattr(struct task_struct *p, ...@@ -4211,7 +4226,12 @@ static int selinux_setprocattr(struct task_struct *p,
tsec->exec_sid = sid; tsec->exec_sid = sid;
else if (!strcmp(name, "fscreate")) else if (!strcmp(name, "fscreate"))
tsec->create_sid = sid; 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; struct av_decision avd;
if (sid == 0) if (sid == 0)
...@@ -4275,7 +4295,10 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk, ...@@ -4275,7 +4295,10 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
return -ENOMEM; return -ENOMEM;
ksec->obj = k; ksec->obj = k;
ksec->sid = tsec->sid; if (tsec->keycreate_sid)
ksec->sid = tsec->keycreate_sid;
else
ksec->sid = tsec->sid;
k->security = ksec; k->security = ksec;
return 0; return 0;
...@@ -4514,10 +4537,10 @@ static __init int selinux_init(void) ...@@ -4514,10 +4537,10 @@ static __init int selinux_init(void)
#ifdef CONFIG_KEYS #ifdef CONFIG_KEYS
/* Add security information to initial keyrings */ /* Add security information to initial keyrings */
security_key_alloc(&root_user_keyring, current, selinux_key_alloc(&root_user_keyring, current,
KEY_ALLOC_NOT_IN_QUOTA); KEY_ALLOC_NOT_IN_QUOTA);
security_key_alloc(&root_session_keyring, current, selinux_key_alloc(&root_session_keyring, current,
KEY_ALLOC_NOT_IN_QUOTA); KEY_ALLOC_NOT_IN_QUOTA);
#endif #endif
return 0; return 0;
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem")
S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack")
S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap")
S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate")
S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue")
S_(SECCLASS_MSG, MSG__SEND, "send") S_(SECCLASS_MSG, MSG__SEND, "send")
S_(SECCLASS_MSG, MSG__RECEIVE, "receive") S_(SECCLASS_MSG, MSG__RECEIVE, "receive")
...@@ -248,3 +249,4 @@ ...@@ -248,3 +249,4 @@
S_(SECCLASS_KEY, KEY__SEARCH, "search") S_(SECCLASS_KEY, KEY__SEARCH, "search")
S_(SECCLASS_KEY, KEY__LINK, "link") S_(SECCLASS_KEY, KEY__LINK, "link")
S_(SECCLASS_KEY, KEY__SETATTR, "setattr") S_(SECCLASS_KEY, KEY__SETATTR, "setattr")
S_(SECCLASS_KEY, KEY__CREATE, "create")
...@@ -467,6 +467,7 @@ ...@@ -467,6 +467,7 @@
#define PROCESS__EXECMEM 0x02000000UL #define PROCESS__EXECMEM 0x02000000UL
#define PROCESS__EXECSTACK 0x04000000UL #define PROCESS__EXECSTACK 0x04000000UL
#define PROCESS__EXECHEAP 0x08000000UL #define PROCESS__EXECHEAP 0x08000000UL
#define PROCESS__SETKEYCREATE 0x10000000UL
#define IPC__CREATE 0x00000001UL #define IPC__CREATE 0x00000001UL
#define IPC__DESTROY 0x00000002UL #define IPC__DESTROY 0x00000002UL
...@@ -966,4 +967,4 @@ ...@@ -966,4 +967,4 @@
#define KEY__SEARCH 0x00000008UL #define KEY__SEARCH 0x00000008UL
#define KEY__LINK 0x00000010UL #define KEY__LINK 0x00000010UL
#define KEY__SETATTR 0x00000020UL #define KEY__SETATTR 0x00000020UL
#define KEY__CREATE 0x00000040UL
...@@ -32,6 +32,7 @@ struct task_security_struct { ...@@ -32,6 +32,7 @@ struct task_security_struct {
u32 sid; /* current SID */ u32 sid; /* current SID */
u32 exec_sid; /* exec SID */ u32 exec_sid; /* exec SID */
u32 create_sid; /* fscreate SID */ u32 create_sid; /* fscreate SID */
u32 keycreate_sid; /* keycreate SID */
u32 ptrace_sid; /* SID of ptrace parent */ u32 ptrace_sid; /* SID of ptrace parent */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment