Commit 3b149cc7 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] remove lock_kernel() from exec of setuid apps

Patch from Manfred Spraul <manfred@colorfullife.com>

exec of setuid apps and ptrace must be synchronized, to ensure that a normal
user cannot ptrace a setuid app across exec.  ptrace_attach acquires the
task_lock around the uid checks, compute_creds acquires the BLK.  The patch
converts compute_creds to the task_lock.  Additionally, it removes the
do_unlock variable: the task_lock is not heaviliy used, there is no need to
avoid the spinlock by adding branches.

The patch is a cleanup patch, not a fix for a security problem: AFAICS the
sys_ptrace in every arch acquires the BKL before calling ptrace_attach.
parent db54e742
......@@ -873,12 +873,10 @@ int prepare_binprm(struct linux_binprm *bprm)
void compute_creds(struct linux_binprm *bprm)
{
int do_unlock = 0;
task_lock(current);
if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
current->mm->dumpable = 0;
lock_kernel();
if (must_not_trace_exec(current)
|| atomic_read(&current->fs->count) > 1
|| atomic_read(&current->files->count) > 1
......@@ -888,14 +886,12 @@ void compute_creds(struct linux_binprm *bprm)
bprm->e_gid = current->gid;
}
}
do_unlock = 1;
}
current->suid = current->euid = current->fsuid = bprm->e_uid;
current->sgid = current->egid = current->fsgid = bprm->e_gid;
if(do_unlock)
unlock_kernel();
task_unlock(current);
security_bprm_compute_creds(bprm);
}
......
......@@ -120,17 +120,16 @@ void cap_bprm_compute_creds (struct linux_binprm *bprm)
{
/* Derived from fs/exec.c:compute_creds. */
kernel_cap_t new_permitted, working;
int do_unlock = 0;
new_permitted = cap_intersect (bprm->cap_permitted, cap_bset);
working = cap_intersect (bprm->cap_inheritable,
current->cap_inheritable);
new_permitted = cap_combine (new_permitted, working);
task_lock(current);
if (!cap_issubset (new_permitted, current->cap_permitted)) {
current->mm->dumpable = 0;
lock_kernel ();
if (must_not_trace_exec (current)
|| atomic_read (&current->fs->count) > 1
|| atomic_read (&current->files->count) > 1
......@@ -141,7 +140,6 @@ void cap_bprm_compute_creds (struct linux_binprm *bprm)
cap_permitted);
}
}
do_unlock = 1;
}
/* For init, we want to retain the capabilities set
......@@ -154,9 +152,7 @@ void cap_bprm_compute_creds (struct linux_binprm *bprm)
}
/* AUD: Audit candidate if current->cap_effective is set */
if (do_unlock)
unlock_kernel ();
task_unlock(current);
current->keep_capabilities = 0;
}
......
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