diff mbox series

[v7,16/33] arm64: idreg_override: Avoid kstrtou64() to parse a single hex digit

Message ID 20221111171201.2088501-17-ardb@kernel.org (mailing list archive)
State New, archived
Headers show
Series arm64: robustify boot sequence and add support for WXN | expand

Commit Message

Ard Biesheuvel Nov. 11, 2022, 5:11 p.m. UTC
All ID register value overrides are =0 with the exception of the nokaslr
pseudo feature which uses =1. In order to remove the dependency on
kstrtou64(), which is part of the core kernel and no longer usable once
we move idreg-override into the early mini C runtime, let's just parse a
single hex digit (with optional leading 0x) and set the output value
accordingly.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/kernel/idreg-override.c | 27 +++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c
index a5299aa1d1711adc..7e3eb48f5c83d539 100644
--- a/arch/arm64/kernel/idreg-override.c
+++ b/arch/arm64/kernel/idreg-override.c
@@ -170,6 +170,7 @@  static int __init find_field(const char *cmdline, char *opt, int len,
 			     const struct ftr_set_desc *reg, int f, u64 *v)
 {
 	int flen = strlen(reg->fields[f].name);
+	const char *p;
 
 	// append '<fieldname>=' to obtain '<name>.<fieldname>='
 	memcpy(opt + len, reg->fields[f].name, flen);
@@ -179,7 +180,31 @@  static int __init find_field(const char *cmdline, char *opt, int len,
 	if (memcmp(cmdline, opt, len))
 		return -1;
 
-	return kstrtou64(cmdline + len, 0, v);
+	p = cmdline + len;
+
+	// skip "0x" if it comes next
+	if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X'))
+		p += 2;
+
+	// check whether the RHS is a single non-whitespace character
+	if (*p == '\0' || (p[1] && !isspace(p[1])))
+		return -1;
+
+	// only accept a single hex character as the value
+	switch (*p) {
+	case '0' ... '9':
+		*v = *p - '0';
+		break;
+	case 'a' ... 'f':
+		*v = *p - 'a' + 10;
+		break;
+	case 'A' ... 'F':
+		*v = *p - 'A' + 10;
+		break;
+	default:
+		return -1;
+	}
+	return 0;
 }
 
 static const void * __init get_filter(const struct ftr_set_desc *reg, int idx)