summaryrefslogtreecommitdiffstats
path: root/security/keys/keyctl.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2020-05-12 16:16:29 +0200
committerDavid Howells <dhowells@redhat.com>2020-05-19 16:42:22 +0200
commit8c0637e950d68933a67f7438f779d79b049b5e5c (patch)
tree3a0e17ac6d3dac7dad70f78b9e3e69cb6a2d4e7f /security/keys/keyctl.c
parentpipe: Add notification lossage handling (diff)
downloadlinux-8c0637e950d68933a67f7438f779d79b049b5e5c.tar.xz
linux-8c0637e950d68933a67f7438f779d79b049b5e5c.zip
keys: Make the KEY_NEED_* perms an enum rather than a mask
Since the meaning of combining the KEY_NEED_* constants is undefined, make it so that you can't do that by turning them into an enum. The enum is also given some extra values to represent special circumstances, such as: (1) The '0' value is reserved and causes a warning to trap the parameter being unset. (2) The key is to be unlinked and we require no permissions on it, only the keyring, (this replaces the KEY_LOOKUP_FOR_UNLINK flag). (3) An override due to CAP_SYS_ADMIN. (4) An override due to an instantiation token being present. (5) The permissions check is being deferred to later key_permission() calls. The extra values give the opportunity for LSMs to audit these situations. [Note: This really needs overhauling so that lookup_user_key() tells key_task_permission() and the LSM what operation is being done and leaves it to those functions to decide how to map that onto the available permits. However, I don't really want to make these change in the middle of the notifications patchset.] Signed-off-by: David Howells <dhowells@redhat.com> cc: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> cc: Paul Moore <paul@paul-moore.com> cc: Stephen Smalley <stephen.smalley.work@gmail.com> cc: Casey Schaufler <casey@schaufler-ca.com> cc: keyrings@vger.kernel.org cc: selinux@vger.kernel.org
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r--security/keys/keyctl.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 7d8de1c9a478..6763ee45e04d 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -434,7 +434,7 @@ long keyctl_invalidate_key(key_serial_t id)
/* Root is permitted to invalidate certain special keys */
if (capable(CAP_SYS_ADMIN)) {
- key_ref = lookup_user_key(id, 0, 0);
+ key_ref = lookup_user_key(id, 0, KEY_SYSADMIN_OVERRIDE);
if (IS_ERR(key_ref))
goto error;
if (test_bit(KEY_FLAG_ROOT_CAN_INVAL,
@@ -479,7 +479,8 @@ long keyctl_keyring_clear(key_serial_t ringid)
/* Root is permitted to invalidate certain special keyrings */
if (capable(CAP_SYS_ADMIN)) {
- keyring_ref = lookup_user_key(ringid, 0, 0);
+ keyring_ref = lookup_user_key(ringid, 0,
+ KEY_SYSADMIN_OVERRIDE);
if (IS_ERR(keyring_ref))
goto error;
if (test_bit(KEY_FLAG_ROOT_CAN_CLEAR,
@@ -563,7 +564,7 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
goto error;
}
- key_ref = lookup_user_key(id, KEY_LOOKUP_FOR_UNLINK, 0);
+ key_ref = lookup_user_key(id, KEY_LOOKUP_PARTIAL, KEY_NEED_UNLINK);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
goto error2;
@@ -663,7 +664,7 @@ long keyctl_describe_key(key_serial_t keyid,
key_put(instkey);
key_ref = lookup_user_key(keyid,
KEY_LOOKUP_PARTIAL,
- 0);
+ KEY_AUTHTOKEN_OVERRIDE);
if (!IS_ERR(key_ref))
goto okay;
}
@@ -833,7 +834,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
size_t key_data_len;
/* find the key first */
- key_ref = lookup_user_key(keyid, 0, 0);
+ key_ref = lookup_user_key(keyid, 0, KEY_DEFER_PERM_CHECK);
if (IS_ERR(key_ref)) {
ret = -ENOKEY;
goto out;
@@ -1471,7 +1472,7 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout)
key_put(instkey);
key_ref = lookup_user_key(id,
KEY_LOOKUP_PARTIAL,
- 0);
+ KEY_AUTHTOKEN_OVERRIDE);
if (!IS_ERR(key_ref))
goto okay;
}
@@ -1579,7 +1580,8 @@ long keyctl_get_security(key_serial_t keyid,
return PTR_ERR(instkey);
key_put(instkey);
- key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0);
+ key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL,
+ KEY_AUTHTOKEN_OVERRIDE);
if (IS_ERR(key_ref))
return PTR_ERR(key_ref);
}