mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/6] Keys: Key management updates  [try #3]
@ 2006-06-20 17:37 David Howells
  2006-06-20 17:37 ` [PATCH 1/6] Keys: Sort out key quota system " David Howells
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: David Howells @ 2006-06-20 17:37 UTC (permalink / raw)
  To: torvalds, akpm; +Cc: linux-kernel, keyrings


These patches update a few key management related things, mainly security
related.  They have the following prerequisite patches from Andrew Morton's -mm
tree:

	selinux-add-hooks-for-key-subsystem.patch
	keys-fix-race-between-two-instantiators-of-a-key.patch

Some of these patches have been modified from the originals I've been given so
that they'll all apply in sequence.

David

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/6] Keys: Sort out key quota system [try #3]
  2006-06-20 17:37 [PATCH 0/6] Keys: Key management updates [try #3] David Howells
@ 2006-06-20 17:37 ` David Howells
  2006-06-20 17:37 ` [PATCH 2/6] Keys: Discard the contents of a key on revocation " David Howells
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Howells @ 2006-06-20 17:37 UTC (permalink / raw)
  To: torvalds, akpm; +Cc: linux-kernel, keyrings

From: David Howells <dhowells@redhat.com>

The attached patch adds the ability for key creation to overrun the user's
quota in some circumstances - notably when a session keyring is created and
assigned to a process that didn't previously have one.

This means it's still possible to log in, should PAM require the creation of a
new session keyring, and fix an overburdened key quota.

Signed-Off-By: David Howells <dhowells@redhat.com>
---

 include/linux/key.h              |   13 ++++++++++---
 include/linux/security.h         |   11 +++++++----
 security/dummy.c                 |    3 ++-
 security/keys/internal.h         |    3 ++-
 security/keys/key.c              |   26 ++++++++++++++------------
 security/keys/keyctl.c           |    5 +++--
 security/keys/keyring.c          |    4 ++--
 security/keys/process_keys.c     |   24 +++++++++++++++++-------
 security/keys/request_key.c      |   36 +++++++++++++++++++++---------------
 security/keys/request_key_auth.c |    2 +-
 security/selinux/hooks.c         |    9 ++++++---
 11 files changed, 85 insertions(+), 51 deletions(-)

diff --git a/include/linux/key.h b/include/linux/key.h
index e81ebf9..e693e72 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -248,7 +248,14 @@ extern struct key *key_alloc(struct key_
 			     const char *desc,
 			     uid_t uid, gid_t gid,
 			     struct task_struct *ctx,
-			     key_perm_t perm, int not_in_quota);
+			     key_perm_t perm,
+			     unsigned long flags);
+
+
+#define KEY_ALLOC_IN_QUOTA	0x0000	/* add to quota, reject if would overrun */
+#define KEY_ALLOC_QUOTA_OVERRUN	0x0001	/* add to quota, permit even if overrun */
+#define KEY_ALLOC_NOT_IN_QUOTA	0x0002	/* not in quota */
+
 extern int key_payload_reserve(struct key *key, size_t datalen);
 extern int key_instantiate_and_link(struct key *key,
 				    const void *data,
@@ -285,7 +292,7 @@ extern key_ref_t key_create_or_update(ke
 				      const char *description,
 				      const void *payload,
 				      size_t plen,
-				      int not_in_quota);
+				      unsigned long flags);
 
 extern int key_update(key_ref_t key,
 		      const void *payload,
@@ -299,7 +306,7 @@ extern int key_unlink(struct key *keyrin
 
 extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
 				 struct task_struct *ctx,
-				 int not_in_quota,
+				 unsigned long flags,
 				 struct key *dest);
 
 extern int keyring_clear(struct key *keyring);
diff --git a/include/linux/security.h b/include/linux/security.h
index 383c320..d4aa1bf 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -853,6 +853,7 @@ #ifdef CONFIG_SECURITY
  *	Permit allocation of a key and assign security data. Note that key does
  *	not have a serial number assigned at this point.
  *	@key points to the key.
+ *	@flags is the allocation flags
  *	Return 0 if permission is granted, -ve error otherwise.
  * @key_free:
  *	Notification of destruction; free security data.
@@ -1313,7 +1314,7 @@ #endif	/* CONFIG_SECURITY_NETWORK_XFRM *
 
 	/* key management security hooks */
 #ifdef CONFIG_KEYS
-	int (*key_alloc)(struct key *key, struct task_struct *tsk);
+	int (*key_alloc)(struct key *key, struct task_struct *tsk, unsigned long flags);
 	void (*key_free)(struct key *key);
 	int (*key_permission)(key_ref_t key_ref,
 			      struct task_struct *context,
@@ -3009,9 +3010,10 @@ #endif	/* CONFIG_SECURITY_NETWORK_XFRM *
 #ifdef CONFIG_KEYS
 #ifdef CONFIG_SECURITY
 static inline int security_key_alloc(struct key *key,
-				     struct task_struct *tsk)
+				     struct task_struct *tsk,
+				     unsigned long flags)
 {
-	return security_ops->key_alloc(key, tsk);
+	return security_ops->key_alloc(key, tsk, flags);
 }
 
 static inline void security_key_free(struct key *key)
@@ -3029,7 +3031,8 @@ static inline int security_key_permissio
 #else
 
 static inline int security_key_alloc(struct key *key,
-				     struct task_struct *tsk)
+				     struct task_struct *tsk,
+				     unsigned long flags)
 {
 	return 0;
 }
diff --git a/security/dummy.c b/security/dummy.c
index c98d553..93a9180 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -860,7 +860,8 @@ static int dummy_setprocattr(struct task
 }
 
 #ifdef CONFIG_KEYS
-static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx)
+static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx,
+				  unsigned long flags)
 {
 	return 0;
 }
diff --git a/security/keys/internal.h b/security/keys/internal.h
index e066e60..3c2877f 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -99,7 +99,8 @@ extern int install_process_keyring(struc
 extern struct key *request_key_and_link(struct key_type *type,
 					const char *description,
 					const char *callout_info,
-					struct key *dest_keyring);
+					struct key *dest_keyring,
+					unsigned long flags);
 
 /*
  * request_key authorisation
diff --git a/security/keys/key.c b/security/keys/key.c
index 9ef9e5b..a9b6ca7 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -248,7 +248,7 @@ static inline void key_alloc_serial(stru
  */
 struct key *key_alloc(struct key_type *type, const char *desc,
 		      uid_t uid, gid_t gid, struct task_struct *ctx,
-		      key_perm_t perm, int not_in_quota)
+		      key_perm_t perm, unsigned long flags)
 {
 	struct key_user *user = NULL;
 	struct key *key;
@@ -269,12 +269,14 @@ struct key *key_alloc(struct key_type *t
 
 	/* check that the user's quota permits allocation of another key and
 	 * its description */
-	if (!not_in_quota) {
+	if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
 		spin_lock(&user->lock);
-		if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
-		    user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
-		    )
-			goto no_quota;
+		if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
+			if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
+			    user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
+			    )
+				goto no_quota;
+		}
 
 		user->qnkeys++;
 		user->qnbytes += quotalen;
@@ -308,7 +310,7 @@ struct key *key_alloc(struct key_type *t
 	key->payload.data = NULL;
 	key->security = NULL;
 
-	if (!not_in_quota)
+	if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
 		key->flags |= 1 << KEY_FLAG_IN_QUOTA;
 
 	memset(&key->type_data, 0, sizeof(key->type_data));
@@ -318,7 +320,7 @@ #ifdef KEY_DEBUGGING
 #endif
 
 	/* let the security module know about the key */
-	ret = security_key_alloc(key, ctx);
+	ret = security_key_alloc(key, ctx, flags);
 	if (ret < 0)
 		goto security_error;
 
@@ -332,7 +334,7 @@ error:
 security_error:
 	kfree(key->description);
 	kmem_cache_free(key_jar, key);
-	if (!not_in_quota) {
+	if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
 		spin_lock(&user->lock);
 		user->qnkeys--;
 		user->qnbytes -= quotalen;
@@ -345,7 +347,7 @@ security_error:
 no_memory_3:
 	kmem_cache_free(key_jar, key);
 no_memory_2:
-	if (!not_in_quota) {
+	if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
 		spin_lock(&user->lock);
 		user->qnkeys--;
 		user->qnbytes -= quotalen;
@@ -761,7 +763,7 @@ key_ref_t key_create_or_update(key_ref_t
 			       const char *description,
 			       const void *payload,
 			       size_t plen,
-			       int not_in_quota)
+			       unsigned long flags)
 {
 	struct key_type *ktype;
 	struct key *keyring, *key = NULL;
@@ -822,7 +824,7 @@ key_ref_t key_create_or_update(key_ref_t
 
 	/* allocate a new key */
 	key = key_alloc(ktype, description, current->fsuid, current->fsgid,
-			current, perm, not_in_quota);
+			current, perm, flags);
 	if (IS_ERR(key)) {
 		key_ref = ERR_PTR(PTR_ERR(key));
 		goto error_3;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index ed71d86..d744585 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -102,7 +102,7 @@ asmlinkage long sys_add_key(const char _
 	/* create or update the requested key and add it to the target
 	 * keyring */
 	key_ref = key_create_or_update(keyring_ref, type, description,
-				       payload, plen, 0);
+				       payload, plen, KEY_ALLOC_IN_QUOTA);
 	if (!IS_ERR(key_ref)) {
 		ret = key_ref_to_ptr(key_ref)->serial;
 		key_ref_put(key_ref);
@@ -184,7 +184,8 @@ asmlinkage long sys_request_key(const ch
 
 	/* do the search */
 	key = request_key_and_link(ktype, description, callout_info,
-				   key_ref_to_ptr(dest_ref));
+				   key_ref_to_ptr(dest_ref),
+				   KEY_ALLOC_IN_QUOTA);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
 		goto error5;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 1357207..6c282bd 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -240,7 +240,7 @@ static long keyring_read(const struct ke
  * allocate a keyring and link into the destination keyring
  */
 struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
-			  struct task_struct *ctx, int not_in_quota,
+			  struct task_struct *ctx, unsigned long flags,
 			  struct key *dest)
 {
 	struct key *keyring;
@@ -249,7 +249,7 @@ struct key *keyring_alloc(const char *de
 	keyring = key_alloc(&key_type_keyring, description,
 			    uid, gid, ctx,
 			    (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
-			    not_in_quota);
+			    flags);
 
 	if (!IS_ERR(keyring)) {
 		ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index e4eddbb..f5fbc37 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -77,7 +77,8 @@ int alloc_uid_keyring(struct user_struct
 	/* concoct a default session keyring */
 	sprintf(buf, "_uid_ses.%u", user->uid);
 
-	session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, NULL);
+	session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
+					KEY_ALLOC_IN_QUOTA, NULL);
 	if (IS_ERR(session_keyring)) {
 		ret = PTR_ERR(session_keyring);
 		goto error;
@@ -87,8 +88,8 @@ int alloc_uid_keyring(struct user_struct
 	 * keyring */
 	sprintf(buf, "_uid.%u", user->uid);
 
-	uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0,
-				    session_keyring);
+	uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
+				    KEY_ALLOC_IN_QUOTA, session_keyring);
 	if (IS_ERR(uid_keyring)) {
 		key_put(session_keyring);
 		ret = PTR_ERR(uid_keyring);
@@ -144,7 +145,8 @@ int install_thread_keyring(struct task_s
 
 	sprintf(buf, "_tid.%u", tsk->pid);
 
-	keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL);
+	keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+				KEY_ALLOC_QUOTA_OVERRUN, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto error;
@@ -178,7 +180,8 @@ int install_process_keyring(struct task_
 	if (!tsk->signal->process_keyring) {
 		sprintf(buf, "_pid.%u", tsk->tgid);
 
-		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL);
+		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+					KEY_ALLOC_QUOTA_OVERRUN, NULL);
 		if (IS_ERR(keyring)) {
 			ret = PTR_ERR(keyring);
 			goto error;
@@ -209,6 +212,7 @@ error:
 static int install_session_keyring(struct task_struct *tsk,
 				   struct key *keyring)
 {
+	unsigned long flags;
 	struct key *old;
 	char buf[20];
 
@@ -218,7 +222,12 @@ static int install_session_keyring(struc
 	if (!keyring) {
 		sprintf(buf, "_ses.%u", tsk->tgid);
 
-		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL);
+		flags = KEY_ALLOC_QUOTA_OVERRUN;
+		if (tsk->signal->session_keyring)
+			flags = KEY_ALLOC_IN_QUOTA;
+
+		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+					flags, NULL);
 		if (IS_ERR(keyring))
 			return PTR_ERR(keyring);
 	}
@@ -729,7 +738,8 @@ long join_session_keyring(const char *na
 	keyring = find_keyring_by_name(name, 0);
 	if (PTR_ERR(keyring) == -ENOKEY) {
 		/* not found - try and create a new one */
-		keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 0, NULL);
+		keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk,
+					KEY_ALLOC_IN_QUOTA, NULL);
 		if (IS_ERR(keyring)) {
 			ret = PTR_ERR(keyring);
 			goto error2;
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index eab66a0..58d1efd 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -48,8 +48,8 @@ static int call_sbin_request_key(struct 
 	/* allocate a new session keyring */
 	sprintf(desc, "_req.%u", key->serial);
 
-	keyring = keyring_alloc(desc, current->fsuid, current->fsgid,
-				current, 1, NULL);
+	keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current,
+				KEY_ALLOC_QUOTA_OVERRUN, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto error_alloc;
@@ -126,7 +126,8 @@ error_alloc:
  */
 static struct key *__request_key_construction(struct key_type *type,
 					      const char *description,
-					      const char *callout_info)
+					      const char *callout_info,
+					      unsigned long flags)
 {
 	request_key_actor_t actor;
 	struct key_construction cons;
@@ -134,12 +135,12 @@ static struct key *__request_key_constru
 	struct key *key, *authkey;
 	int ret, negated;
 
-	kenter("%s,%s,%s", type->name, description, callout_info);
+	kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags);
 
 	/* create a key and add it to the queue */
 	key = key_alloc(type, description,
-			current->fsuid, current->fsgid,
-			current, KEY_POS_ALL, 0);
+			current->fsuid, current->fsgid, current, KEY_POS_ALL,
+			flags);
 	if (IS_ERR(key))
 		goto alloc_failed;
 
@@ -258,15 +259,16 @@ alloc_failed:
 static struct key *request_key_construction(struct key_type *type,
 					    const char *description,
 					    struct key_user *user,
-					    const char *callout_info)
+					    const char *callout_info,
+					    unsigned long flags)
 {
 	struct key_construction *pcons;
 	struct key *key, *ckey;
 
 	DECLARE_WAITQUEUE(myself, current);
 
-	kenter("%s,%s,{%d},%s",
-	       type->name, description, user->uid, callout_info);
+	kenter("%s,%s,{%d},%s,%lx",
+	       type->name, description, user->uid, callout_info, flags);
 
 	/* see if there's such a key under construction already */
 	down_write(&key_construction_sem);
@@ -282,7 +284,8 @@ static struct key *request_key_construct
 	}
 
 	/* see about getting userspace to construct the key */
-	key = __request_key_construction(type, description, callout_info);
+	key = __request_key_construction(type, description, callout_info,
+					 flags);
  error:
 	kleave(" = %p", key);
 	return key;
@@ -389,14 +392,15 @@ static void request_key_link(struct key 
 struct key *request_key_and_link(struct key_type *type,
 				 const char *description,
 				 const char *callout_info,
-				 struct key *dest_keyring)
+				 struct key *dest_keyring,
+				 unsigned long flags)
 {
 	struct key_user *user;
 	struct key *key;
 	key_ref_t key_ref;
 
-	kenter("%s,%s,%s,%p",
-	       type->name, description, callout_info, dest_keyring);
+	kenter("%s,%s,%s,%p,%lx",
+	       type->name, description, callout_info, dest_keyring, flags);
 
 	/* search all the process keyrings for a key */
 	key_ref = search_process_keyrings(type, description, type->match,
@@ -429,7 +433,8 @@ struct key *request_key_and_link(struct 
 			/* ask userspace (returns NULL if it waited on a key
 			 * being constructed) */
 			key = request_key_construction(type, description,
-						       user, callout_info);
+						       user, callout_info,
+						       flags);
 			if (key)
 				break;
 
@@ -485,7 +490,8 @@ struct key *request_key(struct key_type 
 			const char *description,
 			const char *callout_info)
 {
-	return request_key_and_link(type, description, callout_info, NULL);
+	return request_key_and_link(type, description, callout_info, NULL,
+				    KEY_ALLOC_IN_QUOTA);
 
 } /* end request_key() */
 
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index cb9817c..cbf58a9 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -187,7 +187,7 @@ struct key *request_key_auth_new(struct 
 	authkey = key_alloc(&key_type_request_key_auth, desc,
 			    current->fsuid, current->fsgid, current,
 			    KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
-			    KEY_USR_VIEW, 1);
+			    KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
 	if (IS_ERR(authkey)) {
 		ret = PTR_ERR(authkey);
 		goto error_alloc;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 093efba..f80c74d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4254,7 +4254,8 @@ static int selinux_setprocattr(struct ta
 
 #ifdef CONFIG_KEYS
 
-static int selinux_key_alloc(struct key *k, struct task_struct *tsk)
+static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
+			     unsigned long flags)
 {
 	struct task_security_struct *tsec = tsk->security;
 	struct key_security_struct *ksec;
@@ -4501,8 +4502,10 @@ static __init int selinux_init(void)
 
 #ifdef CONFIG_KEYS
 	/* Add security information to initial keyrings */
-	security_key_alloc(&root_user_keyring, current);
-	security_key_alloc(&root_session_keyring, current);
+	security_key_alloc(&root_user_keyring, current,
+			   KEY_ALLOC_NOT_IN_QUOTA);
+	security_key_alloc(&root_session_keyring, current,
+			   KEY_ALLOC_NOT_IN_QUOTA);
 #endif
 
 	return 0;


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2/6] Keys: Discard the contents of a key on revocation [try #3]
  2006-06-20 17:37 [PATCH 0/6] Keys: Key management updates [try #3] David Howells
  2006-06-20 17:37 ` [PATCH 1/6] Keys: Sort out key quota system " David Howells
@ 2006-06-20 17:37 ` David Howells
  2006-06-20 17:37 ` [PATCH 3/6] Keys: Let keyctl_chown() change a key's owner " David Howells
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Howells @ 2006-06-20 17:37 UTC (permalink / raw)
  To: torvalds, akpm; +Cc: linux-kernel, keyrings

From: David Howells <dhowells@redhat.com>

The attached patch causes the keys linked to a keyring to be unlinked from it
when revoked and it causes the data attached to a user-defined key to be
discarded when revoked.

This frees up most of the quota a key occupied at that point, rather than
waiting for the key to actually be destroyed.

Signed-Off-By: David Howells <dhowells@redhat.com>
---

 include/keys/user-type.h     |    1 +
 security/keys/keyring.c      |   21 +++++++++++++++++++++
 security/keys/user_defined.c |   25 ++++++++++++++++++++++++-
 3 files changed, 46 insertions(+), 1 deletions(-)

diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index a3dae18..c37c342 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -37,6 +37,7 @@ extern struct key_type key_type_user;
 extern int user_instantiate(struct key *key, const void *data, size_t datalen);
 extern int user_update(struct key *key, const void *data, size_t datalen);
 extern int user_match(const struct key *key, const void *criterion);
+extern void user_revoke(struct key *key);
 extern void user_destroy(struct key *key);
 extern void user_describe(const struct key *user, struct seq_file *m);
 extern long user_read(const struct key *key,
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 6c282bd..e8d02ac 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -49,6 +49,7 @@ static inline unsigned keyring_hash(cons
 static int keyring_instantiate(struct key *keyring,
 			       const void *data, size_t datalen);
 static int keyring_match(const struct key *keyring, const void *criterion);
+static void keyring_revoke(struct key *keyring);
 static void keyring_destroy(struct key *keyring);
 static void keyring_describe(const struct key *keyring, struct seq_file *m);
 static long keyring_read(const struct key *keyring,
@@ -59,6 +60,7 @@ struct key_type key_type_keyring = {
 	.def_datalen	= sizeof(struct keyring_list),
 	.instantiate	= keyring_instantiate,
 	.match		= keyring_match,
+	.revoke		= keyring_revoke,
 	.destroy	= keyring_destroy,
 	.describe	= keyring_describe,
 	.read		= keyring_read,
@@ -953,3 +955,22 @@ int keyring_clear(struct key *keyring)
 } /* end keyring_clear() */
 
 EXPORT_SYMBOL(keyring_clear);
+
+/*****************************************************************************/
+/*
+ * dispose of the links from a revoked keyring
+ * - called with the key sem write-locked
+ */
+static void keyring_revoke(struct key *keyring)
+{
+	struct keyring_list *klist = keyring->payload.subscriptions;
+
+	/* adjust the quota */
+	key_payload_reserve(keyring, 0);
+
+	if (klist) {
+		rcu_assign_pointer(keyring->payload.subscriptions, NULL);
+		call_rcu(&klist->rcu, keyring_clear_rcu_disposal);
+	}
+
+} /* end keyring_revoke() */
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 8e71895..5bbfdeb 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -28,6 +28,7 @@ struct key_type key_type_user = {
 	.instantiate	= user_instantiate,
 	.update		= user_update,
 	.match		= user_match,
+	.revoke		= user_revoke,
 	.destroy	= user_destroy,
 	.describe	= user_describe,
 	.read		= user_read,
@@ -67,6 +68,7 @@ error:
 	return ret;
 
 } /* end user_instantiate() */
+
 EXPORT_SYMBOL_GPL(user_instantiate);
 
 /*****************************************************************************/
@@ -141,7 +143,28 @@ EXPORT_SYMBOL_GPL(user_match);
 
 /*****************************************************************************/
 /*
- * dispose of the data dangling from the corpse of a user
+ * dispose of the links from a revoked keyring
+ * - called with the key sem write-locked
+ */
+void user_revoke(struct key *key)
+{
+	struct user_key_payload *upayload = key->payload.data;
+
+	/* clear the quota */
+	key_payload_reserve(key, 0);
+
+	if (upayload) {
+		rcu_assign_pointer(key->payload.data, NULL);
+		call_rcu(&upayload->rcu, user_update_rcu_disposal);
+	}
+
+} /* end user_revoke() */
+
+EXPORT_SYMBOL(user_revoke);
+
+/*****************************************************************************/
+/*
+ * dispose of the data dangling from the corpse of a user key
  */
 void user_destroy(struct key *key)
 {


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/6] Keys: Let keyctl_chown() change a key's owner [try #3]
  2006-06-20 17:37 [PATCH 0/6] Keys: Key management updates [try #3] David Howells
  2006-06-20 17:37 ` [PATCH 1/6] Keys: Sort out key quota system " David Howells
  2006-06-20 17:37 ` [PATCH 2/6] Keys: Discard the contents of a key on revocation " David Howells
@ 2006-06-20 17:37 ` David Howells
  2006-06-20 17:37 ` [PATCH 4/6] Keys: Allocate key serial numbers randomly " David Howells
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Howells @ 2006-06-20 17:37 UTC (permalink / raw)
  To: torvalds, akpm; +Cc: linux-kernel, keyrings

From: Fredrik Tolf <fredrik@dolda2000.com>

The attached patch lets keyctl_chown() change a key's owner, including
attempting to transfer the quota burden to the new user.

Signed-Off-By: David Howells <dhowells@redhat.com>
---

 security/keys/keyctl.c |   56 +++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index d744585..329411c 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -673,6 +673,7 @@ long keyctl_read_key(key_serial_t keyid,
  */
 long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
 {
+	struct key_user *newowner, *zapowner = NULL;
 	struct key *key;
 	key_ref_t key_ref;
 	long ret;
@@ -696,19 +697,50 @@ long keyctl_chown_key(key_serial_t id, u
 	if (!capable(CAP_SYS_ADMIN)) {
 		/* only the sysadmin can chown a key to some other UID */
 		if (uid != (uid_t) -1 && key->uid != uid)
-			goto no_access;
+			goto error_put;
 
 		/* only the sysadmin can set the key's GID to a group other
 		 * than one of those that the current process subscribes to */
 		if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid))
-			goto no_access;
+			goto error_put;
 	}
 
-	/* change the UID (have to update the quotas) */
+	/* change the UID */
 	if (uid != (uid_t) -1 && uid != key->uid) {
-		/* don't support UID changing yet */
-		ret = -EOPNOTSUPP;
-		goto no_access;
+		ret = -ENOMEM;
+		newowner = key_user_lookup(uid);
+		if (!newowner)
+			goto error_put;
+
+		/* transfer the quota burden to the new user */
+		if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
+			spin_lock(&newowner->lock);
+			if (newowner->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
+			    newowner->qnbytes + key->quotalen >=
+			    KEYQUOTA_MAX_BYTES)
+				goto quota_overrun;
+
+			newowner->qnkeys++;
+			newowner->qnbytes += key->quotalen;
+			spin_unlock(&newowner->lock);
+
+			spin_lock(&key->user->lock);
+			key->user->qnkeys--;
+			key->user->qnbytes -= key->quotalen;
+			spin_unlock(&key->user->lock);
+		}
+
+		atomic_dec(&key->user->nkeys);
+		atomic_inc(&newowner->nkeys);
+
+		if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
+			atomic_dec(&key->user->nikeys);
+			atomic_inc(&newowner->nikeys);
+		}
+
+		zapowner = key->user;
+		key->user = newowner;
+		key->uid = uid;
 	}
 
 	/* change the GID */
@@ -717,12 +749,20 @@ long keyctl_chown_key(key_serial_t id, u
 
 	ret = 0;
 
- no_access:
+error_put:
 	up_write(&key->sem);
 	key_put(key);
- error:
+	if (zapowner)
+		key_user_put(zapowner);
+error:
 	return ret;
 
+quota_overrun:
+	spin_unlock(&newowner->lock);
+	zapowner = newowner;
+	ret = -EDQUOT;
+	goto error_put;
+
 } /* end keyctl_chown_key() */
 
 /*****************************************************************************/


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 4/6] Keys: Allocate key serial numbers randomly [try #3]
  2006-06-20 17:37 [PATCH 0/6] Keys: Key management updates [try #3] David Howells
                   ` (2 preceding siblings ...)
  2006-06-20 17:37 ` [PATCH 3/6] Keys: Let keyctl_chown() change a key's owner " David Howells
@ 2006-06-20 17:37 ` David Howells
  2006-06-20 17:37 ` [PATCH 5/6] Keys: Restrict contents of /proc/keys to Viewable keys " David Howells
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Howells @ 2006-06-20 17:37 UTC (permalink / raw)
  To: torvalds, akpm; +Cc: linux-kernel, keyrings

From: Michael LeMay <mdlemay@epoch.ncsc.mil>

The attached patch causes key_alloc_serial() to generate key serial numbers
randomly rather than in linear sequence.

Using an linear sequence permits a covert communication channel to be
established, in which one process can communicate with another by creating or
not creating new keys within a certain timeframe.  The second process can
probe for the expected next key serial number and judge its existence by the
error returned.

This is a problem as the serial number namespace is globally shared between
all tasks, regardless of their context.

For more information on this topic, this old TCSEC guide is recommended:

	http://www.radium.ncsc.mil/tpep/library/rainbow/NCSC-TG-030.html

Signed-off-by: Michael LeMay <mdlemay@epoch.ncsc.mil>
Signed-off-by: James Morris <jmorris@namei.org>
Signed-Off-By: David Howells <dhowells@redhat.com>
---

 security/keys/key.c |   28 ++++++++++++++--------------
 1 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/security/keys/key.c b/security/keys/key.c
index a9b6ca7..10fea8c 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -15,11 +15,11 @@ #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/security.h>
 #include <linux/workqueue.h>
+#include <linux/random.h>
 #include <linux/err.h>
 #include "internal.h"
 
 static kmem_cache_t	*key_jar;
-static key_serial_t	key_serial_next = 3;
 struct rb_root		key_serial_tree; /* tree of keys indexed by serial */
 DEFINE_SPINLOCK(key_serial_lock);
 
@@ -169,22 +169,23 @@ static void __init __key_insert_serial(s
 /*****************************************************************************/
 /*
  * assign a key the next unique serial number
- * - we work through all the serial numbers between 2 and 2^31-1 in turn and
- *   then wrap
+ * - these are assigned randomly to avoid security issues through covert
+ *   channel problems
  */
 static inline void key_alloc_serial(struct key *key)
 {
 	struct rb_node *parent, **p;
 	struct key *xkey;
 
-	spin_lock(&key_serial_lock);
-
-	/* propose a likely serial number and look for a hole for it in the
+	/* propose a random serial number and look for a hole for it in the
 	 * serial number tree */
-	key->serial = key_serial_next;
-	if (key->serial < 3)
-		key->serial = 3;
-	key_serial_next = key->serial + 1;
+	do {
+		get_random_bytes(&key->serial, sizeof(key->serial));
+
+		key->serial >>= 1; /* negative numbers are not permitted */
+	} while (key->serial < 3);
+
+	spin_lock(&key_serial_lock);
 
 	parent = NULL;
 	p = &key_serial_tree.rb_node;
@@ -204,12 +205,11 @@ static inline void key_alloc_serial(stru
 
 	/* we found a key with the proposed serial number - walk the tree from
 	 * that point looking for the next unused serial number */
- serial_exists:
+serial_exists:
 	for (;;) {
-		key->serial = key_serial_next;
+		key->serial++;
 		if (key->serial < 2)
 			key->serial = 2;
-		key_serial_next = key->serial + 1;
 
 		if (!parent->rb_parent)
 			p = &key_serial_tree.rb_node;
@@ -228,7 +228,7 @@ static inline void key_alloc_serial(stru
 	}
 
 	/* we've found a suitable hole - arrange for this key to occupy it */
- insert_here:
+insert_here:
 	rb_link_node(&key->serial_node, parent, p);
 	rb_insert_color(&key->serial_node, &key_serial_tree);
 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 5/6] Keys: Restrict contents of /proc/keys to Viewable keys [try #3]
  2006-06-20 17:37 [PATCH 0/6] Keys: Key management updates [try #3] David Howells
                   ` (3 preceding siblings ...)
  2006-06-20 17:37 ` [PATCH 4/6] Keys: Allocate key serial numbers randomly " David Howells
@ 2006-06-20 17:37 ` David Howells
  2006-06-20 17:37 ` [PATCH 6/6] Keys: Add a way to store the appropriate context for newly-created " David Howells
  2006-06-20 20:44 ` [Keyrings] [PATCH 0/6] Keys: Key management updates " James Morris
  6 siblings, 0 replies; 9+ messages in thread
From: David Howells @ 2006-06-20 17:37 UTC (permalink / raw)
  To: torvalds, akpm; +Cc: linux-kernel, keyrings

From: Michael LeMay <mdlemay@epoch.ncsc.mil>

This patch restricts /proc/keys such that only those keys to which the current
task is granted View permission are presented.

The documentation is also updated to reflect these changes.

Signed-off-by: Michael LeMay <mdlemay@epoch.ncsc.mil>
Signed-off-by: James Morris <jmorris@namei.org>
Signed-Off-By: David Howells <dhowells@redhat.com>
---

 Documentation/keys.txt |   16 ++++++++++++----
 security/Kconfig       |   20 +++++++++++++-------
 security/keys/proc.c   |    7 +++++++
 3 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 3bbe157..70e83cf 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -270,9 +270,17 @@ about the status of the key service:
 
  (*) /proc/keys
 
-     This lists all the keys on the system, giving information about their
-     type, description and permissions. The payload of the key is not available
-     this way:
+     This lists the keys that are currently viewable by the task reading the
+     file, giving information about their type, description and permissions.
+     It is not possible to view the payload of the key this way, though some
+     information about it may be given.
+
+     The only keys included in the list are those that grant View permission to
+     the reading process whether or not it possesses them.  Note that LSM
+     security checks are still performed, and may further filter out keys that
+     the current process is not authorised to view.
+
+     The contents of the file look like this:
 
 	SERIAL   FLAGS  USAGE EXPY PERM     UID   GID   TYPE      DESCRIPTION: SUMMARY
 	00000001 I-----    39 perm 1f3f0000     0     0 keyring   _uid_ses.0: 1/4
@@ -300,7 +308,7 @@ about the status of the key service:
  (*) /proc/key-users
 
      This file lists the tracking data for each user that has at least one key
-     on the system. Such data includes quota information and statistics:
+     on the system.  Such data includes quota information and statistics:
 
 	[root@andromeda root]# cat /proc/key-users
 	0:     46 45/45 1/100 13/10000
diff --git a/security/Kconfig b/security/Kconfig
index 34f5934..67785df 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -22,16 +22,22 @@ config KEYS
 	  If you are unsure as to whether this is required, answer N.
 
 config KEYS_DEBUG_PROC_KEYS
-	bool "Enable the /proc/keys file by which all keys may be viewed"
+	bool "Enable the /proc/keys file by which keys may be viewed"
 	depends on KEYS
 	help
-	  This option turns on support for the /proc/keys file through which
-	  all the keys on the system can be listed.
+	  This option turns on support for the /proc/keys file - through which
+	  can be listed all the keys on the system that are viewable by the
+	  reading process.
 
-	  This option is a slight security risk in that it makes it possible
-	  for anyone to see all the keys on the system. Normally the manager
-	  pretends keys that are inaccessible to a process don't exist as far
-	  as that process is concerned.
+	  The only keys included in the list are those that grant View
+	  permission to the reading process whether or not it possesses them.
+	  Note that LSM security checks are still performed, and may further
+	  filter out keys that the current process is not authorised to view.
+
+	  Only key attributes are listed here; key payloads are not included in
+	  the resulting table.
+
+	  If you are unsure as to whether this is required, answer N.
 
 config SECURITY
 	bool "Enable different security models"
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 12b750e..686a9ee 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -137,6 +137,13 @@ static int proc_keys_show(struct seq_fil
 	struct timespec now;
 	unsigned long timo;
 	char xbuf[12];
+	int rc;
+
+	/* check whether the current task is allowed to view the key (assuming
+	 * non-possession) */
+	rc = key_task_permission(make_key_ref(key, 0), current, KEY_VIEW);
+	if (rc < 0)
+		return 0;
 
 	now = current_kernel_time();
 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 6/6] Keys: Add a way to store the appropriate context for newly-created keys [try #3]
  2006-06-20 17:37 [PATCH 0/6] Keys: Key management updates [try #3] David Howells
                   ` (4 preceding siblings ...)
  2006-06-20 17:37 ` [PATCH 5/6] Keys: Restrict contents of /proc/keys to Viewable keys " David Howells
@ 2006-06-20 17:37 ` David Howells
  2006-06-20 20:44 ` [Keyrings] [PATCH 0/6] Keys: Key management updates " James Morris
  6 siblings, 0 replies; 9+ messages in thread
From: David Howells @ 2006-06-20 17:37 UTC (permalink / raw)
  To: torvalds, akpm; +Cc: linux-kernel, keyrings

From: Michael LeMay <mdlemay@epoch.ncsc.mil>

Add a /proc/<pid>/attr/keycreate entry that stores the appropriate
context for newly-created keys.  Modify the selinux_key_alloc
hook to make use of the new entry.  Update the flask headers to
include a new "setkeycreate" permission for processes.  Update the
flask headers to include a new "create" permission for keys.  Use
the create permission to restrict which SIDs each task can assign
to newly-created keys.  Add a new parameter to the security hook
"security_key_alloc" to indicate whether it is being invoked by
the kernel, or from userspace.  If it is being invoked by the
kernel, the security hook should never fail.  Update the
documentation to reflect these changes.

Signed-off-by: Michael LeMay <mdlemay@epoch.ncsc.mil>
Signed-off-by: James Morris <jmorris@namei.org>
Signed-Off-By: David Howells <dhowells@redhat.com>
---

 Documentation/keys.txt                       |   27 ++++++++++++--------
 fs/proc/base.c                               |    6 ++++
 security/selinux/hooks.c                     |   35 ++++++++++++++++++++++----
 security/selinux/include/av_perm_to_string.h |    2 +
 security/selinux/include/av_permissions.h    |    2 +
 security/selinux/include/objsec.h            |    1 +
 6 files changed, 56 insertions(+), 17 deletions(-)

diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 70e83cf..61c0fad 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -241,25 +241,30 @@ The security class "key" has been added 
 controls can be applied to keys created within various contexts.  This support
 is preliminary, and is likely to change quite significantly in the near future.
 Currently, all of the basic permissions explained above are provided in SELinux
-as well; SE Linux is simply invoked after all basic permission checks have been
+as well; SELinux is simply invoked after all basic permission checks have been
 performed.
 
-Each key is labeled with the same context as the task to which it belongs.
-Typically, this is the same task that was running when the key was created.
-The default keyrings are handled differently, but in a way that is very
-intuitive:
+The value of the file /proc/self/attr/keycreate influences the labeling of
+newly-created keys.  If the contents of that file correspond to an SELinux
+security context, then the key will be assigned that context.  Otherwise, the
+key will be assigned the current context of the task that invoked the key
+creation request.  Tasks must be granted explicit permission to assign a
+particular context to newly-created keys, using the "create" permission in the
+key security class.
 
- (*) The user and user session keyrings that are created when the user logs in
-     are currently labeled with the context of the login manager.
-
- (*) The keyrings associated with new threads are each labeled with the context
-     of their associated thread, and both session and process keyrings are
-     handled similarly.
+The default keyrings associated with users will be labeled with the default
+context of the user if and only if the login programs have been instrumented to
+properly initialize keycreate during the login process.  Otherwise, they will
+be labeled with the context of the login program itself.
 
 Note, however, that the default keyrings associated with the root user are
 labeled with the default kernel context, since they are created early in the
 boot process, before root has a chance to log in.
 
+The keyrings associated with new threads are each labeled with the context of
+their associated thread, and both session and process keyrings are handled
+similarly.
+
 
 ================
 NEW PROCFS FILES
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 6cc77dc..5334e07 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -121,6 +121,7 @@ #ifdef CONFIG_SECURITY
 	PROC_TGID_ATTR_PREV,
 	PROC_TGID_ATTR_EXEC,
 	PROC_TGID_ATTR_FSCREATE,
+	PROC_TGID_ATTR_KEYCREATE,
 #endif
 #ifdef CONFIG_AUDITSYSCALL
 	PROC_TGID_LOGINUID,
@@ -162,6 +163,7 @@ #ifdef CONFIG_SECURITY
 	PROC_TID_ATTR_PREV,
 	PROC_TID_ATTR_EXEC,
 	PROC_TID_ATTR_FSCREATE,
+	PROC_TID_ATTR_KEYCREATE,
 #endif
 #ifdef CONFIG_AUDITSYSCALL
 	PROC_TID_LOGINUID,
@@ -275,6 +277,7 @@ static struct pid_entry tgid_attr_stuff[
 	E(PROC_TGID_ATTR_PREV,     "prev",     S_IFREG|S_IRUGO),
 	E(PROC_TGID_ATTR_EXEC,     "exec",     S_IFREG|S_IRUGO|S_IWUGO),
 	E(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
+	E(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
 	{0,0,NULL,0}
 };
 static struct pid_entry tid_attr_stuff[] = {
@@ -282,6 +285,7 @@ static struct pid_entry tid_attr_stuff[]
 	E(PROC_TID_ATTR_PREV,      "prev",     S_IFREG|S_IRUGO),
 	E(PROC_TID_ATTR_EXEC,      "exec",     S_IFREG|S_IRUGO|S_IWUGO),
 	E(PROC_TID_ATTR_FSCREATE,  "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
+	E(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
 	{0,0,NULL,0}
 };
 #endif
@@ -1800,6 +1804,8 @@ #ifdef CONFIG_SECURITY
 		case PROC_TGID_ATTR_EXEC:
 		case PROC_TID_ATTR_FSCREATE:
 		case PROC_TGID_ATTR_FSCREATE:
+		case PROC_TID_ATTR_KEYCREATE:
+		case PROC_TGID_ATTR_KEYCREATE:
 			inode->i_fop = &proc_pid_attr_operations;
 			break;
 #endif
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f80c74d..8c1e1d5 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1099,6 +1099,17 @@ static int may_create(struct inode *dir,
 			    FILESYSTEM__ASSOCIATE, &ad);
 }
 
+/* Check whether a task can create a key. */
+static int may_create_key(u32 ksid,
+			  struct task_struct *ctx)
+{
+	struct task_security_struct *tsec;
+
+	tsec = ctx->security;
+
+	return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
+}
+
 #define MAY_LINK   0
 #define MAY_UNLINK 1
 #define MAY_RMDIR  2
@@ -4140,6 +4151,8 @@ static int selinux_getprocattr(struct ta
 		sid = tsec->exec_sid;
 	else if (!strcmp(name, "fscreate"))
 		sid = tsec->create_sid;
+	else if (!strcmp(name, "keycreate"))
+		sid = tsec->keycreate_sid;
 	else
 		return -EINVAL;
 
@@ -4172,6 +4185,8 @@ static int selinux_setprocattr(struct ta
 		error = task_has_perm(current, p, PROCESS__SETEXEC);
 	else if (!strcmp(name, "fscreate"))
 		error = task_has_perm(current, p, PROCESS__SETFSCREATE);
+	else if (!strcmp(name, "keycreate"))
+		error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
 	else if (!strcmp(name, "current"))
 		error = task_has_perm(current, p, PROCESS__SETCURRENT);
 	else
@@ -4201,7 +4216,12 @@ static int selinux_setprocattr(struct ta
 		tsec->exec_sid = sid;
 	else if (!strcmp(name, "fscreate"))
 		tsec->create_sid = sid;
-	else if (!strcmp(name, "current")) {
+	else if (!strcmp(name, "keycreate")) {
+		error = may_create_key(sid, p);
+		if (error)
+			return error;
+		tsec->keycreate_sid = sid;
+	} else if (!strcmp(name, "current")) {
 		struct av_decision avd;
 
 		if (sid == 0)
@@ -4265,7 +4285,10 @@ static int selinux_key_alloc(struct key 
 		return -ENOMEM;
 
 	ksec->obj = k;
-	ksec->sid = tsec->sid;
+	if (tsec->keycreate_sid)
+		ksec->sid = tsec->keycreate_sid;
+	else
+		ksec->sid = tsec->sid;
 	k->security = ksec;
 
 	return 0;
@@ -4502,10 +4525,10 @@ static __init int selinux_init(void)
 
 #ifdef CONFIG_KEYS
 	/* Add security information to initial keyrings */
-	security_key_alloc(&root_user_keyring, current,
-			   KEY_ALLOC_NOT_IN_QUOTA);
-	security_key_alloc(&root_session_keyring, current,
-			   KEY_ALLOC_NOT_IN_QUOTA);
+	selinux_key_alloc(&root_user_keyring, current,
+			  KEY_ALLOC_NOT_IN_QUOTA);
+	selinux_key_alloc(&root_session_keyring, current,
+			  KEY_ALLOC_NOT_IN_QUOTA);
 #endif
 
 	return 0;
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index bc020bd..e777578 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -72,6 +72,7 @@
    S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem")
    S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack")
    S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap")
+   S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate")
    S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue")
    S_(SECCLASS_MSG, MSG__SEND, "send")
    S_(SECCLASS_MSG, MSG__RECEIVE, "receive")
@@ -248,3 +249,4 @@
    S_(SECCLASS_KEY, KEY__SEARCH, "search")
    S_(SECCLASS_KEY, KEY__LINK, "link")
    S_(SECCLASS_KEY, KEY__SETATTR, "setattr")
+   S_(SECCLASS_KEY, KEY__CREATE, "create")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index b108dda..ba5ef05 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -467,6 +467,7 @@ #define PROCESS__SETCURRENT             
 #define PROCESS__EXECMEM                          0x02000000UL
 #define PROCESS__EXECSTACK                        0x04000000UL
 #define PROCESS__EXECHEAP                         0x08000000UL
+#define PROCESS__SETKEYCREATE                     0x10000000UL
 
 #define IPC__CREATE                               0x00000001UL
 #define IPC__DESTROY                              0x00000002UL
@@ -965,3 +966,4 @@ #define KEY__WRITE                      
 #define KEY__SEARCH                               0x00000008UL
 #define KEY__LINK                                 0x00000010UL
 #define KEY__SETATTR                              0x00000020UL
+#define KEY__CREATE                               0x00000040UL
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 8f5547a..191b3e4 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -32,6 +32,7 @@ struct task_security_struct {
 	u32 sid;             /* current SID */
 	u32 exec_sid;        /* exec SID */
 	u32 create_sid;      /* fscreate SID */
+	u32 keycreate_sid;   /* keycreate SID */
 	u32 ptrace_sid;      /* SID of ptrace parent */
 };
 


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Keyrings] [PATCH 0/6] Keys: Key management updates  [try #3]
  2006-06-20 17:37 [PATCH 0/6] Keys: Key management updates [try #3] David Howells
                   ` (5 preceding siblings ...)
  2006-06-20 17:37 ` [PATCH 6/6] Keys: Add a way to store the appropriate context for newly-created " David Howells
@ 2006-06-20 20:44 ` James Morris
  2006-06-20 21:03   ` Andrew Morton
  6 siblings, 1 reply; 9+ messages in thread
From: James Morris @ 2006-06-20 20:44 UTC (permalink / raw)
  To: David Howells; +Cc: Linus Torvalds, Andrew Morton, keyrings, linux-kernel

On Tue, 20 Jun 2006, David Howells wrote:

> These patches update a few key management related things, mainly security
> related.  They have the following prerequisite patches from Andrew Morton's -mm
> tree:
> 
> 	selinux-add-hooks-for-key-subsystem.patch
> 	keys-fix-race-between-two-instantiators-of-a-key.patch

When do you think these patches will move from -mm into mainline?

I ask because I've got a bunch of SELinux patches lined up behind this 
patchset, which we're aiming for 2.6.18 inclusion.



- James 
-- 
James Morris <jmorris@namei.org>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Keyrings] [PATCH 0/6] Keys: Key management updates  [try #3]
  2006-06-20 20:44 ` [Keyrings] [PATCH 0/6] Keys: Key management updates " James Morris
@ 2006-06-20 21:03   ` Andrew Morton
  0 siblings, 0 replies; 9+ messages in thread
From: Andrew Morton @ 2006-06-20 21:03 UTC (permalink / raw)
  To: James Morris; +Cc: dhowells, torvalds, keyrings, linux-kernel

On Tue, 20 Jun 2006 16:44:16 -0400 (EDT)
James Morris <jmorris@namei.org> wrote:

> On Tue, 20 Jun 2006, David Howells wrote:
> 
> > These patches update a few key management related things, mainly security
> > related.  They have the following prerequisite patches from Andrew Morton's -mm
> > tree:
> > 
> > 	selinux-add-hooks-for-key-subsystem.patch
> > 	keys-fix-race-between-two-instantiators-of-a-key.patch
> 
> When do you think these patches will move from -mm into mainline?

I prefer to start the -mm merging in the second week of the merge window,
after the git trees have gone.

a) because that's the order in which the patches are staged

b) because that's the way in which they were tested: -mm patches without
   the presence of the git trees is basically untested code.

c) because I'm more able to handle rejects and other such crap than git
   victims^Wusers.

But sometimes I get bored and merge stuff early anyway.

> I ask because I've got a bunch of SELinux patches lined up behind this 
> patchset, which we're aiming for 2.6.18 inclusion.

OK, I'll move those two up into the i-got-bored batch, aim for tomorrow.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2006-06-20 21:03 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-20 17:37 [PATCH 0/6] Keys: Key management updates [try #3] David Howells
2006-06-20 17:37 ` [PATCH 1/6] Keys: Sort out key quota system " David Howells
2006-06-20 17:37 ` [PATCH 2/6] Keys: Discard the contents of a key on revocation " David Howells
2006-06-20 17:37 ` [PATCH 3/6] Keys: Let keyctl_chown() change a key's owner " David Howells
2006-06-20 17:37 ` [PATCH 4/6] Keys: Allocate key serial numbers randomly " David Howells
2006-06-20 17:37 ` [PATCH 5/6] Keys: Restrict contents of /proc/keys to Viewable keys " David Howells
2006-06-20 17:37 ` [PATCH 6/6] Keys: Add a way to store the appropriate context for newly-created " David Howells
2006-06-20 20:44 ` [Keyrings] [PATCH 0/6] Keys: Key management updates " James Morris
2006-06-20 21:03   ` Andrew Morton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®