* HID-BPF: CAP_BPF-only process can inject input into host session
@ 2026-10-12 8:47 Shi Lecun
2026-10-13 16:00 ` Benjamin Tissoires
0 siblings, 1 reply; 2+ messages in thread
From: Shi Lecun @ 2026-10-12 8:47 UTC (permalink / raw)
To: linux-input; +Cc: jikos, bentiss, bpf
Hi,
Granting a workload permission to manage eBPF can also grant it the
ability to type on the host.
A process that holds only CAP_BPF, running as a non-root user inside a
container with no device nodes and no X11 or Wayland socket, can load a
BPF_PROG_TYPE_SYSCALL program that calls hid_bpf_allocate_context() and
hid_bpf_input_report(), run it through BPF_PROG_TEST_RUN, and inject
keyboard reports into an already-authorized HID device. The reports
travel the normal HID input path and reach the host's unlocked session
(X11 desktop or text console) as if typed on the device, so the attacker
executes commands as the logged-in user; on a server with a management
controller, that session is the operator's console. Container platforms
grant CAP_BPF to networking and observability workloads, so the
capability holder is realistic rather than contrived.
Detailed description:
- Problem: the unattached syscall path can inject input with CAP_BPF
alone. Attaching a struct_ops program to a device requires
CAP_BPF+CAP_PERFMON, but a syscall program calling
hid_bpf_input_report() needs only CAP_BPF and leaves no per-device
record.
- Reachability: a non-root container holding CAP_BPF, one
already-authorized HID device, and an unlocked session. No malicious
device, firmware, USB traffic, verifier flaw or memory-safety bug is
involved.
- Effect: arbitrary commands typed as the host user in the focused
session, including a server's BMC virtual console. With CAP_PERFMON,
the struct_ops path can in addition rewrite the report descriptor so
an authorized mouse presents a keyboard collection.
- Method and testing: a reproducer built against the struct_ops HID-BPF
API, run in QEMU on Ubuntu 26.04 / kernel 7.0.0-28-generic
(CONFIG_HID_BPF=y, BTF enabled) and on an Arch 7.1.5 host.
Capability-restricted non-root runs with setpriv confirm the three
cases above; 1000 of 1000 injections were accepted; commands landed in
both an X session and a text console. Older, pre-struct_ops kernels
are untested.
- Possible fix: a capability check on the syscall path that reaches
hid_bpf_input_report()/hid_bpf_try_input_report(), or a policy gate at
program load. We implemented the latter as an LSM program on
security_bpf_prog_load that denies a load calling any of the seven
HID-BPF kfuncs; it stops the injector with -EPERM and costs about
24 us on a worst-case 4096-instruction load, with no input-path cost.
My reading is that this is not a kernel vulnerability: the program is
verifier-clean, no check is bypassed and nothing is memory-unsafe -- the
malice is in the report data. The behavior also matches
Documentation/hid/hid-bpf.rst, which documents hid_bpf_input_report()
from syscall programs and already calls the tracing use case "god-mode".
What I cannot settle myself is whether the capability split is what you
intended.
The one point I would like an answer on is the asymmetry itself: if the
CAP_PERFMON requirement is about the attach/IRQ context rather than
about input, then this is expected and I have no further concern. If you
would rather close it, I can post the LSM gate, though it is not the only
possible fix.
What I am asking for:
1. Confirm or correct the reading above.
2. If it is a bug: say so, and I will follow the security process
instead.
3. If it is intended: a short statement on this thread would help, and
with your permission I would cite it as the maintainers' position. I
am not asking for a CVE or for you to endorse the paper.
This comes from a paper we are preparing. It is not submitted yet and
nothing will be published for some time, so there is no deadline here.
The reproducer, logs and code are available on request, and I am happy to
discuss everything on the list.
Thanks,
Shi Lecun <shilc2025@mail.sustech.edu.cn>
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: HID-BPF: CAP_BPF-only process can inject input into host session
2026-10-12 8:47 HID-BPF: CAP_BPF-only process can inject input into host session Shi Lecun
@ 2026-10-13 16:00 ` Benjamin Tissoires
0 siblings, 0 replies; 2+ messages in thread
From: Benjamin Tissoires @ 2026-10-13 16:00 UTC (permalink / raw)
To: Shi Lecun; +Cc: linux-input, jikos, bpf
Hi,
On Oct 12 2026, Shi Lecun wrote:
> Hi,
>
> Granting a workload permission to manage eBPF can also grant it the
> ability to type on the host.
>
> A process that holds only CAP_BPF, running as a non-root user inside a
> container with no device nodes and no X11 or Wayland socket, can load a
> BPF_PROG_TYPE_SYSCALL program that calls hid_bpf_allocate_context() and
> hid_bpf_input_report(), run it through BPF_PROG_TEST_RUN, and inject
> keyboard reports into an already-authorized HID device. The reports
> travel the normal HID input path and reach the host's unlocked session
> (X11 desktop or text console) as if typed on the device, so the attacker
> executes commands as the logged-in user; on a server with a management
> controller, that session is the operator's console. Container platforms
> grant CAP_BPF to networking and observability workloads, so the
> capability holder is realistic rather than contrived.
Yes, this is expected, somehow. HID-BPF is required to fix devices. But
it relies on mechanisms primarily used by networking tools, and when you
allow networking tools to monitor the container, they effectively can
alter HID devices as well. I'm not sure we want another CAP_*.
>
> Detailed description:
>
> - Problem: the unattached syscall path can inject input with CAP_BPF
> alone. Attaching a struct_ops program to a device requires
> CAP_BPF+CAP_PERFMON, but a syscall program calling
> hid_bpf_input_report() needs only CAP_BPF and leaves no per-device
> record.
>
> - Reachability: a non-root container holding CAP_BPF, one
> already-authorized HID device, and an unlocked session. No malicious
> device, firmware, USB traffic, verifier flaw or memory-safety bug is
> involved.
>
> - Effect: arbitrary commands typed as the host user in the focused
> session, including a server's BMC virtual console. With CAP_PERFMON,
> the struct_ops path can in addition rewrite the report descriptor so
> an authorized mouse presents a keyboard collection.
>
> - Method and testing: a reproducer built against the struct_ops HID-BPF
> API, run in QEMU on Ubuntu 26.04 / kernel 7.0.0-28-generic
> (CONFIG_HID_BPF=y, BTF enabled) and on an Arch 7.1.5 host.
> Capability-restricted non-root runs with setpriv confirm the three
> cases above; 1000 of 1000 injections were accepted; commands landed in
The contrary would have been problematic: this just says that the code
is working deterministically, which is expected :)
> both an X session and a text console. Older, pre-struct_ops kernels
> are untested.
>
> - Possible fix: a capability check on the syscall path that reaches
> hid_bpf_input_report()/hid_bpf_try_input_report(), or a policy gate at
> program load. We implemented the latter as an LSM program on
> security_bpf_prog_load that denies a load calling any of the seven
> HID-BPF kfuncs; it stops the injector with -EPERM and costs about
> 24 us on a worst-case 4096-instruction load, with no input-path cost.
FWIW, Toke presented a policy for BPF at Plumbers last week[0]. Such
RBACd policy can allow a container to be restricted to use HID-BPF.
But the LSM might work just as well. I just don't want the module to
prevent HID-BPF from running on legitimate use case.
>
> My reading is that this is not a kernel vulnerability: the program is
> verifier-clean, no check is bypassed and nothing is memory-unsafe -- the
> malice is in the report data. The behavior also matches
> Documentation/hid/hid-bpf.rst, which documents hid_bpf_input_report()
> from syscall programs and already calls the tracing use case "god-mode".
> What I cannot settle myself is whether the capability split is what you
> intended.
There was nothing specifically intended for the split
CAP_BPF/CAP_PERFMON. But I don't really see why you are focusing on this
split when the report from above also mentions that CAP_PERFMON is also
used in conjunction with CAP_BPF to ease the injections of keys (without
needing to know in advance the report format).
I think the biggest issue IMO is that BPF was primarily introduced with
the network use case in mind, and CAP_BPF is probably too coarse.
That's where projects like RBACd and the LSM program you mentioned come
in handy.
>
> The one point I would like an answer on is the asymmetry itself: if the
> CAP_PERFMON requirement is about the attach/IRQ context rather than
> about input, then this is expected and I have no further concern.
struct_ops is classed as a perfmon program type because it has raw
kernel-memory access, independent of HID-BPF.
> If you
> would rather close it, I can post the LSM gate, though it is not the only
> possible fix.
I would be curious to see the LSM gate :)
>
> What I am asking for:
FWIW, the convention on the list is to just discuss inline, so it feels
weird to ask summary questions at the end.
>
> 1. Confirm or correct the reading above.
see above
> 2. If it is a bug: say so, and I will follow the security process
> instead.
I wouldn't call it a bug. But yes, hid_bpf_input_report is intentionally
callable from a CAP_BPF-only syscall program; that was a deliberate
choice so fixup tooling doesn't need tracing privileges, and gating it
further is a policy question better solved with RBACd/LSM than a new
CAP_*.
However, Alexei and the other folks from the bpf community might
disagree with me.
> 3. If it is intended: a short statement on this thread would help, and
> with your permission I would cite it as the maintainers' position. I
> am not asking for a CVE or for you to endorse the paper.
What kind of short statement are you asking for? To me, we all know that
there are way too many capabilities with BPF, and that's why the LSM
hook you used, and projects like RBACd [0] are useful.
>
> This comes from a paper we are preparing. It is not submitted yet and
> nothing will be published for some time, so there is no deadline here.
> The reproducer, logs and code are available on request, and I am happy to
> discuss everything on the list.
>
> Thanks,
> Shi Lecun <shilc2025@mail.sustech.edu.cn>
Cheers,
Benjamin
[0] https://lpc.events/event/20/contributions/2441/
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-13 16:00 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-12 8:47 HID-BPF: CAP_BPF-only process can inject input into host session Shi Lecun
2026-10-13 16:00 ` Benjamin Tissoires
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox