diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-22 11:24:42 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-22 11:24:42 -0800 |
commit | 6c71297eaf713ece684a367ce9aff06069d715b9 (patch) | |
tree | da6f4768868ec6c9ba90a89c88fc78560577348f /include | |
parent | d5176cdbf64ce7d4eebf339205f17c23118e9f72 (diff) | |
parent | 904e28c6de083fa4834cdbd0026470ddc30676fc (diff) | |
download | lwn-6c71297eaf713ece684a367ce9aff06069d715b9.tar.gz lwn-6c71297eaf713ece684a367ce9aff06069d715b9.zip |
Merge tag 'for-linus-2023022201' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Benjamin Tissoires:
- HID-BPF infrastructure: this allows to start using HID-BPF. Note that
the mechanism to ship HID-BPF program through the kernel tree is
still not implemented yet (but is planned).
This should be a no-op for 99% of users. Also we are gaining
kselftests for the HID tree (Benjamin Tissoires)
- Some UAF fixes in workers when using uhid (Pietro Borrello & Benjamin
Tissoires)
- Constify hid_ll_driver (Thomas Weißschuh)
- Allow more custom IIO sensors through HID (Philipp Jungkamp)
- Logitech HID++ fixes for scroll wheel, protocol and debug (Bastien
Nocera)
- Some new device support: Steam Deck (Vicki Pfau), UClogic (José
Expósito), Logitech G923 Xbox Edition steering wheel (Walt Holman),
EVision keyboards (Philippe Valembois)
- other assorted code cleanups and fixes
* tag 'for-linus-2023022201' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (99 commits)
HID: mcp-2221: prevent UAF in delayed work
hid: bigben_probe(): validate report count
HID: asus: use spinlock to safely schedule workers
HID: asus: use spinlock to protect concurrent accesses
HID: bigben: use spinlock to safely schedule workers
HID: bigben_worker() remove unneeded check on report_field
HID: bigben: use spinlock to protect concurrent accesses
HID: logitech-hidpp: Add myself to authors
HID: logitech-hidpp: Retry commands when device is busy
HID: logitech-hidpp: Add more debug statements
HID: Add support for Logitech G923 Xbox Edition steering wheel
HID: logitech-hidpp: Add Signature M650
HID: logitech-hidpp: Remove HIDPP_QUIRK_NO_HIDINPUT quirk
HID: logitech-hidpp: Don't restart communication if not necessary
HID: logitech-hidpp: Add constants for HID++ 2.0 error codes
Revert "HID: logitech-hidpp: add a module parameter to keep firmware gestures"
HID: logitech-hidpp: Hard-code HID++ 1.0 fast scroll support
HID: i2c-hid: goodix: Add mainboard-vddio-supply
dt-bindings: HID: i2c-hid: goodix: Add mainboard-vddio-supply
HID: i2c-hid: goodix: Stop tying the reset line to the regulator
...
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/hid-sensor-ids.h | 1 | ||||
-rw-r--r-- | include/linux/hid.h | 34 | ||||
-rw-r--r-- | include/linux/hid_bpf.h | 170 |
3 files changed, 182 insertions, 23 deletions
diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h index ac631159403a..13b1e65fbdcc 100644 --- a/include/linux/hid-sensor-ids.h +++ b/include/linux/hid-sensor-ids.h @@ -132,6 +132,7 @@ #define HID_USAGE_SENSOR_PROP_FRIENDLY_NAME 0x200301 #define HID_USAGE_SENSOR_PROP_SERIAL_NUM 0x200307 #define HID_USAGE_SENSOR_PROP_MANUFACTURER 0x200305 +#define HID_USAGE_SENSOR_PROP_MODEL 0x200306 #define HID_USAGE_SENSOR_PROP_REPORT_INTERVAL 0x20030E #define HID_USAGE_SENSOR_PROP_SENSITIVITY_ABS 0x20030F #define HID_USAGE_SENSOR_PROP_SENSITIVITY_RANGE_PCT 0x200310 diff --git a/include/linux/hid.h b/include/linux/hid.h index 8677ae38599e..eaf8ab177303 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -26,6 +26,7 @@ #include <linux/mutex.h> #include <linux/power_supply.h> #include <uapi/linux/hid.h> +#include <linux/hid_bpf.h> /* * We parse each description item into this structure. Short items data @@ -312,6 +313,7 @@ struct hid_item { #define HID_DG_LATENCYMODE 0x000d0060 #define HID_BAT_ABSOLUTESTATEOFCHARGE 0x00850065 +#define HID_BAT_CHARGING 0x00850044 #define HID_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076 @@ -595,7 +597,7 @@ struct hid_device { /* device report descriptor */ struct device dev; /* device */ struct hid_driver *driver; - struct hid_ll_driver *ll_driver; + const struct hid_ll_driver *ll_driver; struct mutex ll_open_lock; unsigned int ll_open_count; @@ -611,6 +613,7 @@ struct hid_device { /* device report descriptor */ __s32 battery_max; __s32 battery_report_type; __s32 battery_report_id; + __s32 battery_charge_status; enum hid_battery_status battery_status; bool battery_avoid_query; ktime_t battery_ratelimit_time; @@ -619,6 +622,7 @@ struct hid_device { /* device report descriptor */ unsigned long status; /* see STAT flags above */ unsigned claimed; /* Claimed by hidinput, hiddev? */ unsigned quirks; /* Various quirks the device can pull on us */ + unsigned initial_quirks; /* Initial set of quirks supplied when creating device */ bool io_started; /* If IO has started */ struct list_head inputs; /* The list of inputs */ @@ -651,6 +655,10 @@ struct hid_device { /* device report descriptor */ wait_queue_head_t debug_wait; unsigned int id; /* system unique id */ + +#ifdef CONFIG_BPF + struct hid_bpf bpf; /* hid-bpf data */ +#endif /* CONFIG_BPF */ }; #define to_hid_device(pdev) \ @@ -853,21 +861,7 @@ struct hid_ll_driver { bool (*may_wakeup)(struct hid_device *hdev); }; -extern struct hid_ll_driver i2c_hid_ll_driver; -extern struct hid_ll_driver hidp_hid_driver; -extern struct hid_ll_driver uhid_hid_driver; -extern struct hid_ll_driver usb_hid_driver; - -static inline bool hid_is_using_ll_driver(struct hid_device *hdev, - struct hid_ll_driver *driver) -{ - return hdev->ll_driver == driver; -} - -static inline bool hid_is_usb(struct hid_device *hdev) -{ - return hid_is_using_ll_driver(hdev, &usb_hid_driver); -} +extern bool hid_is_usb(const struct hid_device *hdev); #define PM_HINT_FULLON 1<<5 #define PM_HINT_NORMAL 1<<1 @@ -882,8 +876,6 @@ static inline bool hid_is_usb(struct hid_device *hdev) /* HID core API */ -extern int hid_debug; - extern bool hid_ignore(struct hid_device *); extern int hid_add_device(struct hid_device *); extern void hid_destroy_device(struct hid_device *); @@ -1191,11 +1183,7 @@ int hid_pidff_init(struct hid_device *hid); #define hid_pidff_init NULL #endif -#define dbg_hid(fmt, ...) \ -do { \ - if (hid_debug) \ - printk(KERN_DEBUG "%s: " fmt, __FILE__, ##__VA_ARGS__); \ -} while (0) +#define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__) #define hid_err(hid, fmt, ...) \ dev_err(&(hid)->dev, fmt, ##__VA_ARGS__) diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h new file mode 100644 index 000000000000..e9afb61e6ee0 --- /dev/null +++ b/include/linux/hid_bpf.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __HID_BPF_H +#define __HID_BPF_H + +#include <linux/bpf.h> +#include <linux/spinlock.h> +#include <uapi/linux/hid.h> + +struct hid_device; + +/* + * The following is the user facing HID BPF API. + * + * Extra care should be taken when editing this part, as + * it might break existing out of the tree bpf programs. + */ + +/** + * struct hid_bpf_ctx - User accessible data for all HID programs + * + * ``data`` is not directly accessible from the context. We need to issue + * a call to ``hid_bpf_get_data()`` in order to get a pointer to that field. + * + * All of these fields are currently read-only. + * + * @index: program index in the jump table. No special meaning (a smaller index + * doesn't mean the program will be executed before another program with + * a bigger index). + * @hid: the ``struct hid_device`` representing the device itself + * @report_type: used for ``hid_bpf_device_event()`` + * @allocated_size: Allocated size of data. + * + * This is how much memory is available and can be requested + * by the HID program. + * Note that for ``HID_BPF_RDESC_FIXUP``, that memory is set to + * ``4096`` (4 KB) + * @size: Valid data in the data field. + * + * Programs can get the available valid size in data by fetching this field. + * Programs can also change this value by returning a positive number in the + * program. + * To discard the event, return a negative error code. + * + * ``size`` must always be less or equal than ``allocated_size`` (it is enforced + * once all BPF programs have been run). + * @retval: Return value of the previous program. + */ +struct hid_bpf_ctx { + __u32 index; + const struct hid_device *hid; + __u32 allocated_size; + enum hid_report_type report_type; + union { + __s32 retval; + __s32 size; + }; +}; + +/** + * enum hid_bpf_attach_flags - flags used when attaching a HIF-BPF program + * + * @HID_BPF_FLAG_NONE: no specific flag is used, the kernel choses where to + * insert the program + * @HID_BPF_FLAG_INSERT_HEAD: insert the given program before any other program + * currently attached to the device. This doesn't + * guarantee that this program will always be first + * @HID_BPF_FLAG_MAX: sentinel value, not to be used by the callers + */ +enum hid_bpf_attach_flags { + HID_BPF_FLAG_NONE = 0, + HID_BPF_FLAG_INSERT_HEAD = _BITUL(0), + HID_BPF_FLAG_MAX, +}; + +/* Following functions are tracepoints that BPF programs can attach to */ +int hid_bpf_device_event(struct hid_bpf_ctx *ctx); +int hid_bpf_rdesc_fixup(struct hid_bpf_ctx *ctx); + +/* Following functions are kfunc that we export to BPF programs */ +/* available everywhere in HID-BPF */ +__u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t __sz); + +/* only available in syscall */ +int hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags); +int hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz, + enum hid_report_type rtype, enum hid_class_request reqtype); +struct hid_bpf_ctx *hid_bpf_allocate_context(unsigned int hid_id); +void hid_bpf_release_context(struct hid_bpf_ctx *ctx); + +/* + * Below is HID internal + */ + +/* internal function to call eBPF programs, not to be used by anybody */ +int __hid_bpf_tail_call(struct hid_bpf_ctx *ctx); + +#define HID_BPF_MAX_PROGS_PER_DEV 64 +#define HID_BPF_FLAG_MASK (((HID_BPF_FLAG_MAX - 1) << 1) - 1) + +/* types of HID programs to attach to */ +enum hid_bpf_prog_type { + HID_BPF_PROG_TYPE_UNDEF = -1, + HID_BPF_PROG_TYPE_DEVICE_EVENT, /* an event is emitted from the device */ + HID_BPF_PROG_TYPE_RDESC_FIXUP, + HID_BPF_PROG_TYPE_MAX, +}; + +struct hid_report_enum; + +struct hid_bpf_ops { + struct hid_report *(*hid_get_report)(struct hid_report_enum *report_enum, const u8 *data); + int (*hid_hw_raw_request)(struct hid_device *hdev, + unsigned char reportnum, __u8 *buf, + size_t len, enum hid_report_type rtype, + enum hid_class_request reqtype); + struct module *owner; + struct bus_type *bus_type; +}; + +extern struct hid_bpf_ops *hid_bpf_ops; + +struct hid_bpf_prog_list { + u16 prog_idx[HID_BPF_MAX_PROGS_PER_DEV]; + u8 prog_cnt; +}; + +/* stored in each device */ +struct hid_bpf { + u8 *device_data; /* allocated when a bpf program of type + * SEC(f.../hid_bpf_device_event) has been attached + * to this HID device + */ + u32 allocated_data; + + struct hid_bpf_prog_list __rcu *progs[HID_BPF_PROG_TYPE_MAX]; /* attached BPF progs */ + bool destroyed; /* prevents the assignment of any progs */ + + spinlock_t progs_lock; /* protects RCU update of progs */ +}; + +/* specific HID-BPF link when a program is attached to a device */ +struct hid_bpf_link { + struct bpf_link link; + int hid_table_index; +}; + +#ifdef CONFIG_HID_BPF +u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data, + u32 *size, int interrupt); +int hid_bpf_connect_device(struct hid_device *hdev); +void hid_bpf_disconnect_device(struct hid_device *hdev); +void hid_bpf_destroy_device(struct hid_device *hid); +void hid_bpf_device_init(struct hid_device *hid); +u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size); +#else /* CONFIG_HID_BPF */ +static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, + u8 *data, u32 *size, int interrupt) { return data; } +static inline int hid_bpf_connect_device(struct hid_device *hdev) { return 0; } +static inline void hid_bpf_disconnect_device(struct hid_device *hdev) {} +static inline void hid_bpf_destroy_device(struct hid_device *hid) {} +static inline void hid_bpf_device_init(struct hid_device *hid) {} +static inline u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size) +{ + return kmemdup(rdesc, *size, GFP_KERNEL); +} + +#endif /* CONFIG_HID_BPF */ + +#endif /* __HID_BPF_H */ |