keys: change keyctl_session_to_parent() to use task_work_add()
Change keyctl_session_to_parent() to use task_work_add() and move key_replace_session_keyring() logic into task_work->func(). Note that we do task_work_cancel() before task_work_add() to ensure that only one work can be pending at any time. This is important, we must not allow user-space to abuse the parent's ->task_works list. The callback, replace_session_keyring(), checks PF_EXITING. I guess this is not really needed but looks better. As a side effect, this fixes the (unlikely) race. The callers of key_replace_session_keyring() and keyctl_session_to_parent() lack the necessary barriers, the parent can miss the request. Now we can remove task_struct->replacement_session_keyring and related code. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: David Howells <dhowells@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Richard Kuo <rkuo@codeaurora.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Alexander Gordeev <agordeev@redhat.com> Cc: Chris Zankel <chris@zankel.net> Cc: David Smith <dsmith@redhat.com> Cc: "Frank Ch. Eigler" <fche@redhat.com> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Larry Woodman <lwoodman@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Tejun Heo <tj@kernel.org> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
@@ -834,23 +834,17 @@ error:
|
||||
* Replace a process's session keyring on behalf of one of its children when
|
||||
* the target process is about to resume userspace execution.
|
||||
*/
|
||||
void key_replace_session_keyring(void)
|
||||
void key_change_session_keyring(struct task_work *twork)
|
||||
{
|
||||
const struct cred *old;
|
||||
struct cred *new;
|
||||
const struct cred *old = current_cred();
|
||||
struct cred *new = twork->data;
|
||||
|
||||
if (!current->replacement_session_keyring)
|
||||
kfree(twork);
|
||||
if (unlikely(current->flags & PF_EXITING)) {
|
||||
put_cred(new);
|
||||
return;
|
||||
}
|
||||
|
||||
write_lock_irq(&tasklist_lock);
|
||||
new = current->replacement_session_keyring;
|
||||
current->replacement_session_keyring = NULL;
|
||||
write_unlock_irq(&tasklist_lock);
|
||||
|
||||
if (!new)
|
||||
return;
|
||||
|
||||
old = current_cred();
|
||||
new-> uid = old-> uid;
|
||||
new-> euid = old-> euid;
|
||||
new-> suid = old-> suid;
|
||||
|
Reference in New Issue
Block a user