2021-01-31 13:46:37

by Dmitry Vyukov

[permalink] [raw]
Subject: extended bpf_send_signal_thread with argument

Hi,

I would like to send a signal from a bpf program invoked from a
perf_event. There is:

// kernel/trace/bpf_trace.c
BPF_CALL_1(bpf_send_signal_thread, u32, sig)

which is nice, but it does not allow me to pass any arguments.
I can use a bpf map indexed by pid to "pass" some additional info, but
it's messy and slow (and may cause some synchronization issues, I am
not sure yet).

Signals allow to pass additional arguments, it would be nice to expose
this to bpf programs as well. Any objections? Do you see any potential
issues with this? On the implementation side it seems to be almost
trivial to add something like this:

BPF_CALL_2(bpf_send_signal_thread_ex, u32, sig, uintptr_t sival)

However, siginfo_t is way larger and allows to pass a whole lot of
info, and the latest user-space APIs pidfd_send_signal just directly
accepts siginfo_t (and rt_tgsigqueueinfo as well). But I am not sure
how to expose it according to bpf rules. Could we do something like
(pass whatever you want, it's your business)?

BPF_CALL_2(bpf_send_signal_thread_ex, u32, sig, char siginfo[sizeof(siginfo_t)])

Does it make sense? If yes, what would be the best way to expose this?

Thanks


2021-02-01 09:25:51

by Peter Zijlstra

[permalink] [raw]
Subject: Re: extended bpf_send_signal_thread with argument

On Sun, Jan 31, 2021 at 12:14:02PM +0100, Dmitry Vyukov wrote:
> Hi,
>
> I would like to send a signal from a bpf program invoked from a
> perf_event. There is:

You can't. Sending signals requires sighand lock, and you're not allowed
to take locks from perf_event context.

2021-02-01 09:46:51

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: extended bpf_send_signal_thread with argument

On Mon, Feb 1, 2021 at 10:22 AM Peter Zijlstra <[email protected]> wrote:
>
> On Sun, Jan 31, 2021 at 12:14:02PM +0100, Dmitry Vyukov wrote:
> > Hi,
> >
> > I would like to send a signal from a bpf program invoked from a
> > perf_event. There is:
>
> You can't. Sending signals requires sighand lock, and you're not allowed
> to take locks from perf_event context.


Then we just found a vulnerability because there is
bpf_send_signal_thread which can be attached to perf and it passes the
verifier :)
https://elixir.bootlin.com/linux/v5.11-rc5/source/kernel/trace/bpf_trace.c#L1145

It can defer sending the signal to the exit of irq context:
https://elixir.bootlin.com/linux/v5.11-rc5/source/kernel/trace/bpf_trace.c#L1108
Perhaps this is what makes it work?

2021-02-01 13:39:11

by Peter Zijlstra

[permalink] [raw]
Subject: Re: extended bpf_send_signal_thread with argument

On Mon, Feb 01, 2021 at 10:42:47AM +0100, Dmitry Vyukov wrote:
> On Mon, Feb 1, 2021 at 10:22 AM Peter Zijlstra <[email protected]> wrote:
> >
> > On Sun, Jan 31, 2021 at 12:14:02PM +0100, Dmitry Vyukov wrote:
> > > Hi,
> > >
> > > I would like to send a signal from a bpf program invoked from a
> > > perf_event. There is:
> >
> > You can't. Sending signals requires sighand lock, and you're not allowed
> > to take locks from perf_event context.
>
>
> Then we just found a vulnerability because there is
> bpf_send_signal_thread which can be attached to perf and it passes the
> verifier :)
> https://elixir.bootlin.com/linux/v5.11-rc5/source/kernel/trace/bpf_trace.c#L1145
>
> It can defer sending the signal to the exit of irq context:
> https://elixir.bootlin.com/linux/v5.11-rc5/source/kernel/trace/bpf_trace.c#L1108
> Perhaps this is what makes it work?

Yes.