Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f233706 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of...

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6:
  KEYS: call_sbin_request_key() must write lock keyrings before modifying them
  KEYS: Use RCU dereference wrappers in keyring key type code
  KEYS: find_keyring_by_name() can gain access to a freed keyring
parents 8777c793 896903c2
Loading
Loading
Loading
Loading
+22 −19
Original line number Diff line number Diff line
@@ -20,6 +20,11 @@
#include <asm/uaccess.h>
#include "internal.h"

#define rcu_dereference_locked_keyring(keyring)				\
	(rcu_dereference_protected(					\
		(keyring)->payload.subscriptions,			\
		rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem)))

/*
 * when plumbing the depths of the key tree, this sets a hard limit set on how
 * deep we're willing to go
@@ -201,8 +206,7 @@ static long keyring_read(const struct key *keyring,
	int loop, ret;

	ret = 0;
	klist = keyring->payload.subscriptions;

	klist = rcu_dereference_locked_keyring(keyring);
	if (klist) {
		/* calculate how much data we could return */
		qty = klist->nkeys * sizeof(key_serial_t);
@@ -526,9 +530,8 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
	struct key *keyring;
	int bucket;

	keyring = ERR_PTR(-EINVAL);
	if (!name)
		goto error;
		return ERR_PTR(-EINVAL);

	bucket = keyring_hash(name);

@@ -555,17 +558,18 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
					   KEY_SEARCH) < 0)
				continue;

			/* we've got a match */
			atomic_inc(&keyring->usage);
			read_unlock(&keyring_name_lock);
			goto error;
			/* we've got a match but we might end up racing with
			 * key_cleanup() if the keyring is currently 'dead'
			 * (ie. it has a zero usage count) */
			if (!atomic_inc_not_zero(&keyring->usage))
				continue;
			goto out;
		}
	}

	read_unlock(&keyring_name_lock);
	keyring = ERR_PTR(-ENOKEY);

 error:
out:
	read_unlock(&keyring_name_lock);
	return keyring;

} /* end find_keyring_by_name() */
@@ -720,8 +724,7 @@ int __key_link(struct key *keyring, struct key *key)
	}

	/* see if there's a matching key we can displace */
	klist = keyring->payload.subscriptions;

	klist = rcu_dereference_locked_keyring(keyring);
	if (klist && klist->nkeys > 0) {
		struct key_type *type = key->type;

@@ -765,8 +768,6 @@ int __key_link(struct key *keyring, struct key *key)
	if (ret < 0)
		goto error2;

	klist = keyring->payload.subscriptions;

	if (klist && klist->nkeys < klist->maxkeys) {
		/* there's sufficient slack space to add directly */
		atomic_inc(&key->usage);
@@ -868,7 +869,7 @@ int key_unlink(struct key *keyring, struct key *key)

	down_write(&keyring->sem);

	klist = keyring->payload.subscriptions;
	klist = rcu_dereference_locked_keyring(keyring);
	if (klist) {
		/* search the keyring for the key */
		for (loop = 0; loop < klist->nkeys; loop++)
@@ -959,7 +960,7 @@ int keyring_clear(struct key *keyring)
		/* detach the pointer block with the locks held */
		down_write(&keyring->sem);

		klist = keyring->payload.subscriptions;
		klist = rcu_dereference_locked_keyring(keyring);
		if (klist) {
			/* adjust the quota */
			key_payload_reserve(keyring,
@@ -991,7 +992,9 @@ EXPORT_SYMBOL(keyring_clear);
 */
static void keyring_revoke(struct key *keyring)
{
	struct keyring_list *klist = keyring->payload.subscriptions;
	struct keyring_list *klist;

	klist = rcu_dereference_locked_keyring(keyring);

	/* adjust the quota */
	key_payload_reserve(keyring, 0);
@@ -1025,7 +1028,7 @@ void keyring_gc(struct key *keyring, time_t limit)

	down_write(&keyring->sem);

	klist = keyring->payload.subscriptions;
	klist = rcu_dereference_locked_keyring(keyring);
	if (!klist)
		goto no_klist;

+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ static int call_sbin_request_key(struct key_construction *cons,
	}

	/* attach the auth key to the session keyring */
	ret = __key_link(keyring, authkey);
	ret = key_link(keyring, authkey);
	if (ret < 0)
		goto error_link;