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