Re: 2.4+ptrace exploit fix breaks root's ability to strace

Yusuf Wilajati Purna
2003-04-22T04:52:04Z

Hi,

Thanks for the clarification. :-)

Bernhard Kaindl wrote:

>On Thu, 17 Apr 2003, Yusuf Wilajati Purna wrote:
>
>>On 2003-03-22 17:28:54, Arjan van de Ven wrote:
>>
>>>On Sat, Mar 22, 2003 at 05:13:12PM +0000, Russell King wrote:
>>>
>>>>int ptrace_check_attach(struct task_struct *child, int kill)
>>>>{
>>>> ...
>>>>+ if (!is_dumpable(child))
>>>>+ return -EPERM;
>>>>}
>>>>
>>>>So, we went from being able to ptrace daemons as root, to being able to
>>>>attach daemons and then being unable to do anything with them, even if
>>>>you're root (or have the CAP_SYS_PTRACE capability). I think this
>>>>behaviour is getting on for being described as "insane" 8) and is
>>>>clearly wrong.
>>>>
>>>ok it seems this check is too strong. It *has* to check
>>>child->task_dumpable and return -EPERM, but child->mm->dumpable is not
>>>needed.
>>>
>>So, do you mean that the following is enough:
>>
>>int ptrace_check_attach(struct task_struct *child, int kill)
>>{
>> ...
>>+ if (!child->task_dumpable)
>>+ return -EPERM;
>>}
>>
>
>It's enough to still be safe against the ptrace/kmod exploits.
>
>I could not find a security problem in it yet because
>compute_cred() ignores the suid bit on exec when the
>process is being traced, so the strace does not get
>access to privileges from somebody else and ptrace_attach
>uses is_dumpable() which also checks task->mm->dumpable
>so a tracer can't attach to a suid program.
>
>It will also help the case Russell King describes above
>where root failed to trace a daemon which changed uids
>or a suid program, AFAICS.
>
>It is not the complete fix for it because the ptrace functions
>also use access_process_vm() where the patch had this hunk:
>
>@@ -123,6 +127,8 @@ int access_process_vm(struct task_struct
> /* Worry about races with exit() */
> task_lock(tsk);
> mm = tsk->mm;
>+ if (!is_dumpable(tsk) || (&init_mm == mm))
>+ mm = NULL;
> if (mm)
> atomic_inc(&mm->mm_users);
> task_unlock(tsk);
>
>You need to backout the tsk->mm->dumpable check done within is_dumpable
>here by just checking task_dumpable and then ptracing from root works
>prperly again.
>
>As the kmod ptrace fix relies on task_dumpable for it's protection against
>kernel thread trace, and you just remove the tsk->mm->dumpable check by
>replacing !is_dumpable(tsk) with !tsk->task_dumpable here also, you don't
>affect the kmod ptrace exploit protection in any way while fixing the
>ability of root to trace any task.
>
>This also fixes the problem /proc/<pid>/cmdline being empty (also for root)
>if <pid> is not dumpable, which is the other bug introduced by this hunk
>and broke process managment tools as it was also read on l-k.
>
Just to recapitulate,
The following changes to the original patch (Alan's patch):

int ptrace_check_attach(struct task_struct *child, int kill)
{
...
+ if (!child->task_dumpable)
+ return -EPERM;
}

int access_process_vm(struct task_struct *tsk, unsigned long addr,
void *buf, int len, int write)
{
...
/* Worry about races with exit() */
task_lock(tsk);
mm = tsk->mm;
+ if (!tsk->task_dumpable || (&init_mm == mm))
+ mm = NULL;
...
}

can solve the following side-effects introduced by the original patch:

- /proc/PID/cmdline and /proc/PID/environ are empty for non-dumpable
process es
even for root. (ps displays those processes in [] brackets.)
http://marc.theaimsgroup.com/?l=linux-kernel&m=104807368719299&w=2

- strace started by root cannot ptrace user threads or such non-dumpable
processes.
http://marc.theaimsgroup.com/?l=linux-kernel&m=104835339619706&w=2

At least, I have confirmed this on an i386/IA-32 platform. And I have
checked also
that ptrace/kmod exploits such as isec-ptrace-kmod-exploit.c, ptrace.c,
km3.c cannot
get root privilege with the changes.

Any comments?

Thanks,
Purna