> +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