From: Nicolas Schier <nsc@kernel.org>
To: Hasan Basbunar <basbunarhasan@gmail.com>
Cc: Nathan Chancellor <nathan@kernel.org>,
Masahiro Yamada <masahiroy@kernel.org>,
Randy Dunlap <rdunlap@infradead.org>,
linux-kbuild@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] modpost: prevent stack buffer overflow in do_input_entry() and do_dmi_entry()
Date: Tue, 5 May 2026 17:17:10 +0200 [thread overview]
Message-ID: <afoJ9ha8NaJl1IRC@levanger> (raw)
In-Reply-To: <20260428062912.32918-1-basbunarhasan@gmail.com>
On Tue, Apr 28, 2026 at 08:29:12AM +0200, Hasan Basbunar wrote:
> Several functions in scripts/mod/file2alias.c build the module alias
> string by repeatedly appending into a fixed-size on-stack buffer:
>
> char alias[256] = {};
> ...
> sprintf(alias + strlen(alias), "%X,*", i);
>
> This pattern is unbounded and silently corrupts the stack when the
> formatted output exceeds the destination size. Two functions in this
> file are realistically reachable with input that overflows their
> buffer:
>
> 1. do_input_entry() appends across nine bitmap classes
> (evbit/keybit/relbit/absbit/mscbit/ledbit/sndbit/ffbit/swbit). The
> keybit case alone scans bits from INPUT_DEVICE_ID_KEY_MIN_INTERESTING
> (0x71) to INPUT_DEVICE_ID_KEY_MAX (0x2ff), 655 iterations; if a
> MODULE_DEVICE_TABLE(input, ...) populates keybit[] densely, the
> emission reaches ~3132 bytes — overflowing the 256-byte buffer by
> about 12x. include/linux/mod_devicetable.h declares storage for the
> full bit range ("keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1]"),
> so the worst case is reachable per the ABI.
>
> 2. do_dmi_entry() emits one ":<prefix>*<filtered_substr>*" segment per
> matched DMI field, up to 4 matches per dmi_system_id. Each substr
> is sized as char[79] in struct dmi_strmatch (mod_devicetable.h:584),
> and dmi_ascii_filter() copies it verbatim into the alias buffer
> without bounds. Worst case: 4 × (1 + 3 + 1 + 79 + 1) = 336 bytes
> into alias[256], an 80-byte overflow.
>
> No driver in the current tree triggers either case — every in-tree
> INPUT_DEVICE_ID_MATCH_KEYBIT user populates keybit[] very sparsely
> (1-3 bits), and no in-tree dmi_system_id has four maximally-long
> matches. The concern is defense-in-depth: both unbounded sprintf
> chains are silent stack-corruption primitives in a host build tool,
> and the buffer sizes have not been revisited since the corresponding
> code was first introduced.
>
> The other do_*_entry() handlers in this file (do_usb_entry,
> do_cpu_entry, do_typec_entry, ...) were audited and are bounded by
> their input field sizes (uint16 IDs, fixed-length keys); their alias
> buffers do not need this treatment.
>
> Reproduced under AddressSanitizer with a stand-alone harness mirroring
> do_input on a fully-populated keybit:
>
> ==18319==ERROR: AddressSanitizer: stack-buffer-overflow
> WRITE of size 2 at offset 288 in frame [32, 288) 'alias'
> #6 do_input poc.c:44
>
> Stack-canary build:
> Abort trap: 6 (strlen(alias)=3134, cap was 256-1)
>
> Add a small alias_append() helper around vsnprintf with a remaining-
> space check and call fatal() on overflow, matching the modpost style
> for unrecoverable build conditions. do_input() takes the buffer size
> as a new parameter; do_input_entry() and do_dmi_entry() pass
> sizeof(alias) at every call site. dmi_ascii_filter() takes the
> remaining buffer size as well and aborts on truncation. This bounds
> every write into the on-stack buffers and turns the latent overflow
> into a clean build error if it is ever reached.
>
> Fixes: 1d8f430c15b3 ("[PATCH] Input: add modalias support")
> Signed-off-by: Hasan Basbunar <basbunarhasan@gmail.com>
> ---
> v1: https://lore.kernel.org/lkml/20260427204255.22117-1-basbunarhasan@gmail.com/
>
> Changes since v1 (per Randy Dunlap's review):
> - Audited the other do_*_entry() handlers; do_dmi_entry() has the same
> unbounded-sprintf shape with a realistic 80-byte worst-case overflow,
> and is fixed in v2 alongside do_input_entry(). The remaining
> do_*_entry() handlers were verified bounded by their input field
> types and do not need this treatment.
> - Added a Fixes: tag pointing to the original do_input introduction
> (commit 1d8f430c15b3, 2005).
> - Reworded the alias_append() comment: replaced "cumulative
> bookkeeping" with "remaining-space check", which is what the helper
> actually does.
>
> Randy: I have not carried forward your Reviewed-by/Tested-by from v1
> because v2 expands scope to do_dmi_entry() (new code you have not seen
> yet); please re-affirm if v2 looks good to you.
>
> ---
> scripts/mod/file2alias.c | 91 ++++++++++++++++++++++++++++------------
> 1 file changed, 65 insertions(+), 26 deletions(-)
>
> diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
> index 4e99393a35f1..9ec5c4e1f3ed 100644
> --- a/scripts/mod/file2alias.c
> +++ b/scripts/mod/file2alias.c
> @@ -651,7 +651,38 @@ static void do_vio_entry(struct module *mod, void *symval)
> module_alias_printf(mod, true, "%s", alias);
> }
>
> -static void do_input(char *alias,
> +/*
> + * alias_append() — bounded printf-append into a fixed-size alias buffer.
> + *
> + * Replaces the historical pattern sprintf(alias + strlen(alias), ...)
> + * used across this file. That pattern silently corrupts the stack when
> + * the formatted output exceeds the destination size; the worst-case
> + * emission in do_input_entry() with a maximally-populated keybit[] is
> + * about 12x the on-stack 256-byte buffer, and do_dmi_entry() can also
> + * exceed its 256 bytes for four maximal-length DMI matches. Use
> + * snprintf with a remaining-space check and abort the build on
> + * overflow.
This is well-documented in the commit message (thanks for that!), and I
expect this to not become updated in case we run into the fatal() case
and update the maximum buffer sizes. Thus, I'd rather not add that
stanza into the code at all.
Nevertheless, thanks a lot! LGTM.
I am going to apply that to kbuild-fixes-unstable for some linux-next testing.
Kind regards,
Nicolas
next prev parent reply other threads:[~2026-05-05 15:17 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-27 20:42 [PATCH] modpost: prevent stack buffer overflow in do_input_entry() Hasan Basbunar
2026-04-28 1:09 ` Randy Dunlap
2026-04-28 6:29 ` [PATCH v2] modpost: prevent stack buffer overflow in do_input_entry() and do_dmi_entry() Hasan Basbunar
2026-04-28 6:58 ` Randy Dunlap
2026-05-05 15:17 ` Nicolas Schier [this message]
2026-05-05 16:11 ` [PATCH v3] " Hasan Basbunar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=afoJ9ha8NaJl1IRC@levanger \
--to=nsc@kernel.org \
--cc=basbunarhasan@gmail.com \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=masahiroy@kernel.org \
--cc=nathan@kernel.org \
--cc=rdunlap@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox