lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20151222225244.C64747AF@viggo.jf.intel.com>
Date:	Tue, 22 Dec 2015 14:52:44 -0800
From:	Dave Hansen <dave@...1.net>
To:	x86@...nel.org
Cc:	linux-kernel@...r.kernel.org, Dave Hansen <dave@...1.net>,
	dave.hansen@...ux.intel.com, bp@...e.de, hpa@...or.com,
	fenghua.yu@...el.com, yu-cheng.yu@...el.com
Subject: [PATCH 5/5] x86: test early command-line code


From: Dave Hansen <dave.hansen@...ux.intel.com>

Here are some simple tests for the early command-line code.  It
had way more bugs than it should have, so let's make sure they
never pop up again.

Note, there are a few failures in here now.  We will fix those
up in the next few patches.

This is complete overkill for this code, but I had to do it to
convince myself that I wasn't making it any worse.

Signed-off-by: Dave Hansen <dave.hansen@...ux.intel.com>
Cc: Borislav Petkov <bp@...e.de>
Cc: H. Peter Anvin <hpa@...or.com>
Cc: linux-kernel@...r.kernel.org
Cc: fenghua.yu@...el.com
Cc: yu-cheng.yu@...el.com
---

 b/arch/x86/Kconfig.debug  |    7 ++
 b/arch/x86/kernel/check.c |    1 
 b/arch/x86/kernel/setup.c |    9 +++
 b/arch/x86/lib/cmdline.c  |  122 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 138 insertions(+), 1 deletion(-)

diff -puN arch/x86/Kconfig.debug~x86-early-command-line-test arch/x86/Kconfig.debug
--- a/arch/x86/Kconfig.debug~x86-early-command-line-test	2015-12-22 11:57:01.229266152 -0800
+++ b/arch/x86/Kconfig.debug	2015-12-22 11:57:01.238266557 -0800
@@ -400,4 +400,11 @@ config PUNIT_ATOM_DEBUG
 	  The current power state can be read from
 	  /sys/kernel/debug/punit_atom/dev_power_state
 
+config X86_TEST_EARLY_CMDLINE
+	bool "Early command line runtime tests"
+	---help---
+	  This creates some test command-lines and tries to parse
+	  a bunch of options from them.  The overhead is small both
+	  at boot and increased text/data sizes.
+
 endmenu
diff -puN arch/x86/kernel/check.c~x86-early-command-line-test arch/x86/kernel/check.c
--- a/arch/x86/kernel/check.c~x86-early-command-line-test	2015-12-22 11:57:01.230266197 -0800
+++ b/arch/x86/kernel/check.c	2015-12-22 11:57:01.239266602 -0800
@@ -164,4 +164,3 @@ static int start_periodic_check_for_corr
 	return 0;
 }
 device_initcall(start_periodic_check_for_corruption);
-
diff -puN arch/x86/lib/cmdline.c~x86-early-command-line-test arch/x86/lib/cmdline.c
--- a/arch/x86/lib/cmdline.c~x86-early-command-line-test	2015-12-22 11:57:01.232266287 -0800
+++ b/arch/x86/lib/cmdline.c	2015-12-22 11:57:01.239266602 -0800
@@ -4,6 +4,7 @@
  *
  * Misc librarized functions for cmdline poking.
  */
+#include <linux/bug.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
@@ -108,3 +109,124 @@ int cmdline_find_option_bool(const char
 	return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE,
 			option);
 }
