diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2022-11-03 18:57:44 +0300 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2022-11-15 18:28:28 +0300 |
commit | f5c27da4e3c8a2e42fb4f41a0c685debcb9af294 (patch) | |
tree | dca477e34c80d61362ddd2ebbfbe2a4f9dc6bc22 /drivers/hid/hid-core.c | |
parent | 25621bcc89762fe1329ae9c9dab75bc70ef1aee0 (diff) | |
download | linux-f5c27da4e3c8a2e42fb4f41a0c685debcb9af294.tar.xz |
HID: initial BPF implementation
Declare an entry point that can use fmod_ret BPF programs, and
also an API to access and change the incoming data.
A simpler implementation would consist in just calling
hid_bpf_device_event() for any incoming event and let users deal
with the fact that they will be called for any event of any device.
The goal of HID-BPF is to partially replace drivers, so this situation
can be problematic because we might have programs which will step on
each other toes.
For that, we add a new API hid_bpf_attach_prog() that can be called
from a syscall and we manually deal with a jump table in hid-bpf.
Whenever we add a program to the jump table (in other words, when we
attach a program to a HID device), we keep the number of time we added
this program in the jump table so we can release it whenever there are
no other users.
HID devices have an RCU protected list of available programs in the
jump table, and those programs are called one after the other thanks
to bpf_tail_call().
To achieve the detection of users losing their fds on the programs we
attached, we add 2 tracing facilities on bpf_prog_release() (for when
a fd is closed) and bpf_free_inode() (for when a pinned program gets
unpinned).
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-core.c')
-rw-r--r-- | drivers/hid/hid-core.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9c1d31f63f85..1098c49b5d2e 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2040,6 +2040,10 @@ int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data report_enum = hid->report_enum + type; hdrv = hid->driver; + ret = dispatch_hid_bpf_device_event(hid, type, data, size, interrupt); + if (ret) + goto unlock; + if (!size) { dbg_hid("empty report\n"); ret = -1; @@ -2790,6 +2794,8 @@ struct hid_device *hid_allocate_device(void) sema_init(&hdev->driver_input_lock, 1); mutex_init(&hdev->ll_open_lock); + hid_bpf_device_init(hdev); + return hdev; } EXPORT_SYMBOL_GPL(hid_allocate_device); @@ -2816,6 +2822,7 @@ static void hid_remove_device(struct hid_device *hdev) */ void hid_destroy_device(struct hid_device *hdev) { + hid_bpf_destroy_device(hdev); hid_remove_device(hdev); put_device(&hdev->dev); } @@ -2902,6 +2909,13 @@ int hid_check_keys_pressed(struct hid_device *hid) } EXPORT_SYMBOL_GPL(hid_check_keys_pressed); +#ifdef CONFIG_HID_BPF +static struct hid_bpf_ops hid_ops = { + .owner = THIS_MODULE, + .bus_type = &hid_bus_type, +}; +#endif + static int __init hid_init(void) { int ret; @@ -2916,6 +2930,10 @@ static int __init hid_init(void) goto err; } +#ifdef CONFIG_HID_BPF + hid_bpf_ops = &hid_ops; +#endif + ret = hidraw_init(); if (ret) goto err_bus; @@ -2931,6 +2949,9 @@ err: static void __exit hid_exit(void) { +#ifdef CONFIG_HID_BPF + hid_bpf_ops = NULL; +#endif hid_debug_exit(); hidraw_exit(); bus_unregister(&hid_bus_type); |