2018-08-14 15:41:55

by He Zhe

[permalink] [raw]
Subject: [PATCH v2 1/2] x86: corruption-check: Passing memory_corruption_check to command line causes panic

From: He Zhe <[email protected]>

memory_corruption_check[{_period|_size}]'s handlers do not check input
argument before passing it to kstrtoul or simple_strtoull. The argument
would be a NULL pointer if each of the kernel parameters, without its
value, is set in command line and thus cause the following panic.

PANIC: early exception 0xe3 IP 10:ffffffff73587c22 error 0 cr2 0x0
[ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.18-rc8+ #2
[ 0.000000] RIP: 0010:kstrtoull+0x2/0x10
...
[ 0.000000] Call Trace
[ 0.000000] ? set_corruption_check+0x21/0x49
[ 0.000000] ? do_early_param+0x4d/0x82
[ 0.000000] ? parse_args+0x212/0x330
[ 0.000000] ? rdinit_setup+0x26/0x26
[ 0.000000] ? parse_early_options+0x20/0x23
[ 0.000000] ? rdinit_setup+0x26/0x26
[ 0.000000] ? parse_early_param+0x2d/0x39
[ 0.000000] ? setup_arch+0x2f7/0xbf4
[ 0.000000] ? start_kernel+0x5e/0x4c2
[ 0.000000] ? load_ucode_bsp+0x113/0x12f
[ 0.000000] ? secondary_startup_64+0xa5/0xb0

This patch adds checks to prevent the panic.

Cc: [email protected]
Signed-off-by: He Zhe <[email protected]>
---
v2:
- Split out printk cleanups
- Add cc to [email protected]
- Use more meaningful error message

arch/x86/kernel/check.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c
index 3339942..cc8258a 100644
--- a/arch/x86/kernel/check.c
+++ b/arch/x86/kernel/check.c
@@ -31,6 +31,11 @@ static __init int set_corruption_check(char *arg)
ssize_t ret;
unsigned long val;

+ if (!arg) {
+ pr_err("memory_corruption_check config string not provided\n");
+ return -EINVAL;
+ }
+
ret = kstrtoul(arg, 10, &val);
if (ret)
return ret;
@@ -45,6 +50,11 @@ static __init int set_corruption_check_period(char *arg)
ssize_t ret;
unsigned long val;

+ if (!arg) {
+ pr_err("memory_corruption_check_period config string not provided\n");
+ return -EINVAL;
+ }
+
ret = kstrtoul(arg, 10, &val);
if (ret)
return ret;
@@ -59,6 +69,11 @@ static __init int set_corruption_check_size(char *arg)
char *end;
unsigned size;

+ if (!arg) {
+ pr_err("memory_corruption_check_size config string not provided\n");
+ return -EINVAL;
+ }
+
size = memparse(arg, &end);

if (*end == '\0')
--
2.7.4



2018-08-14 15:42:08

by He Zhe

[permalink] [raw]
Subject: [PATCH v2 2/2] x86: corruption-check: Change printk to the right fashion

From: He Zhe <[email protected]>

pr_* is preferred according to scripts/checkpatch.pl.

Signed-off-by: He Zhe <[email protected]>
---
v2:
- Split printk cleanups into a single patch
- Add pr_fmt for mod name

arch/x86/kernel/check.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c
index cc8258a..a3d9649 100644
--- a/arch/x86/kernel/check.c
+++ b/arch/x86/kernel/check.c
@@ -1,4 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kthread.h>
@@ -128,7 +131,8 @@ void __init setup_bios_corruption_check(void)
}

if (num_scan_areas)
- printk(KERN_INFO "Scanning %d areas for low memory corruption\n", num_scan_areas);
+ pr_info("Scanning %d areas for low memory corruption\n",
+ num_scan_areas);
}


