Commit 8589b4e0 authored by David Howells's avatar David Howells Committed by Linus Torvalds

[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: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7888e7ff
/* process_keys.c: management of a process's keyrings
*
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
* Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
......@@ -181,7 +181,7 @@ static int install_process_keyring(struct task_struct *tsk)
goto error;
}
/* attach or swap keyrings */
/* attach keyring */
spin_lock_irqsave(&tsk->sighand->siglock, flags);
if (!tsk->signal->process_keyring) {
tsk->signal->process_keyring = keyring;
......@@ -227,12 +227,14 @@ static int install_session_keyring(struct task_struct *tsk,
/* install the keyring */
spin_lock_irqsave(&tsk->sighand->siglock, flags);
old = tsk->signal->session_keyring;
tsk->signal->session_keyring = keyring;
old = rcu_dereference(tsk->signal->session_keyring);
rcu_assign_pointer(tsk->signal->session_keyring, keyring);
spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
ret = 0;
/* we're using RCU on the pointer */
synchronize_kernel();
key_put(old);
error:
return ret;
......@@ -245,8 +247,6 @@ static int install_session_keyring(struct task_struct *tsk,
*/
int copy_thread_group_keys(struct task_struct *tsk)
{
unsigned long flags;
key_check(current->thread_group->session_keyring);
key_check(current->thread_group->process_keyring);
......@@ -254,10 +254,10 @@ int copy_thread_group_keys(struct task_struct *tsk)
tsk->signal->process_keyring = NULL;
/* same session keyring */
spin_lock_irqsave(&current->sighand->siglock, flags);
rcu_read_lock();
tsk->signal->session_keyring =
key_get(current->signal->session_keyring);
spin_unlock_irqrestore(&current->sighand->siglock, flags);
key_get(rcu_dereference(current->signal->session_keyring));
rcu_read_unlock();
return 0;
......@@ -381,8 +381,7 @@ struct key *search_process_keyrings_aux(struct key_type *type,
key_match_func_t match)
{
struct task_struct *tsk = current;
unsigned long flags;
struct key *key, *ret, *err, *tmp;
struct key *key, *ret, *err;
/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
* 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,
}
/* search the session keyring last */
spin_lock_irqsave(&tsk->sighand->siglock, flags);
tmp = tsk->signal->session_keyring;
if (!tmp)
tmp = tsk->user->session_keyring;
atomic_inc(&tmp->usage);
spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
if (tsk->signal->session_keyring) {
rcu_read_lock();
key = keyring_search_aux(
rcu_dereference(tsk->signal->session_keyring),
type, description, match);
rcu_read_unlock();
}
else {
key = keyring_search_aux(tsk->user->session_keyring,
type, description, match);
}
key = keyring_search_aux(tmp, type, description, match);
key_put(tmp);
if (!IS_ERR(key))
goto found;
......
......@@ -175,13 +175,12 @@ static struct key *__request_key_construction(struct key_type *type,
key->expiry = now.tv_sec + key_negative_timeout;
if (current->signal->session_keyring) {
unsigned long flags;
struct key *keyring;
spin_lock_irqsave(&current->sighand->siglock, flags);
keyring = current->signal->session_keyring;
rcu_read_lock();
keyring = rcu_dereference(current->signal->session_keyring);
atomic_inc(&keyring->usage);
spin_unlock_irqrestore(&current->sighand->siglock, flags);
rcu_read_unlock();
key_link(keyring, key);
key_put(keyring);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment