summaryrefslogtreecommitdiffstats
path: root/security/keys/keyctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r--security/keys/keyctl.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index cd5bd0cef25d..e26f860e5f2e 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -37,8 +37,6 @@ static int key_get_type_from_user(char *type,
return ret;
if (ret == 0 || ret >= len)
return -EINVAL;
- if (type[0] == '.')
- return -EPERM;
type[len - 1] = '\0';
return 0;
}
@@ -86,6 +84,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
if (!*description) {
kfree(description);
description = NULL;
+ } else if ((description[0] == '.') &&
+ (strncmp(type, "keyring", 7) == 0)) {
+ ret = -EPERM;
+ goto error2;
}
}
@@ -404,12 +406,25 @@ long keyctl_invalidate_key(key_serial_t id)
key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH);
if (IS_ERR(key_ref)) {
ret = PTR_ERR(key_ref);
+
+ /* Root is permitted to invalidate certain special keys */
+ if (capable(CAP_SYS_ADMIN)) {
+ key_ref = lookup_user_key(id, 0, 0);
+ if (IS_ERR(key_ref))
+ goto error;
+ if (test_bit(KEY_FLAG_ROOT_CAN_INVAL,
+ &key_ref_to_ptr(key_ref)->flags))
+ goto invalidate;
+ goto error_put;
+ }
+
goto error;
}
+invalidate:
key_invalidate(key_ref_to_ptr(key_ref));
ret = 0;
-
+error_put:
key_ref_put(key_ref);
error:
kleave(" = %ld", ret);