From: "Shi Lecun" <shilc2025@mail.sustech.edu.cn>
To: linux-input <linux-input@vger.kernel.org>
Cc: jikos <jikos@kernel.org>, bentiss <bentiss@kernel.org>,
bpf <bpf@vger.kernel.org>
Subject: HID-BPF: CAP_BPF-only process can inject input into host session
Date: Mon, 12 Oct 2026 16:47:00 +0800 [thread overview]
Message-ID: <tencent_3B9FD2455BEBDF351B2CD453@qq.com> (raw)
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>
reply other threads:[~2026-10-12 8:47 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=tencent_3B9FD2455BEBDF351B2CD453@qq.com \
--to=shilc2025@mail.sustech.edu.cn \
--cc=bentiss@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox