[PATCH] selinux: add hooks for key subsystem

Introduce SELinux hooks to support the access key retention subsystem
within the kernel.  Incorporate new flask headers from a modified version
of the SELinux reference policy, with support for the new security class
representing retained keys.  Extend the "key_alloc" security hook with a
task parameter representing the intended ownership context for the key
being allocated.  Attach security information to root's default keyrings
within the SELinux initialization routine.

Has passed David's testsuite.

Signed-off-by: Michael LeMay <mdlemay@epoch.ncsc.mil>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
Acked-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Michael LeMay
2006-06-22 14:47:17 -07:00
committed by Linus Torvalds
parent f893afbe12
commit d720024e94
16 changed files with 155 additions and 27 deletions

View File

@@ -860,7 +860,7 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz
}
#ifdef CONFIG_KEYS
static inline int dummy_key_alloc(struct key *key)
static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx)
{
return 0;
}

View File

@@ -247,8 +247,8 @@ static inline void key_alloc_serial(struct key *key)
* instantiate the key or discard it before returning
*/
struct key *key_alloc(struct key_type *type, const char *desc,
uid_t uid, gid_t gid, key_perm_t perm,
int not_in_quota)
uid_t uid, gid_t gid, struct task_struct *ctx,
key_perm_t perm, int not_in_quota)
{
struct key_user *user = NULL;
struct key *key;
@@ -318,7 +318,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
#endif
/* let the security module know about the key */
ret = security_key_alloc(key);
ret = security_key_alloc(key, ctx);
if (ret < 0)
goto security_error;
@@ -822,7 +822,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
/* allocate a new key */
key = key_alloc(ktype, description, current->fsuid, current->fsgid,
perm, not_in_quota);
current, perm, not_in_quota);
if (IS_ERR(key)) {
key_ref = ERR_PTR(PTR_ERR(key));
goto error_3;

View File

@@ -240,13 +240,14 @@ static long keyring_read(const struct key *keyring,
* allocate a keyring and link into the destination keyring
*/
struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
int not_in_quota, struct key *dest)
struct task_struct *ctx, int not_in_quota,
struct key *dest)
{
struct key *keyring;
int ret;
keyring = key_alloc(&key_type_keyring, description,
uid, gid,
uid, gid, ctx,
(KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
not_in_quota);

View File

@@ -67,7 +67,8 @@ struct key root_session_keyring = {
/*
* allocate the keyrings to be associated with a UID
*/
int alloc_uid_keyring(struct user_struct *user)
int alloc_uid_keyring(struct user_struct *user,
struct task_struct *ctx)
{
struct key *uid_keyring, *session_keyring;
char buf[20];
@@ -76,7 +77,7 @@ int alloc_uid_keyring(struct user_struct *user)
/* concoct a default session keyring */
sprintf(buf, "_uid_ses.%u", user->uid);
session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, NULL);
session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, NULL);
if (IS_ERR(session_keyring)) {
ret = PTR_ERR(session_keyring);
goto error;
@@ -86,7 +87,7 @@ int alloc_uid_keyring(struct user_struct *user)
* keyring */
sprintf(buf, "_uid.%u", user->uid);
uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0,
uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0,
session_keyring);
if (IS_ERR(uid_keyring)) {
key_put(session_keyring);
@@ -143,7 +144,7 @@ int install_thread_keyring(struct task_struct *tsk)
sprintf(buf, "_tid.%u", tsk->pid);
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error;
@@ -177,7 +178,7 @@ int install_process_keyring(struct task_struct *tsk)
if (!tsk->signal->process_keyring) {
sprintf(buf, "_pid.%u", tsk->tgid);
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error;
@@ -217,7 +218,7 @@ static int install_session_keyring(struct task_struct *tsk,
if (!keyring) {
sprintf(buf, "_ses.%u", tsk->tgid);
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL);
if (IS_ERR(keyring))
return PTR_ERR(keyring);
}
@@ -717,7 +718,7 @@ long join_session_keyring(const char *name)
keyring = find_keyring_by_name(name, 0);
if (PTR_ERR(keyring) == -ENOKEY) {
/* not found - try and create a new one */
keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL);
keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 0, NULL);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error2;

View File

@@ -48,7 +48,8 @@ static int call_sbin_request_key(struct key *key,
/* allocate a new session keyring */
sprintf(desc, "_req.%u", key->serial);
keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL);
keyring = keyring_alloc(desc, current->fsuid, current->fsgid,
current, 1, NULL);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error_alloc;
@@ -137,7 +138,8 @@ static struct key *__request_key_construction(struct key_type *type,
/* create a key and add it to the queue */
key = key_alloc(type, description,
current->fsuid, current->fsgid, KEY_POS_ALL, 0);
current->fsuid, current->fsgid,
current, KEY_POS_ALL, 0);
if (IS_ERR(key))
goto alloc_failed;

View File

@@ -148,7 +148,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info)
sprintf(desc, "%x", target->serial);
authkey = key_alloc(&key_type_request_key_auth, desc,
current->fsuid, current->fsgid,
current->fsuid, current->fsgid, current,
KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
KEY_USR_VIEW, 1);
if (IS_ERR(authkey)) {

View File

@@ -4252,6 +4252,57 @@ static int selinux_setprocattr(struct task_struct *p,
return size;
}
#ifdef CONFIG_KEYS
static int selinux_key_alloc(struct key *k, struct task_struct *tsk)
{
struct task_security_struct *tsec = tsk->security;
struct key_security_struct *ksec;
ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
if (!ksec)
return -ENOMEM;
ksec->obj = k;
ksec->sid = tsec->sid;
k->security = ksec;
return 0;
}
static void selinux_key_free(struct key *k)
{
struct key_security_struct *ksec = k->security;
k->security = NULL;
kfree(ksec);
}
static int selinux_key_permission(key_ref_t key_ref,
struct task_struct *ctx,
key_perm_t perm)
{
struct key *key;
struct task_security_struct *tsec;
struct key_security_struct *ksec;
key = key_ref_to_ptr(key_ref);
tsec = ctx->security;
ksec = key->security;
/* if no specific permissions are requested, we skip the
permission check. No serious, additional covert channels
appear to be created. */
if (perm == 0)
return 0;
return avc_has_perm(tsec->sid, ksec->sid,
SECCLASS_KEY, perm, NULL);
}
#endif
static struct security_operations selinux_ops = {
.ptrace = selinux_ptrace,
.capget = selinux_capget,
@@ -4406,6 +4457,12 @@ static struct security_operations selinux_ops = {
.xfrm_state_delete_security = selinux_xfrm_state_delete,
.xfrm_policy_lookup = selinux_xfrm_policy_lookup,
#endif
#ifdef CONFIG_KEYS
.key_alloc = selinux_key_alloc,
.key_free = selinux_key_free,
.key_permission = selinux_key_permission,
#endif
};
static __init int selinux_init(void)
@@ -4441,6 +4498,13 @@ static __init int selinux_init(void)
} else {
printk(KERN_INFO "SELinux: Starting in permissive mode\n");
}
#ifdef CONFIG_KEYS
/* Add security information to initial keyrings */
security_key_alloc(&root_user_keyring, current);
security_key_alloc(&root_session_keyring, current);
#endif
return 0;
}

View File

@@ -242,3 +242,9 @@
S_(SECCLASS_PACKET, PACKET__SEND, "send")
S_(SECCLASS_PACKET, PACKET__RECV, "recv")
S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto")
S_(SECCLASS_KEY, KEY__VIEW, "view")
S_(SECCLASS_KEY, KEY__READ, "read")
S_(SECCLASS_KEY, KEY__WRITE, "write")
S_(SECCLASS_KEY, KEY__SEARCH, "search")
S_(SECCLASS_KEY, KEY__LINK, "link")
S_(SECCLASS_KEY, KEY__SETATTR, "setattr")

View File

@@ -959,3 +959,11 @@
#define PACKET__SEND 0x00000001UL
#define PACKET__RECV 0x00000002UL
#define PACKET__RELABELTO 0x00000004UL
#define KEY__VIEW 0x00000001UL
#define KEY__READ 0x00000002UL
#define KEY__WRITE 0x00000004UL
#define KEY__SEARCH 0x00000008UL
#define KEY__LINK 0x00000010UL
#define KEY__SETATTR 0x00000020UL

View File

@@ -60,3 +60,4 @@
S_("netlink_kobject_uevent_socket")
S_("appletalk_socket")
S_("packet")
S_("key")

View File

@@ -62,6 +62,7 @@
#define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55
#define SECCLASS_APPLETALK_SOCKET 56
#define SECCLASS_PACKET 57
#define SECCLASS_KEY 58
/*
* Security identifier indices for initial entities

View File

@@ -99,6 +99,11 @@ struct sk_security_struct {
u32 peer_sid; /* SID of peer */
};
struct key_security_struct {
struct key *obj; /* back pointer */
u32 sid; /* SID of key */
};
extern unsigned int selinux_checkreqprot;
#endif /* _SELINUX_OBJSEC_H_ */