Browse Source

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: Fix RCU handling in key_gc_keyring()
  KEYS: Fix an RCU warning in the reading of user keys
Linus Torvalds 15 years ago
parent
commit
67bff7c087
2 changed files with 8 additions and 4 deletions
  1. 6 3
      security/keys/gc.c
  2. 2 1
      security/keys/user_defined.c

+ 6 - 3
security/keys/gc.c

@@ -77,10 +77,10 @@ static bool key_gc_keyring(struct key *keyring, time_t limit)
 		goto dont_gc;
 		goto dont_gc;
 
 
 	/* scan the keyring looking for dead keys */
 	/* scan the keyring looking for dead keys */
-	klist = rcu_dereference_check(keyring->payload.subscriptions,
-				      lockdep_is_held(&key_serial_lock));
+	rcu_read_lock();
+	klist = rcu_dereference(keyring->payload.subscriptions);
 	if (!klist)
 	if (!klist)
-		goto dont_gc;
+		goto unlock_dont_gc;
 
 
 	for (loop = klist->nkeys - 1; loop >= 0; loop--) {
 	for (loop = klist->nkeys - 1; loop >= 0; loop--) {
 		key = klist->keys[loop];
 		key = klist->keys[loop];
@@ -89,11 +89,14 @@ static bool key_gc_keyring(struct key *keyring, time_t limit)
 			goto do_gc;
 			goto do_gc;
 	}
 	}
 
 
+unlock_dont_gc:
+	rcu_read_unlock();
 dont_gc:
 dont_gc:
 	kleave(" = false");
 	kleave(" = false");
 	return false;
 	return false;
 
 
 do_gc:
 do_gc:
+	rcu_read_unlock();
 	key_gc_cursor = keyring->serial;
 	key_gc_cursor = keyring->serial;
 	key_get(keyring);
 	key_get(keyring);
 	spin_unlock(&key_serial_lock);
 	spin_unlock(&key_serial_lock);

+ 2 - 1
security/keys/user_defined.c

@@ -199,7 +199,8 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
 	struct user_key_payload *upayload;
 	struct user_key_payload *upayload;
 	long ret;
 	long ret;
 
 
-	upayload = rcu_dereference(key->payload.data);
+	upayload = rcu_dereference_protected(
+		key->payload.data, rwsem_is_locked(&((struct key *)key)->sem));
 	ret = upayload->datalen;
 	ret = upayload->datalen;
 
 
 	/* we can return the data as is */
 	/* we can return the data as is */