aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/keys.txt19
-rw-r--r--include/linux/key.h5
-rw-r--r--security/keys/Makefile1
-rw-r--r--security/keys/gc.c193
-rw-r--r--security/keys/internal.h4
-rw-r--r--security/keys/key.c14
-rw-r--r--security/keys/keyctl.c1
-rw-r--r--security/keys/keyring.c85
-rw-r--r--security/keys/sysctl.c28
9 files changed, 344 insertions, 6 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index b56aacc1fff8..203487e9b1d8 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -26,7 +26,7 @@ This document has the following sections:
26 - Notes on accessing payload contents 26 - Notes on accessing payload contents
27 - Defining a key type 27 - Defining a key type
28 - Request-key callback service 28 - Request-key callback service
29 - Key access filesystem 29 - Garbage collection
30 30
31 31
32============ 32============
@@ -113,6 +113,9 @@ Each key has a number of attributes:
113 113
114 (*) Dead. The key's type was unregistered, and so the key is now useless. 114 (*) Dead. The key's type was unregistered, and so the key is now useless.
115 115
116Keys in the last three states are subject to garbage collection. See the
117section on "Garbage collection".
118
116 119
117==================== 120====================
118KEY SERVICE OVERVIEW 121KEY SERVICE OVERVIEW
@@ -1231,3 +1234,17 @@ by executing:
1231 1234
1232In this case, the program isn't required to actually attach the key to a ring; 1235In this case, the program isn't required to actually attach the key to a ring;
1233the rings are provided for reference. 1236the rings are provided for reference.
1237
1238
1239==================
1240GARBAGE COLLECTION
1241==================
1242
1243Dead keys (for which the type has been removed) will be automatically unlinked
1244from those keyrings that point to them and deleted as soon as possible by a
1245background garbage collector.
1246
1247Similarly, revoked and expired keys will be garbage collected, but only after a
1248certain amount of time has passed. This time is set as a number of seconds in:
1249
1250 /proc/sys/kernel/keys/gc_delay
diff --git a/include/linux/key.h b/include/linux/key.h
index e544f466d69a..33e0165de100 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -129,7 +129,10 @@ struct key {
129 struct rw_semaphore sem; /* change vs change sem */ 129 struct rw_semaphore sem; /* change vs change sem */
130 struct key_user *user; /* owner of this key */ 130 struct key_user *user; /* owner of this key */
131 void *security; /* security data for this key */ 131 void *security; /* security data for this key */
132 time_t expiry; /* time at which key expires (or 0) */ 132 union {
133 time_t expiry; /* time at which key expires (or 0) */
134 time_t revoked_at; /* time at which key was revoked */
135 };
133 uid_t uid; 136 uid_t uid;
134 gid_t gid; 137 gid_t gid;
135 key_perm_t perm; /* access permissions */ 138 key_perm_t perm; /* access permissions */
diff --git a/security/keys/Makefile b/security/keys/Makefile
index 747a464943af..74d5447d7df7 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -3,6 +3,7 @@
3# 3#
4 4
5obj-y := \ 5obj-y := \
6 gc.o \
6 key.o \ 7 key.o \
7 keyring.o \ 8 keyring.o \
8 keyctl.o \ 9 keyctl.o \
diff --git a/security/keys/gc.c b/security/keys/gc.c
new file mode 100644
index 000000000000..44adc325e15c
--- /dev/null
+++ b/security/keys/gc.c
@@ -0,0 +1,193 @@
1/* Key garbage collector
2 *
3 * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/module.h>
13#include <keys/keyring-type.h>
14#include "internal.h"
15
16/*
17 * Delay between key revocation/expiry in seconds
18 */
19unsigned key_gc_delay = 5 * 60;
20
21/*
22 * Reaper
23 */
24static void key_gc_timer_func(unsigned long);
25static void key_garbage_collector(struct work_struct *);
26static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0);
27static DECLARE_WORK(key_gc_work, key_garbage_collector);
28static key_serial_t key_gc_cursor; /* the last key the gc considered */
29static unsigned long key_gc_executing;
30static time_t key_gc_next_run = LONG_MAX;
31
32/*
33 * Schedule a garbage collection run
34 * - precision isn't particularly important
35 */
36void key_schedule_gc(time_t gc_at)
37{
38 unsigned long expires;
39 time_t now = current_kernel_time().tv_sec;
40
41 kenter("%ld", gc_at - now);
42
43 gc_at += key_gc_delay;
44
45 if (now >= gc_at) {
46 schedule_work(&key_gc_work);
47 } else if (gc_at < key_gc_next_run) {
48 expires = jiffies + (gc_at - now) * HZ;
49 mod_timer(&key_gc_timer, expires);
50 }
51}
52
53/*
54 * The garbage collector timer kicked off
55 */
56static void key_gc_timer_func(unsigned long data)
57{
58 kenter("");
59 key_gc_next_run = LONG_MAX;
60 schedule_work(&key_gc_work);
61}
62
63/*
64 * Garbage collect pointers from a keyring
65 * - return true if we altered the keyring
66 */
67static bool key_gc_keyring(struct key *keyring, time_t limit)
68{
69 struct keyring_list *klist;
70 struct key *key;
71 int loop;
72
73 kenter("%x", key_serial(keyring));
74
75 if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
76 goto dont_gc;
77
78 /* scan the keyring looking for dead keys */
79 klist = rcu_dereference(keyring->payload.subscriptions);
80 if (!klist)
81 goto dont_gc;
82
83 for (loop = klist->nkeys - 1; loop >= 0; loop--) {
84 key = klist->keys[loop];
85 if (test_bit(KEY_FLAG_DEAD, &key->flags) ||
86 (key->expiry > 0 && key->expiry <= limit))
87 goto do_gc;
88 }
89
90dont_gc:
91 kleave(" = false");
92 return false;
93
94do_gc:
95 key_gc_cursor = keyring->serial;
96 key_get(keyring);
97 spin_unlock(&key_serial_lock);
98 keyring_gc(keyring, limit);
99 key_put(keyring);
100 kleave(" = true");
101 return true;
102}
103
104/*
105 * Garbage collector for keys
106 * - this involves scanning the keyrings for dead, expired and revoked keys
107 * that have overstayed their welcome
108 */
109static void key_garbage_collector(struct work_struct *work)
110{
111 struct rb_node *rb;
112 key_serial_t cursor;
113 struct key *key, *xkey;
114 time_t new_timer = LONG_MAX, limit;
115
116 kenter("");
117
118 if (test_and_set_bit(0, &key_gc_executing)) {
119 key_schedule_gc(current_kernel_time().tv_sec);
120 return;
121 }
122