drivers/hid/bpf/hid_bpf_struct_ops.c

Source file repositories/reference/linux-study-clean/drivers/hid/bpf/hid_bpf_struct_ops.c

File Facts

System
Linux kernel
Corpus path
drivers/hid/bpf/hid_bpf_struct_ops.c
Extension
.c
Size
7821 bytes
Lines
327
Domain
Driver Families
Bucket
drivers/hid
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct hid_bpf_offset_write_range {
	const char *struct_name;
	u32 struct_length;
	u32 start;
	u32 end;
};

static int hid_bpf_ops_btf_struct_access(struct bpf_verifier_log *log,
					   const struct bpf_reg_state *reg,
					   int off, int size)
{
#define WRITE_RANGE(_name, _field, _is_string)					\
	{									\
		.struct_name = #_name,						\
		.struct_length = sizeof(struct _name),				\
		.start = offsetof(struct _name, _field),			\
		.end = offsetofend(struct _name, _field) - !!(_is_string),	\
	}

	const struct hid_bpf_offset_write_range write_ranges[] = {
		WRITE_RANGE(hid_bpf_ctx, retval, false),
		WRITE_RANGE(hid_device, name, true),
		WRITE_RANGE(hid_device, uniq, true),
		WRITE_RANGE(hid_device, phys, true),
	};
#undef WRITE_RANGE
	const struct btf_type *state = NULL;
	const struct btf_type *t;
	const char *cur = NULL;
	int i;

	t = btf_type_by_id(reg->btf, reg->btf_id);

	for (i = 0; i < ARRAY_SIZE(write_ranges); i++) {
		const struct hid_bpf_offset_write_range *write_range = &write_ranges[i];
		s32 type_id;

		/* we already found a writeable struct, but there is a
		 * new one, let's break the loop.
		 */
		if (t == state && write_range->struct_name != cur)
			break;

		/* new struct to look for */
		if (write_range->struct_name != cur) {
			type_id = btf_find_by_name_kind(reg->btf, write_range->struct_name,
							BTF_KIND_STRUCT);
			if (type_id < 0)
				return -EINVAL;

			state = btf_type_by_id(reg->btf, type_id);
		}

		/* this is not the struct we are looking for */
		if (t != state) {
			cur = write_range->struct_name;
			continue;
		}

		/* first time we see this struct, check for out of bounds */
		if (cur != write_range->struct_name &&
		    off + size > write_range->struct_length) {
			bpf_log(log, "write access for struct %s at off %d with size %d\n",
				write_range->struct_name, off, size);
			return -EACCES;
		}

		/* now check if we are in our boundaries */
		if (off >= write_range->start && off + size <= write_range->end)
			return NOT_INIT;

		cur = write_range->struct_name;
	}


	if (t != state)
		bpf_log(log, "write access to this struct is not supported\n");
	else
		bpf_log(log,
			"write access at off %d with size %d on read-only part of %s\n",
			off, size, cur);

	return -EACCES;
}

static const struct bpf_verifier_ops hid_bpf_verifier_ops = {
	.get_func_proto = bpf_base_func_proto,
	.is_valid_access = hid_bpf_ops_is_valid_access,
	.btf_struct_access = hid_bpf_ops_btf_struct_access,
};

Annotation

Implementation Notes