diff options
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r-- | security/keys/keyctl.c | 21 |
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); |