Skip to content

Commit 67eccf1

Browse files
author
Benjamin Tissoires
committed
HID: add source argument to HID low level functions
This allows to know who actually sent what when we process the request to the device. This will be useful for a BPF firewall program to allow or not requests coming from a dedicated hidraw node client. Link: https://patch.msgid.link/[email protected] Acked-by: Jiri Kosina <[email protected]> Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent ebae0b2 commit 67eccf1

File tree

6 files changed

+82
-49
lines changed

6 files changed

+82
-49
lines changed

drivers/hid/bpf/hid_bpf_dispatch.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ EXPORT_SYMBOL(hid_ops);
2424

2525
u8 *
2626
dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type, u8 *data,
27-
u32 *size, int interrupt)
27+
u32 *size, int interrupt, u64 source)
2828
{
2929
struct hid_bpf_ctx_kern ctx_kern = {
3030
.ctx = {
@@ -50,7 +50,7 @@ dispatch_hid_bpf_device_event(struct hid_device *hdev, enum hid_report_type type
5050
rcu_read_lock();
5151
list_for_each_entry_rcu(e, &hdev->bpf.prog_list, list) {
5252
if (e->hid_device_event) {
53-
ret = e->hid_device_event(&ctx_kern.ctx, type);
53+
ret = e->hid_device_event(&ctx_kern.ctx, type, source);
5454
if (ret < 0) {
5555
rcu_read_unlock();
5656
return ERR_PTR(ret);
@@ -359,7 +359,8 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
359359
dma_data,
360360
size,
361361
rtype,
362-
reqtype);
362+
reqtype,
363+
(__u64)ctx);
363364

364365
if (ret > 0)
365366
memcpy(buf, dma_data, ret);
@@ -398,7 +399,8 @@ hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
398399

399400
ret = hid_ops->hid_hw_output_report(hdev,
400401
dma_data,
401-
size);
402+
size,
403+
(__u64)ctx);
402404

403405
kfree(dma_data);
404406
return ret;
@@ -429,7 +431,7 @@ hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, u8 *buf
429431

430432
hdev = (struct hid_device *)ctx->hid; /* discard const */
431433

432-
return hid_ops->hid_input_report(hdev, type, buf, size, 0);
434+
return hid_ops->hid_input_report(hdev, type, buf, size, 0, (__u64)ctx);
433435
}
434436
__bpf_kfunc_end_defs();
435437

drivers/hid/bpf/hid_bpf_struct_ops.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ static void hid_bpf_unreg(void *kdata)
257257
hid_put_device(hdev);
258258
}
259259

260-
static int __hid_bpf_device_event(struct hid_bpf_ctx *ctx, enum hid_report_type type)
260+
static int __hid_bpf_device_event(struct hid_bpf_ctx *ctx, enum hid_report_type type, __u64 source)
261261
{
262262
return 0;
263263
}

drivers/hid/hid-core.c

+53-32
Original file line numberDiff line numberDiff line change
@@ -2025,19 +2025,9 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
20252025
}
20262026
EXPORT_SYMBOL_GPL(hid_report_raw_event);
20272027

2028-
/**
2029-
* hid_input_report - report data from lower layer (usb, bt...)
2030-
*
2031-
* @hid: hid device
2032-
* @type: HID report type (HID_*_REPORT)
2033-
* @data: report contents
2034-
* @size: size of data parameter
2035-
* @interrupt: distinguish between interrupt and control transfers
2036-
*
2037-
* This is data entry for lower layers.
2038-
*/
2039-
int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
2040-
int interrupt)
2028+
2029+
static int __hid_input_report(struct hid_device *hid, enum hid_report_type type,
2030+
u8 *data, u32 size, int interrupt, u64 source)
20412031
{
20422032
struct hid_report_enum *report_enum;
20432033
struct hid_driver *hdrv;
@@ -2057,7 +2047,7 @@ int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data
20572047
report_enum = hid->report_enum + type;
20582048
hdrv = hid->driver;
20592049

2060-
data = dispatch_hid_bpf_device_event(hid, type, data, &size, interrupt);
2050+
data = dispatch_hid_bpf_device_event(hid, type, data, &size, interrupt, source);
20612051
if (IS_ERR(data)) {
20622052
ret = PTR_ERR(data);
20632053
goto unlock;
@@ -2092,6 +2082,23 @@ int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data
20922082
up(&hid->driver_input_lock);
20932083
return ret;
20942084
}
2085+
2086+
/**
2087+
* hid_input_report - report data from lower layer (usb, bt...)
2088+
*
2089+
* @hid: hid device
2090+
* @type: HID report type (HID_*_REPORT)
2091+
* @data: report contents
2092+
* @size: size of data parameter
2093+
* @interrupt: distinguish between interrupt and control transfers
2094+
*
2095+
* This is data entry for lower layers.
2096+
*/
2097+
int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
2098+
int interrupt)
2099+
{
2100+
return __hid_input_report(hid, type, data, size, interrupt, 0);
2101+
}
20952102
EXPORT_SYMBOL_GPL(hid_input_report);
20962103

