From: Richard Haines <richard_c_haines@btinternet.com>
To: selinux@vger.kernel.org
Cc: sds@tycho.nsa.gov, paul@paul-moore.com, dhowells@redhat.com,
Richard Haines <richard_c_haines@btinternet.com>
Subject: security/selinux: Add support for new key permissions
Date: Mon, 3 Feb 2020 14:13:43 +0000 [thread overview]
Message-ID: <20200203141343.29133-1-richard_c_haines@btinternet.com> (raw)
Add a new 'key_perms' policy capability and support for the additional
key permissions: inval, revoke, join, clear
Also fixes JOIN -> LINK permission translation when policy
capability 'keys_perms' = 0;
The current "setattr" perm name remains and is used for KEY_NEED_SETSEC.
This gives the following permissions for the 'key' class:
create Create a key or keyring.
view View attributes.
read Read contents.
write Update or modify.
search Search (keyring) or find (key).
link Link a key into the keyring.
setattr kernel < 5.X Change permissions on a keyring.
kernel >= 5.X Set owner, group, ACL.
inval Invalidate key.
revoke Revoke key.
join Join keyring as session.
clear Clear a keyring.
Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---
include/linux/key.h | 3 +-
security/keys/keyctl.c | 3 +-
security/selinux/hooks.c | 73 ++++++++++++++++++++++++++++++-------
security/selinux/include/classmap.h | 2 +-
security/selinux/include/security.h | 8 ++++
security/selinux/ss/services.c | 3 +-
6 files changed, 74 insertions(+), 18 deletions(-)
diff --git a/include/linux/key.h b/include/linux/key.h
index 24c69457783f..ddfc0709569b 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -435,7 +435,8 @@ extern void key_free_user_ns(struct user_namespace *);
#define KEY_NEED_REVOKE 0x080 /* Require permission to revoke key */
#define KEY_NEED_JOIN 0x100 /* Require permission to join keyring as session */
#define KEY_NEED_CLEAR 0x200 /* Require permission to clear a keyring */
-#define KEY_NEED_ALL 0x3ff
+#define KEY_NEED_PARENT_JOIN 0x400 /* Require permission to impose keyring on parent */
+#define KEY_NEED_ALL 0x7ff
#define OLD_KEY_NEED_SETATTR 0x20 /* Used to be Require permission to change attributes */
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index a0c97d4d8251..65e1c0c3feb1 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1592,7 +1592,8 @@ long keyctl_session_to_parent(void)
struct cred *cred;
int ret;
- keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_NEED_JOIN);
+ keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0,
+ KEY_NEED_PARENT_JOIN);
if (IS_ERR(keyring_r))
return PTR_ERR(keyring_r);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c8db5235b01f..a499bd7d9777 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6556,7 +6556,8 @@ static int selinux_key_permission(key_ref_t key_ref,
{
struct key *key;
struct key_security_struct *ksec;
- unsigned oldstyle_perm;
+ unsigned int key_perm = 0, switch_perm = 0;
+ int bit = 1, count = KEY_NEED_ALL;
u32 sid;
/* if no specific permissions are requested, we skip the
@@ -6565,18 +6566,62 @@ static int selinux_key_permission(key_ref_t key_ref,
if (perm == 0)
return 0;
- oldstyle_perm = perm & (KEY_NEED_VIEW | KEY_NEED_READ | KEY_NEED_WRITE |
- KEY_NEED_SEARCH | KEY_NEED_LINK);
- if (perm & KEY_NEED_SETSEC)
- oldstyle_perm |= OLD_KEY_NEED_SETATTR;
- if (perm & KEY_NEED_INVAL)
- oldstyle_perm |= KEY_NEED_SEARCH;
- if (perm & KEY_NEED_REVOKE && !(perm & OLD_KEY_NEED_SETATTR))
- oldstyle_perm |= KEY_NEED_WRITE;
- if (perm & KEY_NEED_JOIN)
- oldstyle_perm |= KEY_NEED_SEARCH;
- if (perm & KEY_NEED_CLEAR)
- oldstyle_perm |= KEY_NEED_WRITE;
+ if (selinux_policycap_key_perms()) {
+ while (count) {
+ switch_perm = bit & perm;
+ switch (switch_perm) {
+ case KEY_NEED_VIEW:
+ key_perm |= KEY__VIEW;
+ break;
+ case KEY_NEED_READ:
+ key_perm |= KEY__READ;
+ break;
+ case KEY_NEED_WRITE:
+ key_perm |= KEY__WRITE;
+ break;
+ case KEY_NEED_SEARCH:
+ key_perm |= KEY__SEARCH;
+ break;
+ case KEY_NEED_LINK:
+ key_perm |= KEY__LINK;
+ break;
+ case KEY_NEED_SETSEC:
+ key_perm |= KEY__SETATTR;
+ break;
+ case KEY_NEED_INVAL:
+ key_perm |= KEY__INVAL;
+ break;
+ case KEY_NEED_REVOKE:
+ key_perm |= KEY__REVOKE;
+ break;
+ case KEY_NEED_JOIN:
+ case KEY_NEED_PARENT_JOIN:
+ key_perm |= KEY__JOIN;
+ break;
+ case KEY_NEED_CLEAR:
+ key_perm |= KEY__CLEAR;
+ break;
+ }
+ bit <<= 1;
+ count >>= 1;
+ }
+ } else {
+ key_perm = perm & (KEY_NEED_VIEW | KEY_NEED_READ |
+ KEY_NEED_WRITE | KEY_NEED_SEARCH |
+ KEY_NEED_LINK);
+ if (perm & KEY_NEED_PARENT_JOIN)
+ key_perm |= KEY_NEED_LINK;
+ if (perm & KEY_NEED_SETSEC)
+ key_perm |= OLD_KEY_NEED_SETATTR;
+ if (perm & KEY_NEED_INVAL)
+ key_perm |= KEY_NEED_SEARCH;
+ if (perm & KEY_NEED_REVOKE && !(perm & OLD_KEY_NEED_SETATTR))
+ key_perm |= KEY_NEED_WRITE;
+ if (perm & KEY_NEED_JOIN)
+ key_perm |= KEY_NEED_SEARCH;
+ if (perm & KEY_NEED_CLEAR)
+ key_perm |= KEY_NEED_WRITE;
+ }
sid = cred_sid(cred);
@@ -6584,7 +6629,7 @@ static int selinux_key_permission(key_ref_t key_ref,
ksec = key->security;
return avc_has_perm(&selinux_state,
- sid, ksec->sid, SECCLASS_KEY, oldstyle_perm, NULL);
+ sid, ksec->sid, SECCLASS_KEY, key_perm, NULL);
}
static int selinux_key_getsecurity(struct key *key, char **_buffer)
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index 7db24855e12d..038374bef526 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -159,7 +159,7 @@ struct security_class_mapping secclass_map[] = {
{ "send", "recv", "relabelto", "forward_in", "forward_out", NULL } },
{ "key",
{ "view", "read", "write", "search", "link", "setattr", "create",
- NULL } },
+ "inval", "revoke", "join", "clear", NULL } },
{ "dccp_socket",
{ COMMON_SOCK_PERMS,
"node_bind", "name_connect", NULL } },
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index ae840634e3c7..6b264b6d9d31 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -79,6 +79,7 @@ enum {
POLICYDB_CAPABILITY_ALWAYSNETWORK,
POLICYDB_CAPABILITY_CGROUPSECLABEL,
POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION,
+ POLICYDB_CAPABILITY_KEYPERMS,
__POLICYDB_CAPABILITY_MAX
};
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
@@ -178,6 +179,13 @@ static inline bool selinux_policycap_nnp_nosuid_transition(void)
return state->policycap[POLICYDB_CAPABILITY_NNP_NOSUID_TRANSITION];
}
+static inline bool selinux_policycap_key_perms(void)
+{
+ struct selinux_state *state = &selinux_state;
+
+ return state->policycap[POLICYDB_CAPABILITY_KEYPERMS];
+}
+
int security_mls_enabled(struct selinux_state *state);
int security_load_policy(struct selinux_state *state,
void *data, size_t len);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index a5813c7629c1..b31dcd54cde9 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -73,7 +73,8 @@ const char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX] = {
"extended_socket_class",
"always_check_network",
"cgroup_seclabel",
- "nnp_nosuid_transition"
+ "nnp_nosuid_transition",
+ "key_perms"
};
static struct selinux_ss selinux_ss;
--
cgit 1.2-0.3.lf.el7
next reply other threads:[~2020-02-03 14:14 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-03 14:13 Richard Haines [this message]
2020-02-03 15:29 ` security/selinux: Add support for new key permissions Stephen Smalley
2020-02-03 15:42 ` Richard Haines
2020-02-06 16:03 ` Stephen Smalley
2020-02-06 18:07 ` Richard Haines
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200203141343.29133-1-richard_c_haines@btinternet.com \
--to=richard_c_haines@btinternet.com \
--cc=dhowells@redhat.com \
--cc=paul@paul-moore.com \
--cc=sds@tycho.nsa.gov \
--cc=selinux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.