On 04/16, Roland McGrath wrote:
>
> But even that is a lot of hair for the incremental patches in the first
> several stages, I think.  So just never deallocate it, and:
>
>       static inline int task_ptrace(struct task_struct *task)
>       {
>               return unlikely(task->ptrace_child) ? task->ptrace_child->flags 
> : 0;
>       }

OK, agreed.

Except... personally I dislike ->flags, it is not greppable.

> > even ptracer can't safely access
> > child->ptrace_child->ptrace_flags. Once sys_ptrace() drops tasklist,
> > child's sub-thread can do exec, and de_thread() can untrace the child
> > and free ->ptrace_child.
>
> This kind of trouble is why going to dynamic allocation should start
> with never-deallocate (i.e. until release_task or something).

Yes, except release_task() doesn't work. I think it should be freed
by __put_task_struct(). Proc can read ->ptrace_child and race with
release_task().

> >             // was task_struct->parent
> >             struct task_struct *ptrace_parent;
>
> struct ptrace_task.tracer, please. :-)

OK. I'll send the first patch (or 2 patches) which introduces ptrace_task
and moves ->ptrace into it tomorrow. The patch is simple, but intrusive.


Now the questions. First of all, what does task_lock() currently mean
from the ptrace pov ?

Afaics ptrace_attach() needs this lock only to pin ->mm, no other other
reasons. ptrace_traceme() doesn't need it at all.

The comment above tracehook_unsafe_exec() says "Called with task_lock()",
this is wrong, check_unsafe_exec() doesn't take task_lock().

The only place which believes task_lock() can help is sys_execve() on
some arches, the code clears PT_DTRACE under task_lock(). Why, and what
PT_DTRACE actually means?

I don't understand PT_DTRACE, but looking at the code I assume it can
only be set when the task is ptraced. Right?

arch/m68k/kernel/traps.c:trap_c() does current->ptrace |= PT_DTRACE.
Again, can I assume this can only happen when the task is already
traced? Otherwise, we have a problem with allocationg of ->ptrace_task
(and this is racy with ptrace_attach of course).

Perhaps it makes sense to do a little cleanup first, introduce

        ptrace_clear_dtrace(void)
        {
                if (unlikely(current->ptrace & PT_DTRACE))
                        current->ptrace &= ~PT_DTRACE;
        }

This can't race with the tracer, it never changes ->ptrace flags until
the tracee is TASK_TRACED.

The last question. ptrace_attach() does

        task->ptrace |= PT_PTRACED;

Why can't we use the plain "=" instead of "|=" ? This looks as if ->ptrace
can be nonzero even if the task is not traced. But I assume this is not
possible? And any code which does "if (p->ptrace & PT_TRACED)" could just
do "if (p->ptrace)", right?

Oleg.

Reply via email to