aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2005-06-24 01:00:53 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-24 03:05:18 -0400
commit8589b4e00e352f983259140f25a262d973be6bc5 (patch)
treed53c9b43ee0aaa2d7518a023c4b6373422117506 /security/keys
parent7888e7ff4ee579442128d7d12a9c9dbf2cf7de6a (diff)
[PATCH] Keys: Use RCU to manage session keyring pointer
The attached patch uses RCU to manage the session keyring pointer in struct signal_struct. This means that searching need not disable interrupts and get a the sighand spinlock to access this pointer. Furthermore, by judicious use of rcu_read_(un)lock(), this patch also avoids the need to take and put refcounts on the session keyring itself, thus saving on even more atomic ops. Signed-Off-By: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/process_keys.c42
-rw-r--r--security/keys/request_key.c7
2 files changed, 24 insertions, 25 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 059c350cac4..972e3017268 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -1,6 +1,6 @@
1/* process_keys.c: management of a process's keyrings 1/* process_keys.c: management of a process's keyrings
2 * 2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -181,7 +181,7 @@ static int install_process_keyring(struct task_struct *tsk)
181 goto error; 181 goto error;
182 } 182 }
183 183
184 /* attach or swap keyrings */ 184 /* attach keyring */
185 spin_lock_irqsave(&tsk->sighand->siglock, flags); 185 spin_lock_irqsave(&tsk->sighand->siglock, flags);
186 if (!tsk->signal->process_keyring) { 186 if (!tsk->signal->process_keyring) {
187 tsk->signal->process_keyring = keyring; 187 tsk->signal->process_keyring = keyring;
@@ -227,12 +227,14 @@ static int install_session_keyring(struct task_struct *tsk,
227 227
228 /* install the keyring */ 228 /* install the keyring */
229 spin_lock_irqsave(&tsk->sighand->siglock, flags); 229 spin_lock_irqsave(&tsk->sighand->siglock, flags);
230 old = tsk->signal->session_keyring; 230 old = rcu_dereference(tsk->signal->session_keyring);
231 tsk->signal->session_keyring = keyring; 231 rcu_assign_pointer(tsk->signal->session_keyring, keyring);
232 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 232 spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
233 233
234 ret = 0; 234 ret = 0;
235 235
236 /* we're using RCU on the pointer */
237 synchronize_kernel();
236 key_put(old); 238 key_put(old);
237 error: 239 error:
238 return ret; 240 return ret;
@@ -245,8 +247,6 @@ static int install_session_keyring(struct task_struct *tsk,
245 */ 247 */
246int copy_thread_group_keys(struct task_struct *tsk) 248int copy_thread_group_keys(struct task_struct *tsk)
247{ 249{
248 unsigned long flags;
249
250 key_check(current->thread_group->session_keyring); 250 key_check(current->thread_group->session_keyring);
251 key_check(current->thread_group->process_keyring); 251 key_check(current->thread_group->process_keyring);
252 252
@@ -254,10 +254,10 @@ int copy_thread_group_keys(struct task_struct *tsk)
254 tsk->signal->process_keyring = NULL; 254 tsk->signal->process_keyring = NULL;
255 255
256 /* same session keyring */ 256 /* same session keyring */
257 spin_lock_irqsave(&current->sighand->siglock, flags); 257 rcu_read_lock();
258 tsk->signal->session_keyring = 258 tsk->signal->session_keyring =
259 key_get(current->signal->session_keyring); 259 key_get(rcu_dereference(current->signal->session_keyring));
260 spin_unlock_irqrestore(&current->sighand->siglock, flags); 260 rcu_read_unlock();
261 261
262 return 0; 262 return 0;
263 263
@@ -381,8 +381,7 @@ struct key *search_process_keyrings_aux(struct key_type *type,
381 key_match_func_t match) 381 key_match_func_t match)
382{ 382{
383 struct task_struct *tsk = current; 383 struct task_struct *tsk = current;
384 unsigned long flags; 384 struct key *key, *ret, *err;
385 struct key *key, *ret, *err, *tmp;
386 385
387 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 386 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
388 * searchable, but we failed to find a key or we found a negative key; 387 * searchable, but we failed to find a key or we found a negative key;
@@ -436,17 +435,18 @@ struct key *search_process_keyrings_aux(struct key_type *type,
436 } 435 }
437 436
438 /* search the session keyring last */ 437 /* search the session keyring last */
439 spin_lock_irqsave(&tsk->sighand->siglock, flags); 438 if (tsk->signal->session_keyring) {
440 439 rcu_read_lock();
441 tmp = tsk->signal->session_keyring; 440 key = keyring_search_aux(
442 if (!tmp) 441 rcu_dereference(tsk->signal->session_keyring),
443 tmp = tsk->user->session_keyring; 442 type, description, match);
444 atomic_inc(&tmp->usage); 443 rcu_read_unlock();
445 444 }
446 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 445 else {
446 key = keyring_search_aux(tsk->user->session_keyring,
447 type, description, match);
448 }
447 449
448 key = keyring_search_aux(tmp, type, description, match);
449 key_put(tmp);
450 if (!IS_ERR(key)) 450 if (!IS_ERR(key))
451 goto found; 451 goto found;
452 452
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 1919540f047..54aa7b70e63 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -175,13 +175,12 @@ static struct key *__request_key_construction(struct key_type *type,
175 key->expiry = now.tv_sec + key_negative_timeout; 175 key->expiry = now.tv_sec + key_negative_timeout;
176 176
177 if (current->signal->session_keyring) { 177 if (current->signal->session_keyring) {
178 unsigned long flags;
179 struct key *keyring; 178 struct key *keyring;
180 179
181 spin_lock_irqsave(&current->sighand->siglock, flags); 180 rcu_read_lock();
182 keyring = current->signal->session_keyring; 181 keyring = rcu_dereference(current->signal->session_keyring);
183 atomic_inc(&keyring->usage); 182 atomic_inc(&keyring->usage);
184 spin_unlock_irqrestore(&current->sighand->siglock, flags); 183 rcu_read_unlock();
185 184
186 key_link(keyring, key); 185 key_link(keyring, key);
187 key_put(keyring); 186 key_put(keyring);