diff mbox series

[SRU,Noble,1/1] UBUNTU: SAUCE: arm64: v6.8: cmdline param >= 146 chars kills kernel

Message ID 20240729232944.10019-2-matthew.ruffell@canonical.com
State New
Headers show
Series Linux 6.8 fails to boot on ARM64 if any param is more than 146 chars | expand

Commit Message

Matthew Ruffell July 29, 2024, 11:28 p.m. UTC
From: Tj <tj.iam.tj@proton.me>

BugLink: https://bugs.launchpad.net/bugs/2069534

This is v6.8 specific; v6.9 is reported as not affected (due to
extensive code refactoring).

Commit dc3f5aae0638 reworked how early cmdline CPU feature parsing
is done, and converted to using memcmp() in preparation for the move to
the pi minimal C standard library.
As a result it caused a regression where-by a parameter >= 146
characters on the kernel command line would cause a silent panic with no
console clues as to why.
It is due to memcmp() in include/linux/fortify-string.h detecting an
attempted out-of-bounds read. The cause itself is subtle.

arch/arm64/kernel/idreg-override.c::__parse_cmdline() compares the
struct aliases entries with each parameter via memcmp().

...
static const struct {
char alias[FTR_ALIAS_NAME_LEN];
char feature[FTR_ALIAS_OPTION_LEN];
} aliases[]

Each element is 146 characters. When a parameter is also 146 characters
the call looks like memcmp(buf, aliases[i].alias, len+1) where len is
the equivalent of strlen(buf) and +1 to compare including the trailing
NUL.

That triggers the fortified memcmp()'s:

if (p_size < size || q_size < size)
fortify_panic(__func__);

where q_size == 146, size == 147

The solution here is to not call memcmp() at all unless the two strings
have the same length.

Initially reported in Ubuntu (and confirmed to affect Debian and
Mainline):

https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2069534

Fixes: dc3f5aae0638 ("arm64: idreg-override: Avoid parameq() and parameqn()")
Signed-off-by: Tj <tj.iam.tj@proton.me>
Signed-off-by: Matthew Ruffell <matthew.ruffell@canonical.com>
---
 arch/arm64/kernel/idreg-override.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c
index e30fd9e32ef3..9d2c120f378a 100644
--- a/arch/arm64/kernel/idreg-override.c
+++ b/arch/arm64/kernel/idreg-override.c
@@ -308,7 +308,8 @@  static __init void __parse_cmdline(const char *cmdline, bool parse_aliases)
 		match_options(buf);
 
 		for (i = 0; parse_aliases && i < ARRAY_SIZE(aliases); i++)
-			if (!memcmp(buf, aliases[i].alias, len + 1))
+			if (len == strlen(aliases[i].alias) &&
+			    !memcmp(buf, aliases[i].alias, len + 1))
 				__parse_cmdline(aliases[i].feature, false);
 	} while (1);
 }