> -----Original Message----- > From: Andrii Nakryiko <andrii.nakryiko@xxxxxxxxx> > Sent: 14 August 2021 00:08 > To: Yonghong Song <yhs@xxxxxx> > Cc: Kevin Sheldrake <Kevin.Sheldrake@xxxxxxxxxxxxx>; bpf > <bpf@xxxxxxxxxxxxxxx> > Subject: [EXTERNAL] Re: signal/signal_deliver and bpf_send_signal() > > On Fri, Aug 13, 2021 at 10:20 AM Yonghong Song <yhs@xxxxxx> wrote: > > > > > > > > On 8/13/21 2:57 AM, Kevin Sheldrake wrote: > > > Hello > > > > > > I have a requirement to catch a specific signal hitting a specific process > and to send it a SIGSTOP before that signal arrives. This is so that the process > can then be attached with ptrace(), but without the necessity of ptrace()ing > the process continuously beforehand (due to performance and stability > reasons). I thought this might be possible with an eBPF program attached to > a tracepoint. > > > > > > I attached a program to the signal/signal_deliver tracepoint and used > bpf_send_signal() to send the SIGSTOP but it didn't stop the process. If I > sent SIGTERM or SIGHUP instead it worked as expected, just not SIGSTOP or > SIGTSTP. > > > > > > Sending a SIGSTOP prior to another signal (eg SIGSEGV) works from > userland - the process stops and the other signal is queued. > > > > > > I'm guessing that the reason is that bpf_send_signal() adds the (non- > state transitioning) signal to the process signal queue, ignoring SIGSTOP, > SIGTSTP, SIGKILL, SIGCONT, but doesn't change the state of processes. Can > anyone confirm if that is correct or if there's another possible reason that > bpf_send_signal seems to fail to send a SIGSTOP? If so, is this documented > anywhere? Is there another way to do this with eBPF? > > > > Kernel has SIG_KERNEL_IGNORE_MASK like below > > > > #define SIG_KERNEL_IGNORE_MASK (\ > > rt_sigmask(SIGCONT) | rt_sigmask(SIGCHLD) | \ > > rt_sigmask(SIGWINCH) | rt_sigmask(SIGURG) ) > > > > So SIGCONT will be ignored for bpf_send_signal() helper. > > > > For other signals e.g., SIGSTOP/SIGKILL, there are some comments saying > > special processing might be needed. But I think they may still get > > delivered. If you use signal/signal_deliver when SIGSEGV is delivered, > > is it already too late to do bpf_send_signal() SIGSTOP since that > > will be processed after SIGSEGV? Note that SIGSEGV is already delivered? Thanks both for your responses. Regarding this one, if I send SIGHUP or SIGTERM then it arrives before the SIGSEGV, so I don't believe it is a case Of SIGSEGV winning the race. I'm therefore going to assume the special processing is needed and missing. Thanks for looking into this though. > Too lazy to read the code to know if this will work, but I'll ask > anyway. Would it work to do fmod_ret BPF prog right on the entry point > in the kernel where the signal is just starting to be processed, and > ignoring SIGSEGV completely? Then doing send_signal(SIGSTOP), and then > again for SIGSEGV? > > So, intercept and cancel original signal, inject SIGSTOP, re-introduce > original signal? This is a clever idea but I'm targeting kernels pre 5.5 where fentry etc were introduced. If I can shift the requirements to >=5.5 then I'll go down this route and report back. Thanks for the idea. Kev -- Kevin Sheldrake Microsoft Threat Intelligence Centre