@@ -15,6 +15,7 @@ struct hid_device;
enum bpf_hid_attach_type {
BPF_HID_ATTACH_INVALID = -1,
BPF_HID_ATTACH_DEVICE_EVENT = 0,
+ BPF_HID_ATTACH_RDESC_FIXUP,
MAX_BPF_HID_ATTACH_TYPE
};
@@ -32,6 +33,8 @@ to_bpf_hid_attach_type(enum bpf_attach_type attach_type)
switch (attach_type) {
case BPF_HID_DEVICE_EVENT:
return BPF_HID_ATTACH_DEVICE_EVENT;
+ case BPF_HID_RDESC_FIXUP:
+ return BPF_HID_ATTACH_RDESC_FIXUP;
default:
return BPF_HID_ATTACH_INVALID;
}
@@ -88,6 +91,7 @@ static inline bool bpf_hid_link_empty(struct bpf_hid *bpf,
struct bpf_hid_hooks {
struct hid_device *(*hdev_from_fd)(int fd);
int (*link_attach)(struct hid_device *hdev, enum bpf_hid_attach_type type);
+ void (*link_attached)(struct hid_device *hdev, enum bpf_hid_attach_type type);
void (*array_detached)(struct hid_device *hdev, enum bpf_hid_attach_type type);
};
@@ -999,6 +999,7 @@ enum bpf_attach_type {
BPF_SK_REUSEPORT_SELECT_OR_MIGRATE,
BPF_PERF_EVENT,
BPF_HID_DEVICE_EVENT,
+ BPF_HID_RDESC_FIXUP,
__MAX_BPF_ATTACH_TYPE
};
@@ -24,6 +24,7 @@ struct hid_device;
enum hid_bpf_event {
HID_BPF_UNDEF = 0,
HID_BPF_DEVICE_EVENT, /* when attach type is BPF_HID_DEVICE_EVENT */
+ HID_BPF_RDESC_FIXUP, /* ................... BPF_HID_RDESC_FIXUP */
};
struct hid_bpf_ctx {
@@ -315,6 +315,8 @@ static int bpf_hid_max_progs(enum bpf_hid_attach_type type)
switch (type) {
case BPF_HID_ATTACH_DEVICE_EVENT:
return 64;
+ case BPF_HID_ATTACH_RDESC_FIXUP:
+ return 1;
default:
return 0;
}
@@ -355,6 +357,9 @@ static int bpf_hid_link_attach(struct hid_device *hdev, struct bpf_link *link,
lockdep_is_held(&bpf_hid_mutex));
bpf_prog_array_free(run_array);
+ if (hid_hooks.link_attached)
+ hid_hooks.link_attached(hdev, type);
+
out_unlock:
mutex_unlock(&bpf_hid_mutex);
return err;
@@ -3203,6 +3203,7 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
case BPF_XDP:
return BPF_PROG_TYPE_XDP;
case BPF_HID_DEVICE_EVENT:
+ case BPF_HID_RDESC_FIXUP:
return BPF_PROG_TYPE_HID;
default:
return BPF_PROG_TYPE_UNSPEC;
@@ -3348,6 +3349,7 @@ static int bpf_prog_query(const union bpf_attr *attr,
case BPF_SK_SKB_VERDICT:
return sock_map_bpf_prog_query(attr, uattr);
case BPF_HID_DEVICE_EVENT:
+ case BPF_HID_RDESC_FIXUP:
return bpf_hid_prog_query(attr, uattr);
default:
return -EINVAL;
@@ -999,6 +999,7 @@ enum bpf_attach_type {
BPF_SK_REUSEPORT_SELECT_OR_MIGRATE,
BPF_PERF_EVENT,
BPF_HID_DEVICE_EVENT,
+ BPF_HID_RDESC_FIXUP,
__MAX_BPF_ATTACH_TYPE
};
The report descriptor is the dictionary of the HID protocol specific to the given device. Changing it is a common habit in the HID world, and making that feature accessible from eBPF allows to fix devices without having to install a new kernel. However, the report descriptor is supposed to be static on a device. To be able to change it, we need to reconnect the device at the HID level. So whenever the report descriptor program type is attached or detached, we call on a hook on HID to notify it that there is something to be done. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> --- changes in v2: - split the series by bpf/libbpf/hid/selftests and samples - unsigned long -> __u16 in uapi/linux/bpf_hid.h --- include/linux/bpf-hid.h | 4 ++++ include/uapi/linux/bpf.h | 1 + include/uapi/linux/bpf_hid.h | 1 + kernel/bpf/hid.c | 5 +++++ kernel/bpf/syscall.c | 2 ++ tools/include/uapi/linux/bpf.h | 1 + 6 files changed, 14 insertions(+)