KEYS: Move the unreferenced key reaper to the keys garbage collector file
authorDavid Howells <dhowells@redhat.com>
Mon, 22 Aug 2011 13:09:11 +0000 (14:09 +0100)
committerJames Morris <jmorris@namei.org>
Mon, 22 Aug 2011 23:57:36 +0000 (09:57 +1000)
Move the unreferenced key reaper function to the keys garbage collector file
as that's a more appropriate place with the dead key link reaper.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
security/keys/gc.c
security/keys/internal.h
security/keys/key.c

index 89df6b5f203c534c64fffd3fc0547f611dedebea..b23db3fbb32dd932d76e0a9c59620b7892215b7e 100644 (file)
@@ -10,6 +10,8 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/security.h>
 #include <keys/keyring-type.h>
 #include "internal.h"
 
 unsigned key_gc_delay = 5 * 60;
 
 /*
- * Reaper
+ * Reaper for unused keys.
+ */
+static void key_gc_unused_keys(struct work_struct *work);
+DECLARE_WORK(key_gc_unused_work, key_gc_unused_keys);
+
+/*
+ * Reaper for links from keyrings to dead keys.
  */
 static void key_gc_timer_func(unsigned long);
-static void key_garbage_collector(struct work_struct *);
+static void key_gc_dead_links(struct work_struct *);
 static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0);
-static DECLARE_WORK(key_gc_work, key_garbage_collector);
+static DECLARE_WORK(key_gc_work, key_gc_dead_links);
 static key_serial_t key_gc_cursor; /* the last key the gc considered */
 static bool key_gc_again;
 static unsigned long key_gc_executing;
@@ -108,10 +116,12 @@ do_gc:
 }
 
 /*
- * Garbage collector for keys.  This involves scanning the keyrings for dead,
- * expired and revoked keys that have overstayed their welcome
+ * Garbage collector for links to dead keys.
+ *
+ * This involves scanning the keyrings for dead, expired and revoked keys that
+ * have overstayed their welcome
  */
-static void key_garbage_collector(struct work_struct *work)
+static void key_gc_dead_links(struct work_struct *work)
 {
        struct rb_node *rb;
        key_serial_t cursor;
@@ -220,3 +230,68 @@ reached_the_end:
        }
        kleave(" [end]");
 }
+
+/*
+ * Garbage collector for unused keys.
+ *
+ * This is done in process context so that we don't have to disable interrupts
+ * all over the place.  key_put() schedules this rather than trying to do the
+ * cleanup itself, which means key_put() doesn't have to sleep.
+ */
+static void key_gc_unused_keys(struct work_struct *work)
+{
+       struct rb_node *_n;
+       struct key *key;
+
+go_again:
+       /* look for a dead key in the tree */
+       spin_lock(&key_serial_lock);
+
+       for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
+               key = rb_entry(_n, struct key, serial_node);
+
+               if (atomic_read(&key->usage) == 0)
+                       goto found_dead_key;
+       }
+
+       spin_unlock(&key_serial_lock);
+       return;
+
+found_dead_key:
+       /* we found a dead key - once we've removed it from the tree, we can
+        * drop the lock */
+       rb_erase(&key->serial_node, &key_serial_tree);
+       spin_unlock(&key_serial_lock);
+
+       key_check(key);
+
+       security_key_free(key);
+
+       /* deal with the user's key tracking and quota */
+       if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
+               spin_lock(&key->user->lock);
+               key->user->qnkeys--;
+               key->user->qnbytes -= key->quotalen;
+               spin_unlock(&key->user->lock);
+       }
+
+       atomic_dec(&key->user->nkeys);
+       if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
+               atomic_dec(&key->user->nikeys);
+
+       key_user_put(key->user);
+
+       /* now throw away the key memory */
+       if (key->type->destroy)
+               key->type->destroy(key);
+
+       kfree(key->description);
+
+#ifdef KEY_DEBUGGING
+       key->magic = KEY_DEBUG_MAGIC_X;
+#endif
+       kmem_cache_free(key_jar, key);
+
+       /* there may, of course, be more than one key to destroy */
+       goto go_again;
+}
index f375152a2500b1d747d7128517430d2401f3a4ce..a7cd1a6823216a6b0f56838c4d9fcc5ec023556e 100644 (file)
@@ -75,6 +75,7 @@ extern unsigned key_quota_maxbytes;
 #define KEYQUOTA_LINK_BYTES    4               /* a link in a keyring is worth 4 bytes */
 
 
