> +static int ptrace_rw_siginfo(struct task_struct *tracee,
> +                             struct ptrace_context *context,
> +                             siginfo_t *info, bool write)
> +{
> +     unsigned long flags;
> +     siginfo_t *context_info;
> +     int err = -ESRCH;
> +
> +     if (!lock_task_sighand(tracee, &flags))
> +             return err;
> +     /*
> +      * Make sure the compiler reads ->siginfo only once, if we race
> +      * with SIGKILL ->siginfo can be cleared under us. But the memory
> +      * it points to can't go away, and since we hold ->siglock we can't
> +      * race with get_signal_to_deliver() pathes clobber this memory.

s/pathes clobber/paths that clobber/

> +      * See also the comment in ptrace_report_signal().
> +      */
> +     context_info = ACCESS_ONCE(context->siginfo);
> +     if (context_info) {
> +             if (write)
> +                     *context_info = *info;
> +             else
> +                     *info = *context_info;
> +             err = 0;
> +     }
> +     unlock_task_sighand(tracee, &flags);

Couldn't we instead do:

        context_info = ACCESS_ONCE(context->siginfo);
        if (context_info) {
                *info = *context_info;
                smp_rmb();
                if (ACCESS_ONCE(context->siginfo))
                        err = 0;
        }

and never use the siglock for the reading case?  If SIGKILL races, then
we see the ptr cleared later and abandon our (maybe half garbage) copy.

I guess it's not worth the bother, the old code uses the siglock anyway.


Thanks,
Roland

Reply via email to