[PATCH 2/2] keyring: allow special keyrings to be cleared

Steve Dickson steved at redhat.com
Wed Dec 14 19:10:04 UTC 2011


Signed-off-by: Steve Dickson <steved at redhat.com>
---
 kernel.spec                                |    3 +
 linux-3.1-keys-remove-specal-keyring.patch |  110 ++++++++++++++++++++++++++++
 2 files changed, 113 insertions(+), 0 deletions(-)
 create mode 100644 linux-3.1-keys-remove-specal-keyring.patch

diff --git a/kernel.spec b/kernel.spec
index 6e1d3fb..baa6eac 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -697,6 +697,7 @@ Patch2901: linux-2.6-v4l-dvb-experimental.patch
 # fs fixes
 
 # NFSv4
+Patch1101: linux-3.1-keys-remove-specal-keyring.patch
 
 # patches headed upstream
 Patch12016: disable-i8042-check-on-apple-mac.patch
@@ -1297,6 +1298,7 @@ ApplyPatch arm-smsc-support-reading-mac-address-from-device-tree.patch
 # eCryptfs
 
 # NFSv4
+ApplyPatch linux-3.1-keys-remove-specal-keyring.patch
 
 # USB
 
@@ -2231,6 +2233,7 @@ fi
 %changelog
 * Wed Dec 14 2011 Steve Dickson <steved at redhat.com>
 - Enabled the in-kernel idmapper.
+- keyring: allow special keyrings to be cleared 
 
 * Tue Dec 13 2011 Dave Jones <davej at redhat.com> - 3.2.0-0.rc5.git1.1
 - Linux 3.2-rc5-git1 (442ee5a942834431ccf0b412e3cf7bb9ae97ff4e)
