All of lore.kernel.org
 help / color / mirror / Atom feed
* signal/signal_deliver and bpf_send_signal()
@ 2021-08-13  9:57 Kevin Sheldrake
  2021-08-13 17:19 ` Yonghong Song
  0 siblings, 1 reply; 4+ messages in thread
From: Kevin Sheldrake @ 2021-08-13  9:57 UTC (permalink / raw)
  To: bpf

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?

Many thanks

Kev

--
Kevin Sheldrake
Microsoft Threat Intelligence Centre


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: signal/signal_deliver and bpf_send_signal()
  2021-08-13  9:57 signal/signal_deliver and bpf_send_signal() Kevin Sheldrake
@ 2021-08-13 17:19 ` Yonghong Song
  2021-08-13 23:08   ` Andrii Nakryiko
  0 siblings, 1 reply; 4+ messages in thread
From: Yonghong Song @ 2021-08-13 17:19 UTC (permalink / raw)
  To: Kevin Sheldrake, bpf



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?

> 
> Many thanks
> 
> Kev
> 
> --
> Kevin Sheldrake
> Microsoft Threat Intelligence Centre
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: signal/signal_deliver and bpf_send_signal()
  2021-08-13 17:19 ` Yonghong Song
@ 2021-08-13 23:08   ` Andrii Nakryiko
  2021-08-16  9:33     ` [EXTERNAL] " Kevin Sheldrake
  0 siblings, 1 reply; 4+ messages in thread
From: Andrii Nakryiko @ 2021-08-13 23:08 UTC (permalink / raw)
  To: Yonghong Song; +Cc: Kevin Sheldrake, bpf

On Fri, Aug 13, 2021 at 10:20 AM Yonghong Song <yhs@fb.com> 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?
>

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?

> >
> > Many thanks
> >
> > Kev
> >
> > --
> > Kevin Sheldrake
> > Microsoft Threat Intelligence Centre
> >

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [EXTERNAL] Re: signal/signal_deliver and bpf_send_signal()
  2021-08-13 23:08   ` Andrii Nakryiko
@ 2021-08-16  9:33     ` Kevin Sheldrake
  0 siblings, 0 replies; 4+ messages in thread
From: Kevin Sheldrake @ 2021-08-16  9:33 UTC (permalink / raw)
  To: Andrii Nakryiko, Yonghong Song; +Cc: bpf

> -----Original Message-----
> From: Andrii Nakryiko <andrii.nakryiko@gmail.com>
> Sent: 14 August 2021 00:08
> To: Yonghong Song <yhs@fb.com>
> Cc: Kevin Sheldrake <Kevin.Sheldrake@microsoft.com>; bpf
> <bpf@vger.kernel.org>
> Subject: [EXTERNAL] Re: signal/signal_deliver and bpf_send_signal()
> 
> On Fri, Aug 13, 2021 at 10:20 AM Yonghong Song <yhs@fb.com> 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


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-08-16  9:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-13  9:57 signal/signal_deliver and bpf_send_signal() Kevin Sheldrake
2021-08-13 17:19 ` Yonghong Song
2021-08-13 23:08   ` Andrii Nakryiko
2021-08-16  9:33     ` [EXTERNAL] " Kevin Sheldrake

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.