+extern struct kmem_cache *key_jar;
 extern struct rb_root key_serial_tree;
 extern spinlock_t key_serial_lock;
 extern struct mutex key_construction_mutex;
@@ -146,6 +147,7 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
 
 extern long join_session_keyring(const char *name);
 
+extern struct work_struct key_gc_unused_work;
 extern unsigned key_gc_delay;
 extern void keyring_gc(struct key *keyring, time_t limit);
 extern void key_schedule_gc(time_t expiry_at);
index f7f9d93f08d98df064104630c3f91ce4fb2aaab9..991a15f1e85faf6a94623f1c5b61347b606ded5c 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/user_namespace.h>
 #include "internal.h"
 
-static struct kmem_cache       *key_jar;
+struct kmem_cache *key_jar;
 struct rb_root         key_serial_tree; /* tree of keys indexed by serial */
 DEFINE_SPINLOCK(key_serial_lock);
 
@@ -36,9 +36,6 @@ unsigned int key_quota_maxbytes = 20000;      /* general key space quota */
 static LIST_HEAD(key_types_list);
 static DECLARE_RWSEM(key_types_sem);
 
-static void key_cleanup(struct work_struct *work);
-static DECLARE_WORK(key_cleanup_task, key_cleanup);
-
 /* We serialise key instantiation and link */
 DEFINE_MUTEX(key_construction_mutex);
 
@@ -591,71 +588,6 @@ int key_reject_and_link(struct key *key,
 }
 EXPORT_SYMBOL(key_reject_and_link);
 
-/*
- * Garbage collect keys in process context so that we don't have to disable
- * interrupts all over the place.
- *
- * key_put() schedules this rather than trying to do the cleanup itself, which
- * means key_put() doesn't have to sleep.
- */
-static void key_cleanup(struct work_struct *work)
-{
-       struct rb_node *_n;
-       struct key *key;
-
-go_again:
-       /* look for a dead key in the tree */
-       spin_lock(&key_serial_lock);
-
-       for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
-               key = rb_entry(_n, struct key, serial_node);
-
-               if (atomic_read(&key->usage) == 0)
-                       goto found_dead_key;
-       }
-
-       spin_unlock(&key_serial_lock);
-       return;
-
-found_dead_key:
-       /* we found a dead key - once we've removed it from the tree, we can
-        * drop the lock */
-       rb_erase(&key->serial_node, &key_serial_tree);
-       spin_unlock(&key_serial_lock);
-
-       key_check(key);
-
-       security_key_free(key);
-
-       /* deal with the user's key tracking and quota */
-       if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
-               spin_lock(&key->user->lock);
-               key->user->qnkeys--;
-               key->user->qnbytes -= key->quotalen;
-               spin_unlock(&key->user->lock);
-       }
-
-       atomic_dec(&key->user->nkeys);
-       if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
-               atomic_dec(&key->user->nikeys);
-
-       key_user_put(key->user);
-
-       /* now throw away the key memory */
-       if (key->type->destroy)
-               key->type->destroy(key);
-
-       kfree(key->description);
-
-#ifdef KEY_DEBUGGING
-       key->magic = KEY_DEBUG_MAGIC_X;
-#endif
-       kmem_cache_free(key_jar, key);
-
-       /* there may, of course, be more than one key to destroy */
-       goto go_again;
-}
-
 /**
  * key_put - Discard a reference to a key.
  * @key: The key to discard a reference from.
@@ -670,7 +602,7 @@ void key_put(struct key *key)
                key_check(key);
 
                if (atomic_dec_and_test(&key->usage))
-                       schedule_work(&key_cleanup_task);
+                       schedule_work(&key_gc_unused_work);
        }
 }
 EXPORT_SYMBOL(key_put);