diff --git a/linux-3.1-keys-remove-specal-keyring.patch b/linux-3.1-keys-remove-specal-keyring.patch
new file mode 100644
index 0000000..4e7f139
--- /dev/null
+++ b/linux-3.1-keys-remove-specal-keyring.patch
@@ -0,0 +1,110 @@
+diff -up linux-3.1.x86_64/Documentation/networking/dns_resolver.txt.orig linux-3.1.x86_64/Documentation/networking/dns_resolver.txt
+--- linux-3.1.x86_64/Documentation/networking/dns_resolver.txt.orig	2011-10-24 03:10:05.000000000 -0400
++++ linux-3.1.x86_64/Documentation/networking/dns_resolver.txt	2011-12-13 15:09:35.705766078 -0500
+@@ -102,6 +102,10 @@ implemented in the module can be called
+      If _expiry is non-NULL, the expiry time (TTL) of the result will be
+      returned also.
+ 
++The kernel maintains an internal keyring in which it caches looked up keys.
++This can be cleared by any process that has the CAP_SYS_ADMIN capability by
++the use of KEYCTL_KEYRING_CLEAR on the keyring ID.
++
+ 
+ ===============================
+ READING DNS KEYS FROM USERSPACE
+diff -up linux-3.1.x86_64/Documentation/security/keys.txt.orig linux-3.1.x86_64/Documentation/security/keys.txt
+--- linux-3.1.x86_64/Documentation/security/keys.txt.orig	2011-10-24 03:10:05.000000000 -0400
++++ linux-3.1.x86_64/Documentation/security/keys.txt	2011-12-13 15:09:35.706766099 -0500
+@@ -554,6 +554,10 @@ The keyctl syscall functions are:
+      process must have write permission on the keyring, and it must be a
+      keyring (or else error ENOTDIR will result).
+ 
++     This function can also be used to clear special kernel keyrings if they
++     are appropriately marked if the user has CAP_SYS_ADMIN capability.  The
++     DNS resolver cache keyring is an example of this.
++
+ 
+  (*) Link a key into a keyring:
+ 
+diff -up linux-3.1.x86_64/fs/cifs/cifsacl.c.orig linux-3.1.x86_64/fs/cifs/cifsacl.c
+--- linux-3.1.x86_64/fs/cifs/cifsacl.c.orig	2011-12-13 12:54:12.221145867 -0500
++++ linux-3.1.x86_64/fs/cifs/cifsacl.c	2011-12-13 15:09:35.707766122 -0500
+@@ -556,6 +556,7 @@ init_cifs_idmap(void)
+ 
+ 	/* instruct request_key() to use this special keyring as a cache for
+ 	 * the results it looks up */
++	set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
+ 	cred->thread_keyring = keyring;
+ 	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+ 	root_cred = cred;
+diff -up linux-3.1.x86_64/fs/nfs/idmap.c.orig linux-3.1.x86_64/fs/nfs/idmap.c
+--- linux-3.1.x86_64/fs/nfs/idmap.c.orig	2011-12-13 12:54:14.657203507 -0500
++++ linux-3.1.x86_64/fs/nfs/idmap.c	2011-12-13 15:10:14.731681691 -0500
+@@ -115,6 +115,7 @@ int nfs_idmap_init(void)
+ 	if (ret < 0)
+ 		goto failed_put_key;
+ 
++	set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
+ 	cred->thread_keyring = keyring;
+ 	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+ 	id_resolver_cache = cred;
+@@ -185,7 +186,7 @@ static ssize_t nfs_idmap_request_key(con
+ 	}
+ 
+ 	rcu_read_lock();
+-	rkey->perm |= KEY_USR_VIEW;
++	rkey->perm |= KEY_USR_VIEW|KEY_USR_WRITE;
+ 
+ 	ret = key_validate(rkey);
+ 	if (ret < 0)
+diff -up linux-3.1.x86_64/include/linux/key.h.orig linux-3.1.x86_64/include/linux/key.h
+--- linux-3.1.x86_64/include/linux/key.h.orig	2011-10-24 03:10:05.000000000 -0400
++++ linux-3.1.x86_64/include/linux/key.h	2011-12-13 15:09:35.748767078 -0500
+@@ -155,6 +155,7 @@ struct key {
+ #define KEY_FLAG_IN_QUOTA	3	/* set if key consumes quota */
+ #define KEY_FLAG_USER_CONSTRUCT	4	/* set if key is being constructed in userspace */
+ #define KEY_FLAG_NEGATIVE	5	/* set if key is negative */
++#define KEY_FLAG_ROOT_CAN_CLEAR	6	/* set if key can be cleared by root without permission */
+ 
+ 	/* the description string
+ 	 * - this is used to match a key against search criteria
+diff -up linux-3.1.x86_64/net/dns_resolver/dns_key.c.orig linux-3.1.x86_64/net/dns_resolver/dns_key.c
+--- linux-3.1.x86_64/net/dns_resolver/dns_key.c.orig	2011-10-24 03:10:05.000000000 -0400
++++ linux-3.1.x86_64/net/dns_resolver/dns_key.c	2011-12-13 15:09:35.748767078 -0500
+@@ -281,6 +281,7 @@ static int __init init_dns_resolver(void
+ 
+ 	/* instruct request_key() to use this special keyring as a cache for
+ 	 * the results it looks up */
++	set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
+ 	cred->thread_keyring = keyring;
+ 	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+ 	dns_resolver_cache = cred;
+diff -up linux-3.1.x86_64/security/keys/keyctl.c.orig linux-3.1.x86_64/security/keys/keyctl.c
+--- linux-3.1.x86_64/security/keys/keyctl.c.orig	2011-12-13 12:54:30.322571289 -0500
++++ linux-3.1.x86_64/security/keys/keyctl.c	2011-12-13 15:09:35.756767271 -0500
+@@ -388,11 +388,24 @@ long keyctl_keyring_clear(key_serial_t r
+ 	keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
+ 	if (IS_ERR(keyring_ref)) {
+ 		ret = PTR_ERR(keyring_ref);
++
++		/* Root is permitted to invalidate certain special keyrings */
++		if (capable(CAP_SYS_ADMIN)) {
++			keyring_ref = lookup_user_key(ringid, 0, 0);
++			if (IS_ERR(keyring_ref))
++				goto error;
++			if (test_bit(KEY_FLAG_ROOT_CAN_CLEAR,
++				     &key_ref_to_ptr(keyring_ref)->flags))
++				goto clear;
++			goto error_put;
++		}
++
+ 		goto error;
+ 	}
+ 
++clear:
+ 	ret = keyring_clear(key_ref_to_ptr(keyring_ref));
+-
++error_put:
+ 	key_ref_put(keyring_ref);
+ error:
+ 	return ret;
-- 
1.7.7.3



More information about the kernel mailing list