aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/keys/gc.c73
1 files changed, 44 insertions, 29 deletions
diff --git a/security/keys/gc.c b/security/keys/gc.c
index a42b45531aac..27610bf72195 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -168,38 +168,45 @@ do_gc:
168} 168}
169 169
170/* 170/*
171 * Garbage collect an unreferenced, detached key 171 * Garbage collect a list of unreferenced, detached keys
172 */ 172 */
173static noinline void key_gc_unused_key(struct key *key) 173static noinline void key_gc_unused_keys(struct list_head *keys)
174{ 174{
175 key_check(key); 175 while (!list_empty(keys)) {
176 176 struct key *key =
177 security_key_free(key); 177 list_entry(keys->next, struct key, graveyard_link);
178 178 list_del(&key->graveyard_link);
179 /* deal with the user's key tracking and quota */ 179
180 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { 180 kdebug("- %u", key->serial);
181 spin_lock(&key->user->lock); 181 key_check(key);
182 key->user->qnkeys--; 182
183 key->user->qnbytes -= key->quotalen; 183 security_key_free(key);
184 spin_unlock(&key->user->lock); 184
185 } 185 /* deal with the user's key tracking and quota */
186 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
187 spin_lock(&key->user->lock);
188 key->user->qnkeys--;
189 key->user->qnbytes -= key->quotalen;
190 spin_unlock(&key->user->lock);
191 }
186 192
187 atomic_dec(&key->user->nkeys); 193 atomic_dec(&key->user->nkeys);
188 if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) 194 if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
189 atomic_dec(&key->user->nikeys); 195 atomic_dec(&key->user->nikeys);
190 196
191 key_user_put(key->user); 197 key_user_put(key->user);
192 198
193 /* now throw away the key memory */ 199 /* now throw away the key memory */
194 if (key->type->destroy) 200 if (key->type->destroy)
195 key->type->destroy(key); 201 key->type->destroy(key);
196 202
197 kfree(key->description); 203 kfree(key->description);
198 204
199#ifdef KEY_DEBUGGING 205#ifdef KEY_DEBUGGING
200 key->magic = KEY_DEBUG_MAGIC_X; 206 key->magic = KEY_DEBUG_MAGIC_X;
201#endif 207#endif
202 kmem_cache_free(key_jar, key); 208 kmem_cache_free(key_jar, key);
209 }
203} 210}
204 211
205/* 212/*
@@ -211,6 +218,7 @@ static noinline void key_gc_unused_key(struct key *key)
211 */ 218 */
212static void key_garbage_collector(struct work_struct *work) 219static void key_garbage_collector(struct work_struct *work)
213{ 220{
221 static LIST_HEAD(graveyard);
214 static u8 gc_state; /* Internal persistent state */ 222 static u8 gc_state; /* Internal persistent state */
215#define KEY_GC_REAP_AGAIN 0x01 /* - Need another cycle */ 223#define KEY_GC_REAP_AGAIN 0x01 /* - Need another cycle */
216#define KEY_GC_REAPING_LINKS 0x02 /* - We need to reap links */ 224#define KEY_GC_REAPING_LINKS 0x02 /* - We need to reap links */
@@ -316,15 +324,22 @@ maybe_resched:
316 key_schedule_gc(new_timer); 324 key_schedule_gc(new_timer);
317 } 325 }
318 326
319 if (unlikely(gc_state & KEY_GC_REAPING_DEAD_2)) { 327 if (unlikely(gc_state & KEY_GC_REAPING_DEAD_2) ||
320 /* Make sure everyone revalidates their keys if we marked a 328 !list_empty(&graveyard)) {
321 * bunch as being dead and make sure all keyring ex-payloads 329 /* Make sure that all pending keyring payload destructions are
322 * are destroyed. 330 * fulfilled and that people aren't now looking at dead or
331 * dying keys that they don't have a reference upon or a link
332 * to.
323 */ 333 */
324 kdebug("dead sync"); 334 kdebug("gc sync");
325 synchronize_rcu(); 335 synchronize_rcu();
326 } 336 }
327 337
338 if (!list_empty(&graveyard)) {
339 kdebug("gc keys");
340 key_gc_unused_keys(&graveyard);
341 }
342
328 if (unlikely(gc_state & (KEY_GC_REAPING_DEAD_1 | 343 if (unlikely(gc_state & (KEY_GC_REAPING_DEAD_1 |
329 KEY_GC_REAPING_DEAD_2))) { 344 KEY_GC_REAPING_DEAD_2))) {
330 if (!(gc_state & KEY_GC_FOUND_DEAD_KEY)) { 345 if (!(gc_state & KEY_GC_FOUND_DEAD_KEY)) {
@@ -359,7 +374,7 @@ found_unreferenced_key:
359 rb_erase(&key->serial_node, &key_serial_tree); 374 rb_erase(&key->serial_node, &key_serial_tree);
360 spin_unlock(&key_serial_lock); 375 spin_unlock(&key_serial_lock);
361 376
362 key_gc_unused_key(key); 377 list_add_tail(&key->graveyard_link, &graveyard);
363 gc_state |= KEY_GC_REAP_AGAIN; 378 gc_state |= KEY_GC_REAP_AGAIN;
364 goto maybe_resched; 379 goto maybe_resched;
365 380