aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2011-08-22 09:09:11 -0400
committerJames Morris <jmorris@namei.org>2011-08-22 19:57:36 -0400
commit8bc16deabce7649e480e94b648c88d4e90c34352 (patch)
treed9e28a921375e7448801b0b89ff43a7e0d2e61ff
parent012146d0728f85f7a5c7c36fb84bba33e2760507 (diff)
KEYS: Move the unreferenced key reaper to the keys garbage collector file
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>
-rw-r--r--security/keys/gc.c87
-rw-r--r--security/keys/internal.h2
-rw-r--r--security/keys/key.c72
3 files changed, 85 insertions, 76 deletions
diff --git a/security/keys/gc.c b/security/keys/gc.c
index 89df6b5f203c..b23db3fbb32d 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -10,6 +10,8 @@
10 */ 10 */
11 11
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/slab.h>
14#include <linux/security.h>
13#include <keys/keyring-type.h> 15#include <keys/keyring-type.h>
14#include "internal.h" 16#include "internal.h"
15 17
@@ -19,12 +21,18 @@
19unsigned key_gc_delay = 5 * 60; 21unsigned key_gc_delay = 5 * 60;
20 22
21/* 23/*
22 * Reaper 24 * Reaper for unused keys.
25 */
26static void key_gc_unused_keys(struct work_struct *work);
27DECLARE_WORK(key_gc_unused_work, key_gc_unused_keys);
28
29/*
30 * Reaper for links from keyrings to dead keys.
23 */ 31 */
24static void key_gc_timer_func(unsigned long); 32static void key_gc_timer_func(unsigned long);
25static void key_garbage_collector(struct work_struct *); 33static void key_gc_dead_links(struct work_struct *);
26static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0); 34static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0);
27static DECLARE_WORK(key_gc_work, key_garbage_collector); 35static DECLARE_WORK(key_gc_work, key_gc_dead_links);
28static key_serial_t key_gc_cursor; /* the last key the gc considered */ 36static key_serial_t key_gc_cursor; /* the last key the gc considered */
29static bool key_gc_again; 37static bool key_gc_again;
30static unsigned long key_gc_executing; 38static unsigned long key_gc_executing;
@@ -108,10 +116,12 @@ do_gc:
108} 116}
109 117
110/* 118/*
111 * Garbage collector for keys. This involves scanning the keyrings for dead, 119 * Garbage collector for links to dead keys.
112 * expired and revoked keys that have overstayed their welcome 120 *
121 * This involves scanning the keyrings for dead, expired and revoked keys that
122 * have overstayed their welcome
113 */ 123 */
114static void key_garbage_collector(struct work_struct *work) 124static void key_gc_dead_links(struct work_struct *work)
115{ 125{
116 struct rb_node *rb; 126 struct rb_node *rb;
117 key_serial_t cursor; 127 key_serial_t cursor;
@@ -220,3 +230,68 @@ reached_the_end:
220 } 230 }
221 kleave(" [end]"); 231 kleave(" [end]");
222} 232}
233
234/*
235 * Garbage collector for unused keys.
236 *
237 * This is done in process context so that we don't have to disable interrupts
238 * all over the place. key_put() schedules this rather than trying to do the
239 * cleanup itself, which means key_put() doesn't have to sleep.
240 */
241static void key_gc_unused_keys(struct work_struct *work)
242{
243 struct rb_node *_n;
244 struct key *key;
245
246go_again:
247 /* look for a dead key in the tree */
248 spin_lock(&key_serial_lock);
249
250 for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
251 key = rb_entry(_n, struct key, serial_node);
252
253 if (atomic_read(&key->usage) == 0)
254 goto found_dead_key;
255 }
256
257 spin_unlock(&key_serial_lock);
258 return;
259
260found_dead_key:
261 /* we found a dead key - once we've removed it from the tree, we can
262 * drop the lock */
263 rb_erase(&key->serial_node, &key_serial_tree);
264 spin_unlock(&key_serial_lock);
265
266 key_check(key);
267
268 security_key_free(key);
269
270 /* deal with the user's key tracking and quota */
271 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
272 spin_lock(&key->user->lock);
273 key->user->qnkeys--;
274 key->user->qnbytes -= key->quotalen;
275 spin_unlock(&key->user->lock);
276 }
277
278 atomic_dec(&key->user->nkeys);
279 if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
280 atomic_dec(&key->user->nikeys);
281
282 key_user_put(key->user);
283
284 /* now throw away the key memory */
285 if (key->type->destroy)
286 key->type->destroy(key);
287
288 kfree(key->description);
289
290#ifdef KEY_DEBUGGING
291 key->magic = KEY_DEBUG_MAGIC_X;
292#endif
293 kmem_cache_free(key_jar, key);
294
295 /* there may, of course, be more than one key to destroy */
296 goto go_again;
297}
diff --git a/security/keys/internal.h b/security/keys/internal.h
index f375152a2500..a7cd1a682321 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -75,6 +75,7 @@ extern unsigned key_quota_maxbytes;
75#define KEYQUOTA_LINK_BYTES 4 /* a link in a keyring is worth 4 bytes */ 75#define KEYQUOTA_LINK_BYTES 4 /* a link in a keyring is worth 4 bytes */
76 76
77 77
78extern struct kmem_cache *key_jar;
78extern struct rb_root key_serial_tree; 79extern struct rb_root key_serial_tree;
79extern spinlock_t key_serial_lock; 80extern spinlock_t key_serial_lock;
80extern struct mutex key_construction_mutex; 81extern struct mutex key_construction_mutex;
@@ -146,6 +147,7 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
146 147
147extern long join_session_keyring(const char *name); 148extern long join_session_keyring(const char *name);
148 149
150extern struct work_struct key_gc_unused_work;
149extern unsigned key_gc_delay; 151extern unsigned key_gc_delay;
150extern void keyring_gc(struct key *keyring, time_t limit); 152extern void keyring_gc(struct key *keyring, time_t limit);
151extern void key_schedule_gc(time_t expiry_at); 153extern void key_schedule_gc(time_t expiry_at);
diff --git a/security/keys/key.c b/security/keys/key.c
index f7f9d93f08d9..991a15f1e85f 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -21,7 +21,7 @@
21#include <linux/user_namespace.h> 21#include <linux/user_namespace.h>
22#include "internal.h" 22#include "internal.h"
23 23
24static struct kmem_cache *key_jar; 24struct kmem_cache *key_jar;
25struct rb_root key_serial_tree; /* tree of keys indexed by serial */ 25struct rb_root key_serial_tree; /* tree of keys indexed by serial */
26DEFINE_SPINLOCK(key_serial_lock); 26DEFINE_SPINLOCK(key_serial_lock);
27 27
@@ -36,9 +36,6 @@ unsigned int key_quota_maxbytes = 20000; /* general key space quota */
36static LIST_HEAD(key_types_list); 36static LIST_HEAD(key_types_list);
37static DECLARE_RWSEM(key_types_sem); 37static DECLARE_RWSEM(key_types_sem);
38 38
39static void key_cleanup(struct work_struct *work);
40static DECLARE_WORK(key_cleanup_task, key_cleanup);
41
42/* We serialise key instantiation and link */ 39/* We serialise key instantiation and link */
43DEFINE_MUTEX(key_construction_mutex); 40DEFINE_MUTEX(key_construction_mutex);
44 41
@@ -591,71 +588,6 @@ int key_reject_and_link(struct key *key,
591} 588}
592EXPORT_SYMBOL(key_reject_and_link); 589EXPORT_SYMBOL(key_reject_and_link);
593 590
594/*
595 * Garbage collect keys in process context so that we don't have to disable
596 * interrupts all over the place.
597 *
598 * key_put() schedules this rather than trying to do the cleanup itself, which
599 * means key_put() doesn't have to sleep.
600 */
601static void key_cleanup(struct work_struct *work)
602{
603 struct rb_node *_n;
604 struct key *key;
605
606go_again:
607 /* look for a dead key in the tree */
608 spin_lock(&key_serial_lock);
609
610 for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
611 key = rb_entry(_n, struct key, serial_node);
612
613 if (atomic_read(&key->usage) == 0)
614 goto found_dead_key;
615 }
616
617 spin_unlock(&key_serial_lock);
618 return;
619
620found_dead_key:
621 /* we found a dead key - once we've removed it from the tree, we can
622 * drop the lock */
623 rb_erase(&key->serial_node, &key_serial_tree);
624 spin_unlock(&key_serial_lock);
625
626 key_check(key);
627
628 security_key_free(key);
629
630 /* deal with the user's key tracking and quota */
631 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
632 spin_lock(&key->user->lock);
633 key->user->qnkeys--;
634 key->user->qnbytes -= key->quotalen;
635 spin_unlock(&key->user->lock);
636 }
637
638 atomic_dec(&key->user->nkeys);
639 if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
640 atomic_dec(&key->user->nikeys);
641
642 key_user_put(key->user);
643
644 /* now throw away the key memory */
645 if (key->type->destroy)
646 key->type->destroy(key);
647
648 kfree(key->description);
649
650#ifdef KEY_DEBUGGING
651 key->magic = KEY_DEBUG_MAGIC_X;
652#endif
653 kmem_cache_free(key_jar, key);
654
655 /* there may, of course, be more than one key to destroy */
656 goto go_again;
657}
658
659/** 591/**
660 * key_put - Discard a reference to a key. 592 * key_put - Discard a reference to a key.
661 * @key: The key to discard a reference from. 593 * @key: The key to discard a reference from.
@@ -670,7 +602,7 @@ void key_put(struct key *key)
670 key_check(key); 602 key_check(key);
671 603
672 if (atomic_dec_and_test(&key->usage)) 604 if (atomic_dec_and_test(&key->usage))
673 schedule_work(&key_cleanup_task); 605 schedule_work(&key_gc_unused_work);
674 } 606 }
675} 607}
676EXPORT_SYMBOL(key_put); 608EXPORT_SYMBOL(key_put);