summaryrefslogtreecommitdiff
path: root/security/keys/process_keys.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2020-05-12 15:16:29 +0100
committerDavid Howells <dhowells@redhat.com>2020-05-19 15:42:22 +0100
commit8c0637e950d68933a67f7438f779d79b049b5e5c (patch)
tree3a0e17ac6d3dac7dad70f78b9e3e69cb6a2d4e7f /security/keys/process_keys.c
parente7d553d69cf63aec7de0f38fed49ccbb30922e1e (diff)
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/process_keys.c')
-rw-r--r--security/keys/process_keys.c46
1 files changed, 22 insertions, 24 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 09541de31f2f..7e0232db1707 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -609,7 +609,7 @@ bool lookup_user_key_possessed(const struct key *key,
* returned key reference.
*/
key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
- key_perm_t perm)
+ enum key_need_perm need_perm)
{
struct keyring_search_context ctx = {
.match_data.cmp = lookup_user_key_possessed,
@@ -773,35 +773,33 @@ try_again:
/* unlink does not use the nominated key in any way, so can skip all
* the permission checks as it is only concerned with the keyring */
- if (lflags & KEY_LOOKUP_FOR_UNLINK) {
- ret = 0;
- goto error;
- }
-
- if (!(lflags & KEY_LOOKUP_PARTIAL)) {
- ret = wait_for_key_construction(key, true);
- switch (ret) {
- case -ERESTARTSYS:
- goto invalid_key;
- default:
- if (perm)
+ if (need_perm != KEY_NEED_UNLINK) {
+ if (!(lflags & KEY_LOOKUP_PARTIAL)) {
+ ret = wait_for_key_construction(key, true);
+ switch (ret) {
+ case -ERESTARTSYS:
+ goto invalid_key;
+ default:
+ if (need_perm != KEY_AUTHTOKEN_OVERRIDE &&
+ need_perm != KEY_DEFER_PERM_CHECK)
+ goto invalid_key;
+ case 0:
+ break;
+ }
+ } else if (need_perm != KEY_DEFER_PERM_CHECK) {
+ ret = key_validate(key);
+ if (ret < 0)
goto invalid_key;
- case 0:
- break;
}
- } else if (perm) {
- ret = key_validate(key);
- if (ret < 0)
+
+ ret = -EIO;
+ if (!(lflags & KEY_LOOKUP_PARTIAL) &&
+ key_read_state(key) == KEY_IS_UNINSTANTIATED)
goto invalid_key;
}
- ret = -EIO;
- if (!(lflags & KEY_LOOKUP_PARTIAL) &&
- key_read_state(key) == KEY_IS_UNINSTANTIATED)
- goto invalid_key;
-
/* check the permissions */
- ret = key_task_permission(key_ref, ctx.cred, perm);
+ ret = key_task_permission(key_ref, ctx.cred, need_perm);
if (ret < 0)
goto invalid_key;