diff options
-rw-r--r-- | Documentation/networking/dns_resolver.txt | 4 | ||||
-rw-r--r-- | Documentation/security/keys.txt | 4 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 1 | ||||
-rw-r--r-- | fs/nfs/idmap.c | 1 | ||||
-rw-r--r-- | include/linux/key.h | 1 | ||||
-rw-r--r-- | net/dns_resolver/dns_key.c | 1 | ||||
-rw-r--r-- | security/keys/keyctl.c | 15 |
7 files changed, 26 insertions, 1 deletions
diff --git a/Documentation/networking/dns_resolver.txt b/Documentation/networking/dns_resolver.txt index 7f531ad83285..d86adcdae420 100644 --- a/Documentation/networking/dns_resolver.txt +++ b/Documentation/networking/dns_resolver.txt | |||
@@ -102,6 +102,10 @@ implemented in the module can be called after doing: | |||
102 | If _expiry is non-NULL, the expiry time (TTL) of the result will be | 102 | If _expiry is non-NULL, the expiry time (TTL) of the result will be |
103 | returned also. | 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 | READING DNS KEYS FROM USERSPACE | 111 | READING DNS KEYS FROM USERSPACE |
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 4d75931d2d79..713ec232c562 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt | |||
@@ -554,6 +554,10 @@ The keyctl syscall functions are: | |||
554 | process must have write permission on the keyring, and it must be a | 554 | process must have write permission on the keyring, and it must be a |
555 | keyring (or else error ENOTDIR will result). | 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 | (*) Link a key into a keyring: | 562 | (*) Link a key into a keyring: |
559 | 563 | ||
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 72ddf23ef6f7..854749d21bb1 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -556,6 +556,7 @@ init_cifs_idmap(void) | |||
556 | 556 | ||
557 | /* instruct request_key() to use this special keyring as a cache for | 557 | /* instruct request_key() to use this special keyring as a cache for |
558 | * the results it looks up */ | 558 | * the results it looks up */ |
559 | set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); | ||
559 | cred->thread_keyring = keyring; | 560 | cred->thread_keyring = keyring; |
560 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | 561 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; |
561 | root_cred = cred; | 562 | root_cred = cred; |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 2c05f1991e1e..a1bbf7780dfc 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -198,6 +198,7 @@ int nfs_idmap_init(void) | |||
198 | if (ret < 0) | 198 | if (ret < 0) |
199 | goto failed_put_key; | 199 | goto failed_put_key; |
200 | 200 | ||
201 | set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); | ||
201 | cred->thread_keyring = keyring; | 202 | cred->thread_keyring = keyring; |
202 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | 203 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; |
203 | id_resolver_cache = cred; | 204 | id_resolver_cache = cred; |
diff --git a/include/linux/key.h b/include/linux/key.h index 183a6af7715d..3ac412855d83 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -155,6 +155,7 @@ struct key { | |||
155 | #define KEY_FLAG_IN_QUOTA 3 /* set if key consumes quota */ | 155 | #define KEY_FLAG_IN_QUOTA 3 /* set if key consumes quota */ |
156 | #define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */ | 156 | #define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */ |
157 | #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ | 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 | /* the description string | 160 | /* the description string |
160 | * - this is used to match a key against search criteria | 161 | * - this is used to match a key against search criteria |
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index fa000d26dc60..c73bba326d70 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c | |||
@@ -281,6 +281,7 @@ static int __init init_dns_resolver(void) | |||
281 | 281 | ||
282 | /* instruct request_key() to use this special keyring as a cache for | 282 | /* instruct request_key() to use this special keyring as a cache for |
283 | * the results it looks up */ | 283 | * the results it looks up */ |
284 | set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); | ||
284 | cred->thread_keyring = keyring; | 285 | cred->thread_keyring = keyring; |
285 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | 286 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; |
286 | dns_resolver_cache = cred; | 287 | dns_resolver_cache = cred; |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 0b3f5d72af1c..6523599e9ac0 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -388,11 +388,24 @@ long keyctl_keyring_clear(key_serial_t ringid) | |||
388 | keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); | 388 | keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); |
389 | if (IS_ERR(keyring_ref)) { | 389 | if (IS_ERR(keyring_ref)) { |
390 | ret = PTR_ERR(keyring_ref); | 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 | goto error; | 403 | goto error; |
392 | } | 404 | } |
393 | 405 | ||
406 | clear: | ||
394 | ret = keyring_clear(key_ref_to_ptr(keyring_ref)); | 407 | ret = keyring_clear(key_ref_to_ptr(keyring_ref)); |
395 | 408 | error_put: | |
396 | key_ref_put(keyring_ref); | 409 | key_ref_put(keyring_ref); |
397 | error: | 410 | error: |
398 | return ret; | 411 | return ret; |