From 3b149cc7cd1573436468c1103b2f42f3fd0888a4 Mon Sep 17 00:00:00 2001 From: Andrew Morton <akpm@digeo.com> Date: Sun, 2 Feb 2003 06:06:58 -0800 Subject: [PATCH] [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. --- fs/exec.c | 8 ++------ security/capability.c | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 92716bc7c10b..69a19459e47d 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -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(¤t->fs->count) > 1 || atomic_read(¤t->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); } diff --git a/security/capability.c b/security/capability.c index 8e26f1f52b1a..cf6d2440a21d 100644 --- a/security/capability.c +++ b/security/capability.c @@ -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 (¤t->fs->count) > 1 || atomic_read (¤t->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; } -- 2.30.9