Skip to content

Commit

Permalink
Merge tag 'hid-for-linus-2024020101' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…linux/kernel/git/hid/hid

Pull HID fixes from Benjamin Tissoires:

 - cleanups in the error path in hid-steam (Dan Carpenter)

 - fixes for Wacom tablets selftests that sneaked in while the CI was
   taking a break during the year end holidays (Benjamin Tissoires)

 - null pointer check in nvidia-shield (Kunwu Chan)

 - memory leak fix in hidraw (Su Hui)

 - another null pointer fix in i2c-hid-of (Johan Hovold)

 - another memory leak fix in HID-BPF this time, as well as a double
   fdget() fix reported by Dan Carpenter (Benjamin Tissoires)

 - fix for Cirque touchpad when they go on suspend (Kai-Heng Feng)

 - new device ID in hid-logitech-hidpp: "Logitech G Pro X SuperLight 2"
   (Jiri Kosina)

* tag 'hid-for-linus-2024020101' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: bpf: use __bpf_kfunc instead of noinline
  HID: bpf: actually free hdev memory after attaching a HID-BPF program
  HID: bpf: remove double fdget()
  HID: i2c-hid-of: fix NULL-deref on failed power up
  HID: hidraw: fix a problem of memory leak in hidraw_release()
  HID: i2c-hid: Skip SET_POWER SLEEP for Cirque touchpad on system suspend
  HID: nvidia-shield: Add missing null pointer checks to LED initialization
  HID: logitech-hidpp: add support for Logitech G Pro X Superlight 2
  selftests/hid: wacom: fix confidence tests
  HID: hid-steam: Fix cleanup in probe()
  HID: hid-steam: remove pointless error message
  • Loading branch information
Linus Torvalds committed Feb 1, 2024
2 parents f6cdd89 + 764ad6b commit 5c24e4e
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 85 deletions.
101 changes: 74 additions & 27 deletions drivers/hid/bpf/hid_bpf_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *s
}
EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup);

/* Disables missing prototype warnings */
__bpf_kfunc_start_defs();

/**
* hid_bpf_get_data - Get the kernel memory pointer associated with the context @ctx
*
Expand All @@ -152,7 +155,7 @@ EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup);
*
* @returns %NULL on error, an %__u8 memory pointer on success
*/
noinline __u8 *
__bpf_kfunc __u8 *
hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr_buf_size)
{
struct hid_bpf_ctx_kern *ctx_kern;
Expand All @@ -167,6 +170,7 @@ hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, const size_t rdwr

return ctx_kern->data + offset;
}
__bpf_kfunc_end_defs();

/*
* The following set contains all functions we agree BPF programs
Expand Down Expand Up @@ -241,6 +245,42 @@ int hid_bpf_reconnect(struct hid_device *hdev)
return 0;
}

static int do_hid_bpf_attach_prog(struct hid_device *hdev, int prog_fd, struct bpf_prog *prog,
__u32 flags)
{
int fd, err, prog_type;

prog_type = hid_bpf_get_prog_attach_type(prog);
if (prog_type < 0)
return prog_type;

if (prog_type >= HID_BPF_PROG_TYPE_MAX)
return -EINVAL;

if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
err = hid_bpf_allocate_event_data(hdev);
if (err)
return err;
}

fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, prog, flags);
if (fd < 0)
return fd;

if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) {
err = hid_bpf_reconnect(hdev);
if (err) {
close_fd(fd);
return err;
}
}

return fd;
}

/* Disables missing prototype warnings */
__bpf_kfunc_start_defs();

/**
* hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device
*
Expand All @@ -253,22 +293,17 @@ int hid_bpf_reconnect(struct hid_device *hdev)
* is pinned to the BPF file system).
*/
/* called from syscall */
noinline int
__bpf_kfunc int
hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
{
struct hid_device *hdev;
struct bpf_prog *prog;
struct device *dev;
int fd, err, prog_type = hid_bpf_get_prog_attach_type(prog_fd);
int err, fd;

if (!hid_bpf_ops)
return -EINVAL;

if (prog_type < 0)
return prog_type;

if (prog_type >= HID_BPF_PROG_TYPE_MAX)
return -EINVAL;

if ((flags & ~HID_BPF_FLAG_MASK))
return -EINVAL;

Expand All @@ -278,25 +313,29 @@ hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)

hdev = to_hid_device(dev);

