Commit 700920eb5ba4de5417b446c9a8bb008df2b973e0
Committed by
James Morris
1 parent
53999bf34d
Exists in
master
and in
20 other branches
KEYS: Allow special keyrings to be cleared
The kernel contains some special internal keyrings, for instance the DNS resolver keyring : 2a93faf1 I----- 1 perm 1f030000 0 0 keyring .dns_resolver: empty It would occasionally be useful to allow the contents of such keyrings to be flushed by root (cache invalidation). Allow a flag to be set on a keyring to mark that someone possessing the sysadmin capability can clear the keyring, even without normal write access to the keyring. Set this flag on the special keyrings created by the DNS resolver, the NFS identity mapper and the CIFS identity mapper. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Jeff Layton <jlayton@redhat.com> Acked-by: Steve Dickson <steved@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
Showing 7 changed files with 26 additions and 1 deletions Side-by-side Diff
Documentation/networking/dns_resolver.txt
... | ... | @@ -102,6 +102,10 @@ |
102 | 102 | If _expiry is non-NULL, the expiry time (TTL) of the result will be |
103 | 103 | returned also. |
104 | 104 | |
105 | +The kernel maintains an internal keyring in which it caches looked up keys. | |
106 | +This can be cleared by any process that has the CAP_SYS_ADMIN capability by | |
107 | +the use of KEYCTL_KEYRING_CLEAR on the keyring ID. | |
108 | + | |
105 | 109 | |
106 | 110 | =============================== |
107 | 111 | READING DNS KEYS FROM USERSPACE |
Documentation/security/keys.txt
... | ... | @@ -554,6 +554,10 @@ |
554 | 554 | process must have write permission on the keyring, and it must be a |
555 | 555 | keyring (or else error ENOTDIR will result). |
556 | 556 | |
557 | + This function can also be used to clear special kernel keyrings if they | |
558 | + are appropriately marked if the user has CAP_SYS_ADMIN capability. The | |
559 | + DNS resolver cache keyring is an example of this. | |
560 | + | |
557 | 561 | |
558 | 562 | (*) Link a key into a keyring: |
559 | 563 |
fs/cifs/cifsacl.c
... | ... | @@ -556,6 +556,7 @@ |
556 | 556 | |
557 | 557 | /* instruct request_key() to use this special keyring as a cache for |
558 | 558 | * the results it looks up */ |
559 | + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); | |
559 | 560 | cred->thread_keyring = keyring; |
560 | 561 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; |
561 | 562 | root_cred = cred; |
fs/nfs/idmap.c
include/linux/key.h
... | ... | @@ -155,6 +155,7 @@ |
155 | 155 | #define KEY_FLAG_IN_QUOTA 3 /* set if key consumes quota */ |
156 | 156 | #define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */ |
157 | 157 | #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ |
158 | +#define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ | |
158 | 159 | |
159 | 160 | /* the description string |
160 | 161 | * - this is used to match a key against search criteria |
net/dns_resolver/dns_key.c
... | ... | @@ -281,6 +281,7 @@ |
281 | 281 | |
282 | 282 | /* instruct request_key() to use this special keyring as a cache for |
283 | 283 | * the results it looks up */ |
284 | + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); | |
284 | 285 | cred->thread_keyring = keyring; |
285 | 286 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; |
286 | 287 | dns_resolver_cache = cred; |
security/keys/keyctl.c
... | ... | @@ -388,11 +388,24 @@ |
388 | 388 | keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); |
389 | 389 | if (IS_ERR(keyring_ref)) { |
390 | 390 | ret = PTR_ERR(keyring_ref); |
391 | + | |
392 | + /* Root is permitted to invalidate certain special keyrings */ | |
393 | + if (capable(CAP_SYS_ADMIN)) { | |
394 | + keyring_ref = lookup_user_key(ringid, 0, 0); | |
395 | + if (IS_ERR(keyring_ref)) | |
396 | + goto error; | |
397 | + if (test_bit(KEY_FLAG_ROOT_CAN_CLEAR, | |
398 | + &key_ref_to_ptr(keyring_ref)->flags)) | |
399 | + goto clear; | |
400 | + goto error_put; | |
401 | + } | |
402 | + | |
391 | 403 | goto error; |
392 | 404 | } |
393 | 405 | |
406 | +clear: | |
394 | 407 | ret = keyring_clear(key_ref_to_ptr(keyring_ref)); |
395 | - | |
408 | +error_put: | |
396 | 409 | key_ref_put(keyring_ref); |
397 | 410 | error: |
398 | 411 | return ret; |