[PATCH v2] HID: core: use flex array allocation
DORMANTno replies
From: Rosen Penev <hidden>
Date: 2026-10-05 19:13:02
Also in:
linux-hardening, lkml
Subsystem:
hid core layer, the rest · Maintainers:
Jiri Kosina, Benjamin Tissoires, Linus Torvalds
Instead of embedding a pointer in the struct, use a flexible array member to avoid the + 1 trick to point to allocation after the struct. This also shrinks struct hid_field by one pointer. Annotate the array with __counted_by(maxusage) so that FORTIFY_SOURCE and UBSAN_BOUNDS can check accesses at runtime. maxusage already holds the number of allocated usages, but it was only set after the usage table was populated, so move the assignment into hid_register_field() right after allocation. Assisted-by: LLM Signed-off-by: Rosen Penev <redacted> --- v2: use __counted_by drivers/hid/hid-core.c | 8 +++----- include/linux/hid.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index ec7c2860c93e..76bf4da89d2c 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c@@ -130,15 +130,14 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned return NULL; } - field = kvzalloc((sizeof(struct hid_field) + - usages * sizeof(struct hid_usage) + - 3 * usages * sizeof(unsigned int)), GFP_KERNEL); + field = kvzalloc(struct_size(field, usage, usages) + + 3 * usages * sizeof(unsigned int), GFP_KERNEL); if (!field) return NULL; + field->maxusage = usages; field->index = report->maxfield++; report->field[field->index] = field; - field->usage = (struct hid_usage *)(field + 1); field->value = (s32 *)(field->usage + usages); field->new_value = (s32 *)(field->value + usages); field->usages_priorities = (s32 *)(field->new_value + usages);
@@ -357,7 +356,6 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign field->usage[i].resolution_multiplier = 1; } - field->maxusage = usages; field->flags = flags; field->report_offset = offset; field->report_type = report_type;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 8d17b741638c..16e8f19d42c5 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h@@ -524,7 +524,6 @@ struct hid_field { unsigned physical; /* physical usage for this field */ unsigned logical; /* logical usage for this field */ unsigned application; /* application usage for this field */ - struct hid_usage *usage; /* usage table for this function */ unsigned maxusage; /* maximum usage index */ unsigned flags; /* main-item flags (i.e. volatile,array,constant) */ unsigned report_offset; /* bit offset in the report */
@@ -549,6 +548,7 @@ struct hid_field { struct hid_input *hidinput; /* associated input structure */ __u16 dpad; /* dpad input code */ unsigned int slot_idx; /* slot index in a report */ + struct hid_usage usage[] __counted_by(maxusage); /* usage table for this function */ }; #define HID_MAX_FIELDS 256
--
2.56.0