aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/idmap.c2
-rw-r--r--include/linux/key.h1
-rw-r--r--net/dns_resolver/dns_query.c1
-rw-r--r--security/keys/keyctl.c15
4 files changed, 18 insertions, 1 deletions
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 567983d2c0eb..b7458d77f511 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -282,6 +282,8 @@ static struct key *nfs_idmap_request_key(const char *name, size_t namelen,
282 desc, "", 0, idmap); 282 desc, "", 0, idmap);
283 mutex_unlock(&idmap->idmap_mutex); 283 mutex_unlock(&idmap->idmap_mutex);
284 } 284 }
285 if (!IS_ERR(rkey))
286 set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags);
285 287
286 kfree(desc); 288 kfree(desc);
287 return rkey; 289 return rkey;
diff --git a/include/linux/key.h b/include/linux/key.h
index 017b0826642f..e37a4d807185 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -170,6 +170,7 @@ struct key {
170#define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ 170#define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */
171#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */ 171#define KEY_FLAG_TRUSTED 8 /* set if key is trusted */
172#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */ 172#define KEY_FLAG_TRUSTED_ONLY 9 /* set if keyring only accepts links to trusted keys */
173#define KEY_FLAG_ROOT_CAN_INVAL 11 /* set if key can be invalidated by root without permission */
173 174
174 /* the key type and key description string 175 /* the key type and key description string
175 * - the desc is used to match a key against search criteria 176 * - the desc is used to match a key against search criteria
diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c
index 9acec61f5433..9a32f55cf9b9 100644
--- a/net/dns_resolver/dns_query.c
+++ b/net/dns_resolver/dns_query.c
@@ -129,6 +129,7 @@ int dns_query(const char *type, const char *name, size_t namelen,
129 } 129 }
130 130
131 down_read(&rkey->sem); 131 down_read(&rkey->sem);
132 set_bit(KEY_FLAG_ROOT_CAN_INVAL, &rkey->flags);
132 rkey->perm |= KEY_USR_VIEW; 133 rkey->perm |= KEY_USR_VIEW;
133 134
134 ret = key_validate(rkey); 135 ret = key_validate(rkey);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index cd5bd0cef25d..609f8d326ddc 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -404,12 +404,25 @@ long keyctl_invalidate_key(key_serial_t id)
404 key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH); 404 key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH);
405 if (IS_ERR(key_ref)) { 405 if (IS_ERR(key_ref)) {
406 ret = PTR_ERR(key_ref); 406 ret = PTR_ERR(key_ref);
407
408 /* Root is permitted to invalidate certain special keys */
409 if (capable(CAP_SYS_ADMIN)) {
410 key_ref = lookup_user_key(id, 0, 0);
411 if (IS_ERR(key_ref))
412 goto error;
413 if (test_bit(KEY_FLAG_ROOT_CAN_INVAL,
414 &key_ref_to_ptr(key_ref)->flags))
415 goto invalidate;
416 goto error_put;
417 }
418
407 goto error; 419 goto error;
408 } 420 }
409 421
422invalidate:
410 key_invalidate(key_ref_to_ptr(key_ref)); 423 key_invalidate(key_ref_to_ptr(key_ref));
411 ret = 0; 424 ret = 0;
412 425error_put:
413 key_ref_put(key_ref); 426 key_ref_put(key_ref);
414error: 427error:
415 kleave(" = %ld", ret); 428 kleave(" = %ld", ret);