Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Howells and committed by
James Morris
700920eb 53999bf3

+26 -1
+4
Documentation/networking/dns_resolver.txt
··· 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
+4
Documentation/security/keys.txt
··· 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
+1
fs/cifs/cifsacl.c
··· 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;
+1
fs/nfs/idmap.c
··· 198 198 if (ret < 0) 199 199 goto failed_put_key; 200 200 201 + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); 201 202 cred->thread_keyring = keyring; 202 203 cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; 203 204 id_resolver_cache = cred;
+1
include/linux/key.h
··· 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
+1
net/dns_resolver/dns_key.c
··· 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;
+14 -1
security/keys/keyctl.c
··· 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;