20972104
bool hid_match_one_id(const struct hid_device *hdev,
@@ -2392,6 +2399,24 @@ void hid_hw_request(struct hid_device *hdev,
23922399
}
23932400
EXPORT_SYMBOL_GPL(hid_hw_request);
23942401

2402+
int __hid_hw_raw_request(struct hid_device *hdev,
2403+
unsigned char reportnum, __u8 *buf,
2404+
size_t len, enum hid_report_type rtype,
2405+
enum hid_class_request reqtype,
2406+
__u64 source)
2407+
{
2408+
unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE;
2409+
2410+
if (hdev->ll_driver->max_buffer_size)
2411+
max_buffer_size = hdev->ll_driver->max_buffer_size;
2412+
2413+
if (len < 1 || len > max_buffer_size || !buf)
2414+
return -EINVAL;
2415+
2416+
return hdev->ll_driver->raw_request(hdev, reportnum, buf, len,
2417+
rtype, reqtype);
2418+
}
2419+
23952420
/**
23962421
* hid_hw_raw_request - send report request to device
23972422
*
@@ -2409,6 +2434,12 @@ EXPORT_SYMBOL_GPL(hid_hw_request);
24092434
int hid_hw_raw_request(struct hid_device *hdev,
24102435
unsigned char reportnum, __u8 *buf,
24112436
size_t len, enum hid_report_type rtype, enum hid_class_request reqtype)
2437+
{
2438+
return __hid_hw_raw_request(hdev, reportnum, buf, len, rtype, reqtype, 0);
2439+
}
2440+
EXPORT_SYMBOL_GPL(hid_hw_raw_request);
2441+
2442+
int __hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len, __u64 source)
24122443
{
24132444
unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE;
24142445

@@ -2418,10 +2449,11 @@ int hid_hw_raw_request(struct hid_device *hdev,
24182449
if (len < 1 || len > max_buffer_size || !buf)
24192450
return -EINVAL;
24202451

2421-
return hdev->ll_driver->raw_request(hdev, reportnum, buf, len,
2422-
rtype, reqtype);
2452+
if (hdev->ll_driver->output_report)
2453+
return hdev->ll_driver->output_report(hdev, buf, len);
2454+
2455+
return -ENOSYS;
24232456
}
2424-
EXPORT_SYMBOL_GPL(hid_hw_raw_request);
24252457

24262458
/**
24272459
* hid_hw_output_report - send output report to device
@@ -2434,18 +2466,7 @@ EXPORT_SYMBOL_GPL(hid_hw_raw_request);
24342466
*/
24352467
int hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len)
24362468
{
2437-
unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE;
2438-
2439-
if (hdev->ll_driver->max_buffer_size)
2440-
max_buffer_size = hdev->ll_driver->max_buffer_size;
2441-
2442-
if (len < 1 || len > max_buffer_size || !buf)
2443-
return -EINVAL;
2444-
2445-
if (hdev->ll_driver->output_report)
2446-
return hdev->ll_driver->output_report(hdev, buf, len);
2447-
2448-
return -ENOSYS;
2469+
return __hid_hw_output_report(hdev, buf, len, 0);
24492470
}
24502471
EXPORT_SYMBOL_GPL(hid_hw_output_report);
24512472

@@ -2972,9 +2993,9 @@ EXPORT_SYMBOL_GPL(hid_check_keys_pressed);
29722993
#ifdef CONFIG_HID_BPF
29732994
static struct hid_ops __hid_ops = {
29742995
.hid_get_report = hid_get_report,
2975-
.hid_hw_raw_request = hid_hw_raw_request,
2976-
.hid_hw_output_report = hid_hw_output_report,
2977-
.hid_input_report = hid_input_report,
2996+
.hid_hw_raw_request = __hid_hw_raw_request,
2997+
.hid_hw_output_report = __hid_hw_output_report,
2998+
.hid_input_report = __hid_input_report,
29782999
.owner = THIS_MODULE,
29793000
.bus_type = &hid_bus_type,
29803001
};

