From: Andrew Morton <akpm@linux-foundation.org>
To: Armaan Sandhu <armaan.sandhu0504@gmail.com>
Cc: Andy Shevchenko <andriy.shevchenko@intel.com>,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
lzhan011 <lzsx618@gmail.com>
Subject: Re: [PATCH] lib/cmdline: fix get_options() count and overflow with large ranges
Date: Wed, 7 Oct 2026 15:00:07 -0700 [thread overview]
Message-ID: <20261007150007.c7c6f2a4e41fd9f950c8427c@linux-foundation.org> (raw)
In-Reply-To: <20261005213945.359905-1-armaan.sandhu0504@gmail.com>
On Mon, 5 Oct 2026 17:39:45 -0400 Armaan Sandhu <armaan.sandhu0504@gmail.com> wrote:
> get_range() stops writing once the array is full, but get_options()
> still advances its index by the whole range. So "1-100" parsed into
> four ints reports 99 numbers, and a range like "0-2147483647" wraps
> the index negative and writes outside the array.
>
> Stop once a range fills the array, bail out in validation mode before
> the count overflows, and saturate the range length in get_range().
> Add KUnit cases; without the fix "0-2147483647" panics the test kernel.
>
> Only root can supply this input, so this is a robustness fix.
>
> Fixes: 22f2e2801799 ("[PATCH] get_options to allow a hypenated range for isolcpus")
> Cc: stable@vger.kernel.org
> Signed-off-by: Armaan Sandhu <armaan.sandhu0504@gmail.com>
I've received two fixes for the same 20 year old bug with an hour
(https://lore.kernel.org/20261005202412.3460441-1-lzsx618@gmail.com).
How did that happen?
> lib/cmdline.c | 13 ++++++++++++-
> lib/tests/cmdline_kunit.c | 38 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 50 insertions(+), 1 deletion(-)
The kunit changes appear to be identical. Which fix is best?
> diff --git a/lib/cmdline.c b/lib/cmdline.c
> index 16cce6621cec..40b98d943a9a 100644
> --- a/lib/cmdline.c
> +++ b/lib/cmdline.c
> @@ -11,6 +11,7 @@
>
> #include <linux/export.h>
> #include <linux/kernel.h>
> +#include <linux/overflow.h>
> #include <linux/string.h>
> #include <linux/ctype.h>
>
> @@ -26,7 +27,9 @@ static int get_range(char **str, int *pint, int n)
>
> (*str)++;
> upper_range = simple_strtol((*str), NULL, 0);
> - inc_counter = upper_range - *pint;
> + /* Keep the sign of the result when the difference doesn't fit */
> + if (check_sub_overflow(upper_range, *pint, &inc_counter))
> + inc_counter = upper_range < *pint ? -1 : INT_MAX;
> for (x = *pint; n && x < upper_range; x++, n--)
> *pint++ = x;
> return inc_counter;
> @@ -122,6 +125,14 @@ char *get_options(const char *str, int nints, int *ints)
> range_nums = get_range((char **)&str, pint, n);
> if (range_nums < 0)
> break;
> + /* The range didn't fit, so the array is full */
> + if (!validate && range_nums > n) {
> + i = nints;
> + break;
> + }
> + /* Leave room for the upper number of the range */
> + if (range_nums >= INT_MAX - i)
> + break;
> /*
> * Decrement the result by one to leave out the
> * last number in the range. The next iteration
> diff --git a/lib/tests/cmdline_kunit.c b/lib/tests/cmdline_kunit.c
> index 3f61ff8d3178..584fcb2c0e44 100644
> --- a/lib/tests/cmdline_kunit.c
> +++ b/lib/tests/cmdline_kunit.c
> @@ -140,6 +140,43 @@ static void cmdline_test_range(struct kunit *test)
> } while (++i < ARRAY_SIZE(cmdline_test_range_strings));
> }
>
> +static const struct {
> + const char *in;
> + int parsed[4];
> + int validated;
> +} cmdline_test_range_overflow_cases[] = {
> + { "1-100", { 3, 1, 2, 3, }, 100, },
> + { "1,5-100,7", { 3, 1, 5, 6, }, 98, },
> + { "1-2147483646", { 3, 1, 2, 3, }, 2147483646, },
> + { "0-2147483647", { 3, 0, 1, 2, }, 0, },
> + { "-5-2147483647", { 3, -5, -4, -3, }, 0, },
> + { "2147483647--5", { 0, 2147483647, }, 0, },
> +};
> +
> +static void cmdline_test_range_overflow(struct kunit *test)
> +{
> + unsigned int i, j;
> +
> + for (i = 0; i < ARRAY_SIZE(cmdline_test_range_overflow_cases); i++) {
> + const char *in = cmdline_test_range_overflow_cases[i].in;
> + const int *e = cmdline_test_range_overflow_cases[i].parsed;
> + /* Two guard elements past the array handed to get_options() */
> + int r[ARRAY_SIZE(cmdline_test_range_overflow_cases[0].parsed) + 2];
> + int n;
> +
> + memset(r, 0, sizeof(r));
> + get_options(in, ARRAY_SIZE(r) - 2, r);
> + for (j = 0; j < ARRAY_SIZE(r) - 2; j++)
> + KUNIT_EXPECT_EQ_MSG(test, r[j], e[j], "Pattern: %s at %u", in, j);
> + for (; j < ARRAY_SIZE(r); j++)
> + KUNIT_EXPECT_EQ_MSG(test, r[j], 0, "Pattern: %s out of bound at %u", in, j);
> +
> + get_options(in, 0, &n);
> + KUNIT_EXPECT_EQ_MSG(test, n, cmdline_test_range_overflow_cases[i].validated,
> + "Pattern: %s (validated)", in);
> + }
> +}
> +
> static void cmdline_test_next_arg_quoted_value(struct kunit *test)
> {
> char in[] = "foo=\"bar baz\" qux=1";
> @@ -258,6 +295,7 @@ static struct kunit_case cmdline_test_cases[] = {
> KUNIT_CASE(cmdline_test_lead_int),
> KUNIT_CASE(cmdline_test_tail_int),
> KUNIT_CASE(cmdline_test_range),
> + KUNIT_CASE(cmdline_test_range_overflow),
> KUNIT_CASE(cmdline_test_next_arg_quoted_value),
> KUNIT_CASE(cmdline_test_next_arg_bare_quote_regression),
> KUNIT_CASE(cmdline_test_next_arg_mixed_tokens),
> --
> 2.55.0
next prev parent reply other threads:[~2026-10-07 22:00 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-05 21:39 Armaan Sandhu
2026-10-07 22:00 ` Andrew Morton [this message]
[not found] ` <CAGD6qbSfTmHq7Y_jM7-QS26at=w6OQwfOZjCU8n4PnnFmqgDNg@mail.gmail.com>
2026-10-07 23:08 ` Andrew Morton
[not found] ` <CAGD6qbRJFPX9dYHokumQat3q0AZiG7bgC3hr8rMpCc_BUS6f2g@mail.gmail.com>
[not found] ` <CANVJMCFQr9r5-_z3MKkX3G56DWBQTBK8XHW8+YBmme4=F+Cb5A@mail.gmail.com>
2026-10-08 0:08 ` Andrew Morton
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=20261007150007.c7c6f2a4e41fd9f950c8427c@linux-foundation.org \
--to=akpm@linux-foundation.org \
--cc=andriy.shevchenko@intel.com \
--cc=armaan.sandhu0504@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lzsx618@gmail.com \
--cc=stable@vger.kernel.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
all inboxes | Powered by JetHome®