if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
err = hid_bpf_allocate_event_data(hdev);
if (err)
return err;
/*
* take a ref on the prog itself, it will be released
* on errors or when it'll be detached
*/
prog = bpf_prog_get(prog_fd);
if (IS_ERR(prog)) {
err = PTR_ERR(prog);
goto out_dev_put;
}

fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, flags);
if (fd < 0)
return fd;

if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) {
err = hid_bpf_reconnect(hdev);
if (err) {
close_fd(fd);
return err;
}
fd = do_hid_bpf_attach_prog(hdev, prog_fd, prog, flags);
if (fd < 0) {
err = fd;
goto out_prog_put;
}

return fd;

out_prog_put:
bpf_prog_put(prog);
out_dev_put:
put_device(dev);
return err;
}

/**
Expand All @@ -306,7 +345,7 @@ hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
*
* @returns A pointer to &struct hid_bpf_ctx on success, %NULL on error.
*/
noinline struct hid_bpf_ctx *
__bpf_kfunc struct hid_bpf_ctx *
hid_bpf_allocate_context(unsigned int hid_id)
{
struct hid_device *hdev;
Expand All @@ -323,8 +362,10 @@ hid_bpf_allocate_context(unsigned int hid_id)
hdev = to_hid_device(dev);

ctx_kern = kzalloc(sizeof(*ctx_kern), GFP_KERNEL);
if (!ctx_kern)
if (!ctx_kern) {
put_device(dev);
return NULL;
}

ctx_kern->ctx.hid = hdev;

Expand All @@ -337,14 +378,19 @@ hid_bpf_allocate_context(unsigned int hid_id)
* @ctx: the HID-BPF context to release
*
*/
noinline void
__bpf_kfunc void
hid_bpf_release_context(struct hid_bpf_ctx *ctx)
{
struct hid_bpf_ctx_kern *ctx_kern;
struct hid_device *hid;

ctx_kern = container_of(ctx, struct hid_bpf_ctx_kern, ctx);
hid = (struct hid_device *)ctx_kern->ctx.hid; /* ignore const */

kfree(ctx_kern);

/* get_device() is called by bus_find_device() */
put_device(&hid->dev);
}

/**
Expand All @@ -358,7 +404,7 @@ hid_bpf_release_context(struct hid_bpf_ctx *ctx)
*
* @returns %0 on success, a negative error code otherwise.
*/
noinline int
__bpf_kfunc 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)
{
Expand Down Expand Up @@ -426,6 +472,7 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
kfree(dma_data);
return ret;
}
__bpf_kfunc_end_defs();

/* our HID-BPF entrypoints */
BTF_SET8_START(hid_bpf_fmodret_ids)
Expand Down
4 changes: 2 additions & 2 deletions drivers/hid/bpf/hid_bpf_dispatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ struct hid_bpf_ctx_kern {

int hid_bpf_preload_skel(void);
void hid_bpf_free_links_and_skel(void);
int hid_bpf_get_prog_attach_type(int prog_fd);
int hid_bpf_get_prog_attach_type(struct bpf_prog *prog);
int __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, int prog_fd,
__u32 flags);
struct bpf_prog *prog, __u32 flags);
void __hid_bpf_destroy_device(struct hid_device *hdev);
int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type,
struct hid_bpf_ctx_kern *ctx_kern);
Expand Down
40 changes: 20 additions & 20 deletions drivers/hid/bpf/hid_bpf_jmp_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ static void __hid_bpf_do_release_prog(int map_fd, unsigned int idx)
static void hid_bpf_release_progs(struct work_struct *work)
{
int i, j, n, map_fd = -1;
bool hdev_destroyed;

if (!jmp_table.map)
return;
Expand All @@ -220,6 +221,12 @@ static void hid_bpf_release_progs(struct work_struct *work)
if (entry->hdev) {
hdev = entry->hdev;
type = entry->type;
/*
* hdev is still valid, even if we are called after hid_destroy_device():
* when hid_bpf_attach() gets called, it takes a ref on the dev through
* bus_find_device()
*/
hdev_destroyed = hdev->bpf.destroyed;

hid_bpf_populate_hdev(hdev, type);

Expand All @@ -232,12 +239,19 @@ static void hid_bpf_release_progs(struct work_struct *work)
if (test_bit(next->idx, jmp_table.enabled))
continue;

if (next->hdev == hdev && next->type == type)
if (next->hdev == hdev && next->type == type) {
/*
* clear the hdev reference and decrement the device ref
* that was taken during bus_find_device() while calling
* hid_bpf_attach()
*/
next->hdev = NULL;
put_device(&hdev->dev);
}
}

/* if type was rdesc fixup, reconnect device */
if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP)
/* if type was rdesc fixup and the device is not gone, reconnect device */
if (type == HID_BPF_PROG_TYPE_RDESC_FIXUP && !hdev_destroyed)
hid_bpf_reconnect(hdev);
}
}
Expand Down Expand Up @@ -333,15 +347,10 @@ static int hid_bpf_insert_prog(int prog_fd, struct bpf_prog *prog)
return err;
}

