summaryrefslogtreecommitdiff
path: root/drivers/hid
diff options
context:
space:
mode:
authorBenjamin Tissoires <bentiss@kernel.org>2024-06-26 15:46:24 +0200
committerBenjamin Tissoires <bentiss@kernel.org>2024-06-27 10:58:22 +0200
commit6cd735f0e57a6c8510ad92f5b63837a8d0cff3a7 (patch)
treedcd4c66314d7a4fedf3438f199f34ddc24bcf3db /drivers/hid
parent67eccf151d76a9939ad8a50c6db5cb486b01df24 (diff)
HID: bpf: protect HID-BPF prog_list access by a SRCU
We want to add sleepable callbacks for hid_hw_raw_request() and hid_hw_output_report(), but we can not use a plain RCU for those. Prepare for a SRCU so we can extend HID-BPF. This changes a little bit how hid_bpf_device_init() behaves, as it may now fail, so there is a tiny hid-core.c change to accommodate for this. Link: https://patch.msgid.link/20240626-hid_hw_req_bpf-v2-3-cfd60fb6c79f@kernel.org Acked-by: Jiri Kosina <jkosina@suse.com> Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/bpf/hid_bpf_dispatch.c6
-rw-r--r--drivers/hid/bpf/hid_bpf_struct_ops.c2
-rw-r--r--drivers/hid/hid-core.c8
3 files changed, 14 insertions, 2 deletions
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index 2df31decaac3..c026248e3d73 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -506,13 +506,17 @@ void hid_bpf_destroy_device(struct hid_device *hdev)
hdev->bpf.destroyed = true;
__hid_bpf_ops_destroy_device(hdev);
+
+ synchronize_srcu(&hdev->bpf.srcu);
+ cleanup_srcu_struct(&hdev->bpf.srcu);
}
EXPORT_SYMBOL_GPL(hid_bpf_destroy_device);
-void hid_bpf_device_init(struct hid_device *hdev)
+int hid_bpf_device_init(struct hid_device *hdev)
{
INIT_LIST_HEAD(&hdev->bpf.prog_list);
mutex_init(&hdev->bpf.prog_list_lock);
+ return init_srcu_struct(&hdev->bpf.srcu);
}
EXPORT_SYMBOL_GPL(hid_bpf_device_init);
diff --git a/drivers/hid/bpf/hid_bpf_struct_ops.c b/drivers/hid/bpf/hid_bpf_struct_ops.c
index 8063db1c8d62..d34731a1b457 100644
--- a/drivers/hid/bpf/hid_bpf_struct_ops.c
+++ b/drivers/hid/bpf/hid_bpf_struct_ops.c
@@ -214,6 +214,7 @@ static int hid_bpf_reg(void *kdata)
list_add_rcu(&ops->list, &hdev->bpf.prog_list);
else
list_add_tail_rcu(&ops->list, &hdev->bpf.prog_list);
+ synchronize_srcu(&hdev->bpf.srcu);
out_unlock:
mutex_unlock(&hdev->bpf.prog_list_lock);
@@ -244,6 +245,7 @@ static void hid_bpf_unreg(void *kdata)
mutex_lock(&hdev->bpf.prog_list_lock);
list_del_rcu(&ops->list);
+ synchronize_srcu(&hdev->bpf.srcu);
reconnect = hdev->bpf.rdesc_ops == ops;
if (reconnect)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 0775a32f5272..ad08289752da 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2875,9 +2875,15 @@ struct hid_device *hid_allocate_device(void)
mutex_init(&hdev->ll_open_lock);
kref_init(&hdev->ref);
- hid_bpf_device_init(hdev);
+ ret = hid_bpf_device_init(hdev);
+ if (ret)
+ goto out_err;
return hdev;
+
+out_err:
+ hid_destroy_device(hdev);
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(hid_allocate_device);