Skip to content

Commit 7cdd210

Browse files
author
Benjamin Tissoires
committed
HID: bpf: remove double fdget()
When the kfunc hid_bpf_attach_prog() is called, we called twice fdget(): one for fetching the type of the bpf program, and one for actually attaching the program to the device. The problem is that between those two calls, we have no guarantees that the prog_fd is still the same file descriptor for the given program. Solve this by calling bpf_prog_get() earlier, and use this to fetch the program type. Reported-by: Dan Carpenter <[email protected]> Link: https://lore.kernel.org/bpf/CAO-hwJJ8vh8JD3-P43L-_CLNmPx0hWj44aom0O838vfP4=_1CA@mail.gmail.com/T/#t Cc: <[email protected]> Fixes: f5c27da ("HID: initial BPF implementation") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent 00aab7d commit 7cdd210

File tree

3 files changed

+49
-41
lines changed

3 files changed

+49
-41
lines changed

drivers/hid/bpf/hid_bpf_dispatch.c

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,39 @@ int hid_bpf_reconnect(struct hid_device *hdev)
241241
return 0;
242242
}
243243

244+
static int do_hid_bpf_attach_prog(struct hid_device *hdev, int prog_fd, struct bpf_prog *prog,
245+
__u32 flags)
246+
{
247+
int fd, err, prog_type;
248+
249+
prog_type = hid_bpf_get_prog_attach_type(prog);
250+
if (prog_type < 0)
251+
return prog_type;
252+
253+
if (prog_type >= HID_BPF_PROG_TYPE_MAX)
254+
return -EINVAL;
255+
256+
if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
257+
err = hid_bpf_allocate_event_data(hdev);
258+
if (err)
259+
return err;
260+
}
261+
262+
fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, prog, flags);
263+
if (fd < 0)
264+
return fd;
265+
266+
if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) {
267+
err = hid_bpf_reconnect(hdev);
268+
if (err) {
269+
close_fd(fd);
270+
return err;
271+
}
272+
}
273+
274+
return fd;
275+
}
276+
244277
/**
245278
* hid_bpf_attach_prog - Attach the given @prog_fd to the given HID device
246279
*
@@ -257,18 +290,13 @@ noinline int
257290
hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
258291
{
259292
struct hid_device *hdev;
293+
struct bpf_prog *prog;
260294
struct device *dev;
261-
int fd, err, prog_type = hid_bpf_get_prog_attach_type(prog_fd);
295+
int fd;
262296

263297
if (!hid_bpf_ops)
264298
return -EINVAL;
265299

266-
if (prog_type < 0)
267-
return prog_type;
268-
269-
if (prog_type >= HID_BPF_PROG_TYPE_MAX)
270-
return -EINVAL;
271-
272300
if ((flags & ~HID_BPF_FLAG_MASK))
273301
return -EINVAL;
274302

@@ -278,23 +306,17 @@ hid_bpf_attach_prog(unsigned int hid_id, int prog_fd, __u32 flags)
278306

279307
hdev = to_hid_device(dev);
280308

281-
if (prog_type == HID_BPF_PROG_TYPE_DEVICE_EVENT) {
282-
err = hid_bpf_allocate_event_data(hdev);
283-
if (err)
284-
return err;
285-
}
309+
/*
310+
* take a ref on the prog itself, it will be released
311+
* on errors or when it'll be detached
312+
*/
313+
prog = bpf_prog_get(prog_fd);
314+
if (IS_ERR(prog))
315+
return PTR_ERR(prog);
286316

287-
fd = __hid_bpf_attach_prog(hdev, prog_type, prog_fd, flags);
317+
fd = do_hid_bpf_attach_prog(hdev, prog_fd, prog, flags);
288318
if (fd < 0)
289-
return fd;
290-
291-
if (prog_type == HID_BPF_PROG_TYPE_RDESC_FIXUP) {
292-
err = hid_bpf_reconnect(hdev);
293-
if (err) {
294-
close_fd(fd);
295-
return err;
296-
}
297-
}
319+
bpf_prog_put(prog);
298320

299321
return fd;
300322
}

drivers/hid/bpf/hid_bpf_dispatch.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ struct hid_bpf_ctx_kern {
1212

1313
int hid_bpf_preload_skel(void);
1414
void hid_bpf_free_links_and_skel(void);
15-
int hid_bpf_get_prog_attach_type(int prog_fd);
15+
int hid_bpf_get_prog_attach_type(struct bpf_prog *prog);
1616
int __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type, int prog_fd,
17-
__u32 flags);
17+
struct bpf_prog *prog, __u32 flags);
1818
void __hid_bpf_destroy_device(struct hid_device *hdev);
1919
int hid_bpf_prog_run(struct hid_device *hdev, enum hid_bpf_prog_type type,
2020
struct hid_bpf_ctx_kern *ctx_kern);

drivers/hid/bpf/hid_bpf_jmp_table.c

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -333,15 +333,10 @@ static int hid_bpf_insert_prog(int prog_fd, struct bpf_prog *prog)
333333
return err;
334334
}
335335

336-
int hid_bpf_get_prog_attach_type(int prog_fd)
336+
int hid_bpf_get_prog_attach_type(struct bpf_prog *prog)
337337
{
338-
struct bpf_prog *prog = NULL;
339-
int i;
340338
int prog_type = HID_BPF_PROG_TYPE_UNDEF;
341-
342-
prog = bpf_prog_get(prog_fd);
343-
if (IS_ERR(prog))
344-
return PTR_ERR(prog);
339+
int i;
345340

346341
for (i = 0; i < HID_BPF_PROG_TYPE_MAX; i++) {
347342
if (hid_bpf_btf_ids[i] == prog->aux->attach_btf_id) {
@@ -350,8 +345,6 @@ int hid_bpf_get_prog_attach_type(int prog_fd)
350345
}
351346
}
352347

353-
bpf_prog_put(prog);
354-
355348
return prog_type;
356349
}
357350

@@ -388,19 +381,13 @@ static const struct bpf_link_ops hid_bpf_link_lops = {
388381
/* called from syscall */
389382
noinline int
390383
__hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type,
391-
int prog_fd, __u32 flags)
384+
int prog_fd, struct bpf_prog *prog, __u32 flags)
392385
{
393386
struct bpf_link_primer link_primer;
394387
struct hid_bpf_link *link;
395-
struct bpf_prog *prog = NULL;
396388
struct hid_bpf_prog_entry *prog_entry;
397389
int cnt, err = -EINVAL, prog_table_idx = -1;
398390

399-
/* take a ref on the prog itself */
400-
prog = bpf_prog_get(prog_fd);
401-
if (IS_ERR(prog))
402-
return PTR_ERR(prog);
403-
404391
mutex_lock(&hid_bpf_attach_lock);
405392

406393
link = kzalloc(sizeof(*link), GFP_USER);
@@ -467,7 +454,6 @@ __hid_bpf_attach_prog(struct hid_device *hdev, enum hid_bpf_prog_type prog_type,
467454
err_unlock:
468455
mutex_unlock(&hid_bpf_attach_lock);
469456

470-
bpf_prog_put(prog);
471457
kfree(link);
472458

473459
return err;

0 commit comments

Comments
 (0)