Skip to content

Commit f1a5fb6

Browse files
author
Benjamin Tissoires
committed
HID: bpf: rework hid_bpf_ops_btf_struct_access
The idea is to provide a list of stucts and their editable fields. Currently no functional changes are introduced here, we will add some more writeable fields in the next patch. Acked-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Benjamin Tissoires <[email protected]>
1 parent bd07475 commit f1a5fb6

File tree

1 file changed

+69
-22
lines changed

1 file changed

+69
-22
lines changed

drivers/hid/bpf/hid_bpf_struct_ops.c

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/hid_bpf.h>
1717
#include <linux/init.h>
1818
#include <linux/module.h>
19+
#include <linux/stddef.h>
1920
#include <linux/workqueue.h>
2021
#include "hid_bpf_dispatch.h"
2122

@@ -52,40 +53,86 @@ static int hid_bpf_ops_check_member(const struct btf_type *t,
5253
return 0;
5354
}
5455

56+
struct hid_bpf_offset_write_range {
57+
const char *struct_name;
58+
u32 struct_length;
59+
u32 start;
60+
u32 end;
61+
};
62+
5563
static int hid_bpf_ops_btf_struct_access(struct bpf_verifier_log *log,
5664
const struct bpf_reg_state *reg,
5765
int off, int size)
5866
{
59-
const struct btf_type *state;
60-
const struct btf_type *t;
61-
s32 type_id;
67+
#define WRITE_RANGE(_name, _field, _is_string) \
68+
{ \
69+
.struct_name = #_name, \
70+
.struct_length = sizeof(struct _name), \
71+
.start = offsetof(struct _name, _field), \
72+
.end = offsetofend(struct _name, _field) - !!(_is_string), \
73+
}
6274

63-
type_id = btf_find_by_name_kind(reg->btf, "hid_bpf_ctx",
64-
BTF_KIND_STRUCT);
65-
if (type_id < 0)
66-
return -EINVAL;
75+
const struct hid_bpf_offset_write_range write_ranges[] = {
76+
WRITE_RANGE(hid_bpf_ctx, retval, false),
77+
};
78+
#undef WRITE_RANGE
79+
const struct btf_type *state = NULL;
80+
const struct btf_type *t;
81+
const char *cur = NULL;
82+
int i;
6783

6884
t = btf_type_by_id(reg->btf, reg->btf_id);
69-
state = btf_type_by_id(reg->btf, type_id);
70-
if (t != state) {
71-
bpf_log(log, "only access to hid_bpf_ctx is supported\n");
72-
return -EACCES;
73-
}
7485

75-
/* out-of-bound access in hid_bpf_ctx */
76-
if (off + size > sizeof(struct hid_bpf_ctx)) {
77-
bpf_log(log, "write access at off %d with size %d\n", off, size);
78-
return -EACCES;
86+
for (i = 0; i < ARRAY_SIZE(write_ranges); i++) {
87+
const struct hid_bpf_offset_write_range *write_range = &write_ranges[i];
88+
s32 type_id;
89+
90+
/* we already found a writeable struct, but there is a
91+
* new one, let's break the loop.
92+
*/
93+
if (t == state && write_range->struct_name != cur)
94+
break;
95+
96+
/* new struct to look for */
97+
if (write_range->struct_name != cur) {
98+
type_id = btf_find_by_name_kind(reg->btf, write_range->struct_name,
99+
BTF_KIND_STRUCT);
100+
if (type_id < 0)
101+
return -EINVAL;
102+
103+
state = btf_type_by_id(reg->btf, type_id);
104+
}
105+
106+
/* this is not the struct we are looking for */
107+
if (t != state) {
108+
cur = write_range->struct_name;
109+
continue;
110+
}
111+
112+
/* first time we see this struct, check for out of bounds */
113+
if (cur != write_range->struct_name &&
114+
off + size > write_range->struct_length) {
115+
bpf_log(log, "write access for struct %s at off %d with size %d\n",
116+
write_range->struct_name, off, size);
117+
return -EACCES;
118+
}
119+
120+
/* now check if we are in our boundaries */
121+
if (off >= write_range->start && off + size <= write_range->end)
122+
return NOT_INIT;
123+
124+
cur = write_range->struct_name;
79125
}
80126

81-
if (off < offsetof(struct hid_bpf_ctx, retval)) {
127+
128+
if (t != state)
129+
bpf_log(log, "write access to this struct is not supported\n");
130+
else
82131
bpf_log(log,
83-
"write access at off %d with size %d on read-only part of hid_bpf_ctx\n",
84-
off, size);
85-
return -EACCES;
86-
}
132+
"write access at off %d with size %d on read-only part of %s\n",
133+
off, size, cur);
87134

88-
return NOT_INIT;
135+
return -EACCES;
89136
}
90137

91138
static const struct bpf_verifier_ops hid_bpf_verifier_ops = {

0 commit comments

Comments
 (0)