@@ -147,7 +151,7 @@ void check_for_bios_corruption(void)
for (; size; addr++, size -= sizeof(unsigned long)) {
if (!*addr)
continue;
- printk(KERN_ERR "Corrupted low memory at %p (%lx phys) = %08lx\n",
+ pr_err("Corrupted low memory at %p (%lx phys) = %08lx\n",
addr, __pa(addr), *addr);
corruption = 1;
*addr = 0;
@@ -172,7 +176,7 @@ static int start_periodic_check_for_corruption(void)
if (!num_scan_areas || !memory_corruption_check || corruption_check_period == 0)
return 0;

- printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n",
+ pr_info("Scanning for low memory corruption every %d seconds\n",
corruption_check_period);

/* First time we run the checks right away */
--
2.7.4


2018-08-20 08:58:36

by He Zhe

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] x86: corruption-check: Passing memory_corruption_check to command line causes panic

Could you please provide your input? Thanks.

Zhe

On 2018年08月14日 23:33, [email protected] wrote:
> From: He Zhe <[email protected]>
>
> memory_corruption_check[{_period|_size}]'s handlers do not check input
> argument before passing it to kstrtoul or simple_strtoull. The argument
> would be a NULL pointer if each of the kernel parameters, without its
> value, is set in command line and thus cause the following panic.
>
> PANIC: early exception 0xe3 IP 10:ffffffff73587c22 error 0 cr2 0x0
> [ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.18-rc8+ #2
> [ 0.000000] RIP: 0010:kstrtoull+0x2/0x10
> ...
> [ 0.000000] Call Trace
> [ 0.000000] ? set_corruption_check+0x21/0x49
> [ 0.000000] ? do_early_param+0x4d/0x82
> [ 0.000000] ? parse_args+0x212/0x330
> [ 0.000000] ? rdinit_setup+0x26/0x26
> [ 0.000000] ? parse_early_options+0x20/0x23
> [ 0.000000] ? rdinit_setup+0x26/0x26
> [ 0.000000] ? parse_early_param+0x2d/0x39
> [ 0.000000] ? setup_arch+0x2f7/0xbf4
> [ 0.000000] ? start_kernel+0x5e/0x4c2
> [ 0.000000] ? load_ucode_bsp+0x113/0x12f
> [ 0.000000] ? secondary_startup_64+0xa5/0xb0
>
> This patch adds checks to prevent the panic.
>
> Cc: [email protected]
> Signed-off-by: He Zhe <[email protected]>
> ---
> v2:
> - Split out printk cleanups
> - Add cc to [email protected]
> - Use more meaningful error message
>
> arch/x86/kernel/check.c | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c
> index 3339942..cc8258a 100644
> --- a/arch/x86/kernel/check.c
> +++ b/arch/x86/kernel/check.c
> @@ -31,6 +31,11 @@ static __init int set_corruption_check(char *arg)
> ssize_t ret;
> unsigned long val;
>
> + if (!arg) {
> + pr_err("memory_corruption_check config string not provided\n");
> + return -EINVAL;
> + }
> +
> ret = kstrtoul(arg, 10, &val);
> if (ret)
> return ret;
> @@ -45,6 +50,11 @@ static __init int set_corruption_check_period(char *arg)
> ssize_t ret;
> unsigned long val;
>
> + if (!arg) {
> + pr_err("memory_corruption_check_period config string not provided\n");
> + return -EINVAL;
> + }
> +
> ret = kstrtoul(arg, 10, &val);
> if (ret)
> return ret;
> @@ -59,6 +69,11 @@ static __init int set_corruption_check_size(char *arg)
> char *end;
> unsigned size;
>
> + if (!arg) {
> + pr_err("memory_corruption_check_size config string not provided\n");
> + return -EINVAL;
> + }
> +
> size = memparse(arg, &end);
>
> if (*end == '\0')


2018-08-20 17:32:07

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] x86: corruption-check: Passing memory_corruption_check to command line causes panic

On Mon, Aug 20, 2018 at 04:56:22PM +0800, He Zhe wrote:
> Could you please provide your input? Thanks.

It is the middle of the merge window, we can not do anything with new
patches. This is a trivial cleanup fix, nothing that is really
important at the moment it will be reviewed in time, please give us a
chance.

thanks,

greg k-h

Subject: [tip:x86/boot] x86/corruption-check: Fix panic in memory_corruption_check() when boot option without value is provided

Commit-ID: ccde460b9ae5c2bd5e4742af0a7f623c2daad566
Gitweb: https://git.kernel.org/tip/ccde460b9ae5c2bd5e4742af0a7f623c2daad566
Author: He Zhe <[email protected]>
AuthorDate: Tue, 14 Aug 2018 23:33:42 +0800
Committer: Ingo Molnar <[email protected]>
CommitDate: Mon, 10 Sep 2018 14:47:32 +0200

x86/corruption-check: Fix panic in memory_corruption_check() when boot option without value is provided

memory_corruption_check[{_period|_size}]()'s handlers do not check input
argument before passing it to kstrtoul() or simple_strtoull(). The argument
would be a NULL pointer if each of the kernel parameters, without its
value, is set in command line and thus cause the following panic.

PANIC: early exception 0xe3 IP 10:ffffffff73587c22 error 0 cr2 0x0
[ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.18-rc8+ #2
[ 0.000000] RIP: 0010:kstrtoull+0x2/0x10
...
[ 0.000000] Call Trace
[ 0.000000] ? set_corruption_check+0x21/0x49
[ 0.000000] ? do_early_param+0x4d/0x82
[ 0.000000] ? parse_args+0x212/0x330
[ 0.000000] ? rdinit_setup+0x26/0x26
[ 0.000000] ? parse_early_options+0x20/0x23
[ 0.000000] ? rdinit_setup+0x26/0x26
[ 0.000000] ? parse_early_param+0x2d/0x39
[ 0.000000] ? setup_arch+0x2f7/0xbf4
[ 0.000000] ? start_kernel+0x5e/0x4c2
[ 0.000000] ? load_ucode_bsp+0x113/0x12f
[ 0.000000] ? secondary_startup_64+0xa5/0xb0

This patch adds checks to prevent the panic.

Signed-off-by: He Zhe <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/check.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c
index 33399426793e..cc8258a5378b 100644
--- a/arch/x86/kernel/check.c
+++ b/arch/x86/kernel/check.c
@@ -31,6 +31,11 @@ static __init int set_corruption_check(char *arg)
ssize_t ret;
unsigned long val;

+ if (!arg) {
+ pr_err("memory_corruption_check config string not provided\n");
+ return -EINVAL;
+ }
+
ret = kstrtoul(arg, 10, &val);
if (ret)
return ret;
@@ -45,6 +50,11 @@ static __init int set_corruption_check_period(char *arg)
ssize_t ret;
unsigned long val;

+ if (!arg) {
+ pr_err("memory_corruption_check_period config string not provided\n");
+ return -EINVAL;
+ }
+
ret = kstrtoul(arg, 10, &val);
if (ret)
return ret;
@@ -59,6 +69,11 @@ static __init int set_corruption_check_size(char *arg)
char *end;
unsigned size;

+ if (!arg) {
+ pr_err("memory_corruption_check_size config string not provided\n");
+ return -EINVAL;
+ }
+
size = memparse(arg, &end);

if (*end == '\0')

Subject: [tip:x86/boot] x86/corruption-check: Use pr_*() instead of printk()

Commit-ID: b1e3a25f5879017fc50ca17f03118b26a19df49a
Gitweb: https://git.kernel.org/tip/b1e3a25f5879017fc50ca17f03118b26a19df49a
Author: He Zhe <[email protected]>
AuthorDate: Tue, 14 Aug 2018 23:33:43 +0800
Committer: Ingo Molnar <[email protected]>
CommitDate: Mon, 10 Sep 2018 14:47:33 +0200

x86/corruption-check: Use pr_*() instead of printk()

pr_*() is the preferred style.

Signed-off-by: He Zhe <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Link: http://lkml.kernel.org/r/[email protected]
[ Moved all console output into a single line. ]
Signed-off-by: Ingo Molnar <[email protected]>
---
arch/x86/kernel/check.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kernel/check.c b/arch/x86/kernel/check.c
index cc8258a5378b..1979a76bfadd 100644
--- a/arch/x86/kernel/check.c
+++ b/arch/x86/kernel/check.c
@@ -1,4 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kthread.h>
@@ -41,6 +44,7 @@ static __init int set_corruption_check(char *arg)
return ret;

memory_corruption_check = val;
+
return 0;
}
early_param("memory_corruption_check", set_corruption_check);
@@ -128,7 +132,7 @@ void __init setup_bios_corruption_check(void)
}

if (num_scan_areas)
- printk(KERN_INFO "Scanning %d areas for low memory corruption\n", num_scan_areas);
+ pr_info("Scanning %d areas for low memory corruption\n", num_scan_areas);
}


@@ -147,8 +151,7 @@ void check_for_bios_corruption(void)
for (; size; addr++, size -= sizeof(unsigned long)) {
if (!*addr)
continue;
- printk(KERN_ERR "Corrupted low memory at %p (%lx phys) = %08lx\n",
- addr, __pa(addr), *addr);
+ pr_err("Corrupted low memory at %p (%lx phys) = %08lx\n", addr, __pa(addr), *addr);
corruption = 1;
*addr = 0;
}
@@ -172,11 +175,11 @@ static int start_periodic_check_for_corruption(void)
if (!num_scan_areas || !memory_corruption_check || corruption_check_period == 0)
return 0;

- printk(KERN_INFO "Scanning for low memory corruption every %d seconds\n",
- corruption_check_period);
+ pr_info("Scanning for low memory corruption every %d seconds\n", corruption_check_period);

/* First time we run the checks right away */
schedule_delayed_work(&bios_check_work, 0);
+
return 0;
}
device_initcall(start_periodic_check_for_corruption);