On Thu, May 19, 2022 at 4:56 AM Benjamin Tissoires benjamin.tissoires@redhat.com wrote:
As Greg mentioned in his reply, report descriptors fixups don't do much besides changing a memory buffer at probe time. So we can either have udev load the program, pin it and forget about it, or we can also have the kernel do that for us.
So I envision the distribution to be hybrid:
- for plain fixups where no userspace is required, we should
distribute those programs in the kernel itself, in-tree. This series already implements pre-loading of BPF programs for the core part of HID-BPF, but I plan on working on some automation of pre-loading of these programs from the kernel itself when we need to do so.
Ideally, the process would be:
- user reports a bug
- developer produces an eBPF program (and maybe compile it if the user
doesn't have LLVM)
- user tests/validates the fix without having to recompile anything
- developer drops the program in-tree
- some automated magic happens (still unclear exactly how to define
which HID device needs which eBPF program ATM)
- when the kernel sees this exact same device (BUS/VID/PID/INTERFACE)
it loads the fixup
- the other part of the hybrid solution is for when userspace is
heavily involved (because it exports a new dbus interface for that particular feature on this device). We can not really automatically preload the BPF program because we might not have the user in front of it. So in that case, the program would be hosted alongside the application, out-of-the-tree, but given that to be able to call kernel functions you need to be GPL, some public distribution of the sources is required.
Agree with everything you've said earlier. Just one additional comment: By default the source code is embedded in bpf objects. Here is an example. $ bpftool prog dump jited id 3927008|head -50 void cwnd_event(long long unsigned int * ctx): bpf_prog_9b9adc0a36a25303_cwnd_event: ; void BPF_STRUCT_OPS(cwnd_event, struct sock* sk, enum tcp_ca_event ev) { 0: nopl 0x0(%rax,%rax,1) 5: xchg %ax,%ax ... ; switch (ev) { 25: mov %r14d,%edi 28: add $0xfffffffc,%edi ... ; ca->loss_cwnd = tp->snd_cwnd; 4a: mov %edi,0x18(%r13) 4e: mov $0x2,%edi ; tp->snd_ssthresh = max(tp->snd_cwnd >> 1U, 2U); 53: test %rbx,%rbx 56: jne 0x000000000000005c
It's not the full source, of course, but good enough in practice for a person to figure out what program is doing.