aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/gc.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-11-14 13:02:31 +0000
committerDavid Howells <dhowells@redhat.com>2013-11-14 14:09:53 +0000
commit62fe318256befbd1b4a6765e71d9c997f768fe79 (patch)
treea24b4672750ceea1850f7b97131256f163554ea7 /security/keys/gc.c
parentKEYS: Fix error handling in big_key instantiation (diff)
downloadlinux-dev-62fe318256befbd1b4a6765e71d9c997f768fe79.tar.xz
linux-dev-62fe318256befbd1b4a6765e71d9c997f768fe79.zip
KEYS: Fix keyring content gc scanner
Key pointers stored in the keyring are marked in bit 1 to indicate if they point to a keyring. We need to strip off this bit before using the pointer when iterating over the keyring for the purpose of looking for links to garbage collect. This means that expirable keyrings aren't correctly expiring because the checker is seeing their key pointer with 2 added to it. Since the fix for this involves knowing about the internals of the keyring, key_gc_keyring() is moved to keyring.c and merged into keyring_gc(). This can be tested by: echo 2 >/proc/sys/kernel/keys/gc_delay keyctl timeout `keyctl add keyring qwerty "" @s` 2 cat /proc/keys sleep 5; cat /proc/keys which should see a keyring called "qwerty" appear in the session keyring and then disappear after it expires, and: echo 2 >/proc/sys/kernel/keys/gc_delay a=`keyctl get_persistent @s` b=`keyctl add keyring 0 "" $a` keyctl add user a a $b keyctl timeout $b 2 cat /proc/keys sleep 5; cat /proc/keys which should see a keyring called "0" with a key called "a" in it appear in the user's persistent keyring (which will be attached to the session keyring) and then both the "0" keyring and the "a" key should disappear when the "0" keyring expires. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Simo Sorce <simo@redhat.com>
Diffstat (limited to 'security/keys/gc.c')
-rw-r--r--security/keys/gc.c42
1 files changed, 1 insertions, 41 deletions
diff --git a/security/keys/gc.c b/security/keys/gc.c
index cce621c33dce..d3222b6d7d59 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -130,46 +130,6 @@ void key_gc_keytype(struct key_type *ktype)
kleave("");
}
-static int key_gc_keyring_func(const void *object, void *iterator_data)
-{
- const struct key *key = object;
- time_t *limit = iterator_data;
- return key_is_dead(key, *limit);
-}
-
-/*
- * Garbage collect pointers from a keyring.
- *
- * Not called with any locks held. The keyring's key struct will not be
- * deallocated under us as only our caller may deallocate it.
- */
-static void key_gc_keyring(struct key *keyring, time_t limit)
-{
- int result;
-
- kenter("%x{%s}", keyring->serial, keyring->description ?: "");
-
- if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) |
- (1 << KEY_FLAG_REVOKED)))
- goto dont_gc;
-
- /* scan the keyring looking for dead keys */
- rcu_read_lock();
- result = assoc_array_iterate(&keyring->keys,
- key_gc_keyring_func, &limit);
- rcu_read_unlock();
- if (result == true)
- goto do_gc;
-
-dont_gc:
- kleave(" [no gc]");
- return;
-
-do_gc:
- keyring_gc(keyring, limit);
- kleave(" [gc]");
-}
-
/*
* Garbage collect a list of unreferenced, detached keys
*/
@@ -388,7 +348,7 @@ found_unreferenced_key:
*/
found_keyring:
spin_unlock(&key_serial_lock);
- key_gc_keyring(key, limit);
+ keyring_gc(key, limit);
goto maybe_resched;
/* We found a dead key that is still referenced. Reset its type and