+
+#ifdef CONFIG_X86_TEST_EARLY_CMDLINE
+
+static int __cmdtest(char *cmdline, int str_size, char *option,
+		int expected_result, int do_shrink)
+{
+	int ret;
+	int null_terminate;
+	/* Results are 1-based, so bias back down by 1 */
+	int option_end = expected_result + strlen(option) - 1;
+	int shrink_max = 0;
+
+	if (cmdline && do_shrink)
+		shrink_max = strlen(cmdline);
+	/*
+	 * The option was not found.  If it was not found in the
+	 * *full* command-line, it should never be found in any
+	 * *part* of the command-line.
+	 */
+	for (null_terminate = 0; null_terminate <= 1; null_terminate++) {
+		int shrink_by;
+		for (shrink_by = 0; shrink_by < shrink_max; shrink_by++) {
+			int str_size_tst = str_size - shrink_by;
+			char tmp = cmdline[str_size_tst];
+
+			/*
+			 * Do not run tests that would truncate
+			 * over the expected option
+			 */
+			if (str_size_tst <= option_end)
+				continue;
+
+			if (null_terminate)
+				cmdline[str_size_tst] = '\0';
+			ret = __cmdline_find_option_bool(cmdline, str_size_tst,
+					option);
+			if (null_terminate)
+				cmdline[str_size_tst] = tmp;
+
+			if (ret == expected_result)
+				continue;
+			pr_err("failed cmdline test ('%s', %d, '%s') == %d "
+					"nulld: %d got: %d\n",
+					cmdline, str_size_tst, option,
+					expected_result, null_terminate,
+					ret);
+			return 1;
+		}
+	}
+	return 0;
+}
+
+#define cmdtest(cmdline, option, result)	\
+	WARN_ON(__cmdtest(cmdline, sizeof(cmdline), option, result, 1))
+
+#define cmdtest_noshrink(cmdline, option, result)	\
+	WARN_ON(__cmdtest(cmdline, sizeof(cmdline), option, result, 0))
+
+char cmdline1[] = "CALL me Ishmael  ";
+char cmdline2[] = "Whenever I find myself growing grim about the mouth  ";
+char cmdline3[] = "grow growing  ";
+int test_early_cmdline(void)
+{
+	/* NULL command-line: */
+	WARN_ON(__cmdline_find_option_bool(NULL, 22, "Ishmael") != -1);
+	/* zero-length command-line: */
+	cmdtest("", "Ishmael", 0);
+
+	/* Find words at each of 3 positions: start, middle, end */
+	cmdtest(cmdline1, "CALL", 1);
+	cmdtest(cmdline1, "me", 6);
+	cmdtest(cmdline1, "Ishmael", 9);
+
+	/*
+	 * Fail to find strings that all occur in the cmdline,
+	 * but not as full words
+	 */
+	/*
+	 * If "option" is _present_ in "cmdline" as the start of a
+	 * word, like cmdline="foo bar" and we pass in option="b",
+	 * when we shrink cmdline to "foo b", it will match.  So,
+	 * skip shrink tests for those.
+	 */
+	cmdtest_noshrink(cmdline1, "m", 0);
+	cmdtest(cmdline1, "e", 0);
+	cmdtest(cmdline1, "C", 0);
+	cmdtest(cmdline1, "l", 0);
+	cmdtest_noshrink(cmdline1, "Ishmae", 0);
+	cmdtest(cmdline1, "mael", 0);
+	/*
+	 * Look for strings that do not occur, but match until
+	 * close to the end of cmdline
+	 */
+	cmdtest_noshrink(cmdline1, "Ishmae", 0);
+	cmdtest(cmdline1, "Ishmaels", 0);
+	cmdtest(cmdline1, "maels", 0);
+
+	/*
+	 * Look for full words that do not occur in a different
+	 * cmdline
+	 */
+	cmdtest(cmdline2, "CALL", 0);
+	cmdtest(cmdline2, "me", 0);
+	cmdtest(cmdline2, "Ishmael", 0);
+	/*
+	 * Look for full words which do occur in cmdline2
+	 */
+	cmdtest(cmdline2, "Whenever", 1);
+	cmdtest(cmdline2, "growing", 24);
+	cmdtest(cmdline2, "grim", 32);
+	cmdtest(cmdline2, "mouth", 47);
+
+	/*
+	 * Catch the bug where if we match a partial word and
+	 * then have a space, we do not match the _next_ word.
+	 */
+	cmdtest(cmdline3, "grow", 1);
+	cmdtest(cmdline3, "growing", 6);
+	return 0;
+}
+#endif /* CONFIG_X86_TEST_EARLY_CMDLINE */
diff -puN arch/x86/kernel/setup.c~x86-early-command-line-test arch/x86/kernel/setup.c
--- a/arch/x86/kernel/setup.c~x86-early-command-line-test	2015-12-22 11:57:01.233266332 -0800
+++ b/arch/x86/kernel/setup.c	2015-12-22 11:57:01.239266602 -0800
@@ -1282,3 +1282,12 @@ static int __init register_kernel_offset
 	return 0;
 }
 __initcall(register_kernel_offset_dumper);
+
+/*
+ * This code is in lib/ and we do not link initcalls from there.
+ * Stash it here instead.
+ */
+#ifdef CONFIG_X86_TEST_EARLY_CMDLINE
+int test_early_cmdline(void);
+late_initcall(test_early_cmdline);
+#endif /* CONFIG_X86_TEST_EARLY_CMDLINE */
_
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