drivers/hid/hidraw.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
140140

141141
if ((report_type == HID_OUTPUT_REPORT) &&
142142
!(dev->quirks & HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP)) {
143-
ret = hid_hw_output_report(dev, buf, count);
143+
ret = __hid_hw_output_report(dev, buf, count, (__u64)file);
144144
/*
145145
* compatibility with old implementation of USB-HID and I2C-HID:
146146
* if the device does not support receiving output reports,
@@ -150,8 +150,8 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
150150
goto out_free;
151151
}
152152

153-
ret = hid_hw_raw_request(dev, buf[0], buf, count, report_type,
154-
HID_REQ_SET_REPORT);
153+
ret = __hid_hw_raw_request(dev, buf[0], buf, count, report_type,
154+
HID_REQ_SET_REPORT, (__u64)file);
155155

156156
out_free:
157157
kfree(buf);
@@ -227,8 +227,8 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t
227227
goto out_free;
228228
}
229229

230-
ret = hid_hw_raw_request(dev, report_number, buf, count, report_type,
231-
HID_REQ_GET_REPORT);
230+
ret = __hid_hw_raw_request(dev, report_number, buf, count, report_type,
231+
HID_REQ_GET_REPORT, (__u64)file);
232232

233233
if (ret < 0)
234234
goto out_free;

include/linux/hid.h

+6
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,12 @@ int __must_check hid_hw_open(struct hid_device *hdev);
11251125
void hid_hw_close(struct hid_device *hdev);
11261126
void hid_hw_request(struct hid_device *hdev,
11271127
struct hid_report *report, enum hid_class_request reqtype);
1128+
int __hid_hw_raw_request(struct hid_device *hdev,
1129+
unsigned char reportnum, __u8 *buf,
1130+
size_t len, enum hid_report_type rtype,
1131+
enum hid_class_request reqtype,
1132+
__u64 source);
1133+
int __hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len, __u64 source);
11281134
int hid_hw_raw_request(struct hid_device *hdev,
11291135
unsigned char reportnum, __u8 *buf,
11301136
size_t len, enum hid_report_type rtype,

include/linux/hid_bpf.h

+10-6
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,12 @@ struct hid_ops {
6666
int (*hid_hw_raw_request)(struct hid_device *hdev,
6767
unsigned char reportnum, __u8 *buf,
6868
size_t len, enum hid_report_type rtype,
69-
enum hid_class_request reqtype);
70-
int (*hid_hw_output_report)(struct hid_device *hdev, __u8 *buf, size_t len);
69+
enum hid_class_request reqtype,
70+
__u64 source);
71+
int (*hid_hw_output_report)(struct hid_device *hdev, __u8 *buf, size_t len,
72+
__u64 source);
7173
int (*hid_input_report)(struct hid_device *hid, enum hid_report_type type,
72-
u8 *data, u32 size, int interrupt);
74+
u8 *data, u32 size, int interrupt, u64 source);
7375
struct module *owner;
7476
const struct bus_type *bus_type;
7577
};
@@ -110,7 +112,8 @@ struct hid_bpf_ops {
110112
*
111113
* Context: Interrupt context.
112114
*/
113-
int (*hid_device_event)(struct hid_bpf_ctx *ctx, enum hid_report_type report_type);
115+
int (*hid_device_event)(struct hid_bpf_ctx *ctx, enum hid_report_type report_type,
116+
__u64 source);
114117

115118
/**
116119
* @hid_rdesc_fixup: called when the probe function parses the report descriptor
@@ -146,15 +149,16 @@ struct hid_bpf {
146149

147150
#ifdef CONFIG_HID_BPF
148151
u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data,
149-
u32 *size, int interrupt);
152+
u32 *size, int interrupt, u64 source);
150153
int hid_bpf_connect_device(struct hid_device *hdev);
151154
void hid_bpf_disconnect_device(struct hid_device *hdev);
152155
void hid_bpf_destroy_device(struct hid_device *hid);
153156
void hid_bpf_device_init(struct hid_device *hid);
154157
u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size);
155158
#else /* CONFIG_HID_BPF */
156159
static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type,
157-
u8 *data, u32 *size, int interrupt) { return data; }
160+
u8 *data, u32 *size, int interrupt,
161+
u64 source) { return data; }
158162
static inline int hid_bpf_connect_device(struct hid_device *hdev) { return 0; }
159163
static inline void hid_bpf_disconnect_device(struct hid_device *hdev) {}
160164
static inline void hid_bpf_destroy_device(struct hid_device *hid) {}

0 commit comments

Comments
 (0)