int hid_bpf_get_prog_attach_type(int prog_fd)
int hid_bpf_get_prog_attach_type(struct bpf_prog *prog)
{
struct bpf_prog *prog = NULL;
int i;
int prog_type = HID_BPF_PROG_TYPE_UNDEF;

prog = bpf_prog_get(prog_fd);
if (IS_ERR(prog))
return PTR_ERR(prog);
int i;

for (i = 0; i < HID_BPF_PROG_TYPE_MAX; i++) {
if (hid_bpf_btf_ids[i] == prog->aux->attach_btf_id) {
Expand All @@ -350,8 +359,6 @@ int hid_bpf_get_prog_attach_type(int prog_fd)
}
}

bpf_prog_put(prog);

return prog_type;
}

Expand Down Expand Up @@ -388,19 +395,13 @@ static const struct bpf_link_ops hid_bpf_link_lops = {
/* called from syscall */
noinline int
__hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type,
int prog_fd, __u32 flags)
int prog_fd, struct bpf_prog *prog, __u32 flags)
{
struct bpf_link_primer link_primer;
struct hid_bpf_link *link;
struct bpf_prog *prog = NULL;
struct hid_bpf_prog_entry *prog_entry;
int cnt, err = -EINVAL, prog_table_idx = -1;

/* take a ref on the prog itself */
prog = bpf_prog_get(prog_fd);
if (IS_ERR(prog))
return PTR_ERR(prog);

mutex_lock(&hid_bpf_attach_lock);

link = kzalloc(sizeof(*link), GFP_USER);
Expand Down Expand Up @@ -467,7 +468,6 @@ __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type,
err_unlock:
mutex_unlock(&hid_bpf_attach_lock);

bpf_prog_put(prog);
kfree(link);

return err;
Expand Down
3 changes: 3 additions & 0 deletions drivers/hid/hid-ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@

#define USB_VENDOR_ID_CIDC 0x1677

#define I2C_VENDOR_ID_CIRQUE 0x0488
#define I2C_PRODUCT_ID_CIRQUE_1063 0x1063

#define USB_VENDOR_ID_CJTOUCH 0x24b8
#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020 0x0020
#define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040 0x0040
Expand Down
2 changes: 2 additions & 0 deletions drivers/hid/hid-logitech-hidpp.c
Original file line number Diff line number Diff line change
Expand Up @@ -4610,6 +4610,8 @@ static const struct hid_device_id hidpp_devices[] = {
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC088) },
{ /* Logitech G Pro X Superlight Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC094) },
{ /* Logitech G Pro X Superlight 2 Gaming Mouse over USB */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC09b) },

{ /* G935 Gaming Headset */
HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0x0a87),
Expand Down
4 changes: 4 additions & 0 deletions drivers/hid/hid-nvidia-shield.c
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,8 @@ static inline int thunderstrike_led_create(struct thunderstrike *ts)

led->name = devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL,
"thunderstrike%d:blue:led", ts->id);
if (!led->name)
return -ENOMEM;
led->max_brightness = 1;
led->flags = LED_CORE_SUSPENDRESUME | LED_RETAIN_AT_SHUTDOWN;
led->brightness_get = &thunderstrike_led_get_brightness;
Expand Down Expand Up @@ -831,6 +833,8 @@ static inline int thunderstrike_psy_create(struct shield_device *shield_dev)
shield_dev->battery_dev.desc.name =
devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL,
"thunderstrike_%d", ts->id);
if (!shield_dev->battery_dev.desc.name)
return -ENOMEM;

shield_dev->battery_dev.psy = power_supply_register(
&hdev->dev, &shield_dev->battery_dev.desc, &psy_cfg);
Expand Down
Loading

0 comments on commit 5c24e4e

Please sign in to comment.