Commit 5c24e4e9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'hid-for-linus-2024020101' of git://git.kernel.org/pub/scm/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
parents f6cdd897 764ad6b0
Loading
Loading
Loading
Loading
+74 −27
Original line number Diff line number Diff line
@@ -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
 *
@@ -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;
@@ -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
@@ -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
 *
@@ -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;

@@ -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;
}

/**
@@ -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;
@@ -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;

@@ -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);
}

/**
@@ -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)
{
@@ -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)
+2 −2
Original line number Diff line number Diff line
@@ -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);
+20 −20
Original line number Diff line number Diff line
@@ -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;
@@ -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);

@@ -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);
		}
	}
@@ -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) {
@@ -350,8 +359,6 @@ int hid_bpf_get_prog_attach_type(int prog_fd)
		}
	}

	bpf_prog_put(prog);

	return prog_type;
}

@@ -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);
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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),
Loading