2018-09-22 15:41:31

by He Zhe

[permalink] [raw]
Subject: [PATCH v3 1/2] printk: Fix panic caused by passing log_buf_len to command line

From: He Zhe <[email protected]>

log_buf_len_setup does not check input argument before passing it to
simple_strtoull. The argument would be a NULL pointer if "log_buf_len",
without its value, is set in command line and thus causes the following
panic.

PANIC: early exception 0xe3 IP 10:ffffffffaaeacd0d error 0 cr2 0x0
[ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.19.0-rc4-yocto-standard+ #1
[ 0.000000] RIP: 0010:_parse_integer_fixup_radix+0xd/0x70
...
[ 0.000000] Call Trace:
[ 0.000000] simple_strtoull+0x29/0x70
[ 0.000000] memparse+0x26/0x90
[ 0.000000] log_buf_len_setup+0x17/0x22
[ 0.000000] do_early_param+0x57/0x8e
[ 0.000000] parse_args+0x208/0x320
[ 0.000000] ? rdinit_setup+0x30/0x30
[ 0.000000] parse_early_options+0x29/0x2d
[ 0.000000] ? rdinit_setup+0x30/0x30
[ 0.000000] parse_early_param+0x36/0x4d
[ 0.000000] setup_arch+0x336/0x99e
[ 0.000000] start_kernel+0x6f/0x4ee
[ 0.000000] x86_64_start_reservations+0x24/0x26
[ 0.000000] x86_64_start_kernel+0x6f/0x72
[ 0.000000] secondary_startup_64+0xa4/0xb0

This patch adds a check to prevent the panic.

Signed-off-by: He Zhe <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
v2:
Split out the addition of pr_fmt and the unsigned update
v3:
Use more clear error info
Change unsigned to unsigned in to avoid checkpatch.pl warning

kernel/printk/printk.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 9bf5404..d9821c0 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1048,7 +1048,14 @@ static void __init log_buf_len_update(unsigned size)
/* save requested log_buf_len since it's too early to process it */
static int __init log_buf_len_setup(char *str)
{
- unsigned size = memparse(str, &str);
+ unsigned int size;
+
+ if (!str) {
+ pr_err("boot command line parameter value not provided\n");
+ return -EINVAL;
+ }
+
+ size = memparse(str, &str);

log_buf_len_update(size);

--
2.7.4



2018-09-22 15:42:54

by He Zhe

[permalink] [raw]
Subject: [PATCH v3 2/2] printk: Add KBUILD_MODNAME and correct wrong casting

From: He Zhe <[email protected]>

Add KBUILD_MODNAME to make prints more clear and correct wrong casting that
might cut off the normal output.

Signed-off-by: He Zhe <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
---
v2:
Correct one more place
v3:
Correct wrong casting

kernel/printk/printk.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index d9821c0..6b059a0 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -16,6 +16,8 @@
* 01Mar01 Andrew Morton
*/

+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/tty.h>
@@ -2358,8 +2360,9 @@ void console_unlock(void)
printk_safe_enter_irqsave(flags);
raw_spin_lock(&logbuf_lock);
if (console_seq < log_first_seq) {
- len = sprintf(text, "** %u printk messages dropped **\n",
- (unsigned)(log_first_seq - console_seq));
+ len = sprintf(text,
+ "** %llu printk messages dropped **\n",
+ log_first_seq - console_seq);

/* messages are gone, move to first one */
console_seq = log_first_seq;
--
2.7.4


2018-09-22 16:19:29

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] printk: Fix panic caused by passing log_buf_len to command line

On Sat, 22 Sep 2018 23:40:51 +0800
<[email protected]> wrote:

> From: He Zhe <[email protected]>
>
> log_buf_len_setup does not check input argument before passing it to
> simple_strtoull. The argument would be a NULL pointer if "log_buf_len",
> without its value, is set in command line and thus causes the following
> panic.
>
> PANIC: early exception 0xe3 IP 10:ffffffffaaeacd0d error 0 cr2 0x0
> [ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.19.0-rc4-yocto-standard+ #1
> [ 0.000000] RIP: 0010:_parse_integer_fixup_radix+0xd/0x70
> ...
> [ 0.000000] Call Trace:
> [ 0.000000] simple_strtoull+0x29/0x70
> [ 0.000000] memparse+0x26/0x90
> [ 0.000000] log_buf_len_setup+0x17/0x22
> [ 0.000000] do_early_param+0x57/0x8e
> [ 0.000000] parse_args+0x208/0x320
> [ 0.000000] ? rdinit_setup+0x30/0x30
> [ 0.000000] parse_early_options+0x29/0x2d
> [ 0.000000] ? rdinit_setup+0x30/0x30
> [ 0.000000] parse_early_param+0x36/0x4d
> [ 0.000000] setup_arch+0x336/0x99e
> [ 0.000000] start_kernel+0x6f/0x4ee
> [ 0.000000] x86_64_start_reservations+0x24/0x26
> [ 0.000000] x86_64_start_kernel+0x6f/0x72
> [ 0.000000] secondary_startup_64+0xa4/0xb0
>
> This patch adds a check to prevent the panic.
>
> Signed-off-by: He Zhe <[email protected]>
> Cc: [email protected]

I just tried this on a 2.6.32 kernel, and it crashes there. I guess
this goes farther back than git history goes.

Perhaps it should be commented that this bug has been here since
creation of (git) time.


> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> ---
> v2:
> Split out the addition of pr_fmt and the unsigned update

Which unsigned update? As it does switch to unsigned to "unsigned int",
but that change is fine to me with this.

> v3:
> Use more clear error info
> Change unsigned to unsigned in to avoid checkpatch.pl warning
>
> kernel/printk/printk.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index 9bf5404..d9821c0 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -1048,7 +1048,14 @@ static void __init log_buf_len_update(unsigned size)
> /* save requested log_buf_len since it's too early to process it */
> static int __init log_buf_len_setup(char *str)
> {
> - unsigned size = memparse(str, &str);
> + unsigned int size;

I'm OK with the int update too, as its low risk.

Acked-by: Steven Rostedt (VMware) <[email protected]>

-- Steve

> +
> + if (!str) {
> + pr_err("boot command line parameter value not provided\n");
> + return -EINVAL;
> + }
> +
> + size = memparse(str, &str);
>
> log_buf_len_update(size);
>


2018-09-23 06:51:43

by He Zhe

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] printk: Fix panic caused by passing log_buf_len to command line



On 2018年09月23日 00:19, Steven Rostedt wrote:
> On Sat, 22 Sep 2018 23:40:51 +0800
> <[email protected]> wrote:
>
>> From: He Zhe <[email protected]>
>>
>> log_buf_len_setup does not check input argument before passing it to
>> simple_strtoull. The argument would be a NULL pointer if "log_buf_len",
>> without its value, is set in command line and thus causes the following
>> panic.
>>
>> PANIC: early exception 0xe3 IP 10:ffffffffaaeacd0d error 0 cr2 0x0
>> [ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.19.0-rc4-yocto-standard+ #1
>> [ 0.000000] RIP: 0010:_parse_integer_fixup_radix+0xd/0x70
>> ...
>> [ 0.000000] Call Trace:
>> [ 0.000000] simple_strtoull+0x29/0x70
>> [ 0.000000] memparse+0x26/0x90
>> [ 0.000000] log_buf_len_setup+0x17/0x22
>> [ 0.000000] do_early_param+0x57/0x8e
>> [ 0.000000] parse_args+0x208/0x320
>> [ 0.000000] ? rdinit_setup+0x30/0x30
>> [ 0.000000] parse_early_options+0x29/0x2d
>> [ 0.000000] ? rdinit_setup+0x30/0x30
>> [ 0.000000] parse_early_param+0x36/0x4d
>> [ 0.000000] setup_arch+0x336/0x99e
>> [ 0.000000] start_kernel+0x6f/0x4ee
>> [ 0.000000] x86_64_start_reservations+0x24/0x26
>> [ 0.000000] x86_64_start_kernel+0x6f/0x72
>> [ 0.000000] secondary_startup_64+0xa4/0xb0
>>
>> This patch adds a check to prevent the panic.
>>
>> Signed-off-by: He Zhe <[email protected]>
>> Cc: [email protected]
> I just tried this on a 2.6.32 kernel, and it crashes there. I guess
> this goes farther back than git history goes.
>
> Perhaps it should be commented that this bug has been here since
> creation of (git) time.

I did a try on 2.6.32. It passed. Actually this bug only happens on
early_param(not __setup) which is introduced since v3.0. The oldest
LTS version is 3.16 now. Should I send v4 and add a statement about
the supported version range in commit log?

>
>
>> Cc: [email protected]
>> Cc: [email protected]
>> Cc: [email protected]
>> ---
>> v2:
>> Split out the addition of pr_fmt and the unsigned update
> Which unsigned update? As it does switch to unsigned to "unsigned int",
> but that change is fine to me with this.

No problem. It's the history of v2.

In v1 you suggested "unsigned int size" should be in a separate patch and
I did that in v2. Then Sergey suggested "unsigned int size" should be in the
1/2 patch to avoid checkpatch.pl warning. With your conformation, I add it
back here in v3.

Thanks,
Zhe

>
>> v3:
>> Use more clear error info
>> Change unsigned to unsigned in to avoid checkpatch.pl warning
>>
>> kernel/printk/printk.c | 9 ++++++++-
>> 1 file changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
>> index 9bf5404..d9821c0 100644
>> --- a/kernel/printk/printk.c
>> +++ b/kernel/printk/printk.c
>> @@ -1048,7 +1048,14 @@ static void __init log_buf_len_update(unsigned size)
>> /* save requested log_buf_len since it's too early to process it */
>> static int __init log_buf_len_setup(char *str)
>> {
>> - unsigned size = memparse(str, &str);
>> + unsigned int size;
> I'm OK with the int update too, as its low risk.
>
> Acked-by: Steven Rostedt (VMware) <[email protected]>
>
> -- Steve
>
>> +
>> + if (!str) {
>> + pr_err("boot command line parameter value not provided\n");
>> + return -EINVAL;
>> + }
>> +
>> + size = memparse(str, &str);
>>
>> log_buf_len_update(size);
>>
>


2018-09-24 13:14:24

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] printk: Fix panic caused by passing log_buf_len to command line

On Sun, 23 Sep 2018 14:51:12 +0800
He Zhe <[email protected]> wrote:

> On 2018年09月23日 00:19, Steven Rostedt wrote:
> > On Sat, 22 Sep 2018 23:40:51 +0800
> > <[email protected]> wrote:
> >
> >> From: He Zhe <[email protected]>
> >>
> >> log_buf_len_setup does not check input argument before passing it to
> >> simple_strtoull. The argument would be a NULL pointer if "log_buf_len",
> >> without its value, is set in command line and thus causes the following
> >> panic.
> >>
> >> PANIC: early exception 0xe3 IP 10:ffffffffaaeacd0d error 0 cr2 0x0
> >> [ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.19.0-rc4-yocto-standard+ #1
> >> [ 0.000000] RIP: 0010:_parse_integer_fixup_radix+0xd/0x70
> >> ...
> >> [ 0.000000] Call Trace:
> >> [ 0.000000] simple_strtoull+0x29/0x70
> >> [ 0.000000] memparse+0x26/0x90
> >> [ 0.000000] log_buf_len_setup+0x17/0x22
> >> [ 0.000000] do_early_param+0x57/0x8e
> >> [ 0.000000] parse_args+0x208/0x320
> >> [ 0.000000] ? rdinit_setup+0x30/0x30
> >> [ 0.000000] parse_early_options+0x29/0x2d
> >> [ 0.000000] ? rdinit_setup+0x30/0x30
> >> [ 0.000000] parse_early_param+0x36/0x4d
> >> [ 0.000000] setup_arch+0x336/0x99e
> >> [ 0.000000] start_kernel+0x6f/0x4ee
> >> [ 0.000000] x86_64_start_reservations+0x24/0x26
> >> [ 0.000000] x86_64_start_kernel+0x6f/0x72
> >> [ 0.000000] secondary_startup_64+0xa4/0xb0
> >>
> >> This patch adds a check to prevent the panic.
> >>
> >> Signed-off-by: He Zhe <[email protected]>
> >> Cc: [email protected]
> > I just tried this on a 2.6.32 kernel, and it crashes there. I guess
> > this goes farther back than git history goes.
> >
> > Perhaps it should be commented that this bug has been here since
> > creation of (git) time.
>
> I did a try on 2.6.32. It passed. Actually this bug only happens on
> early_param(not __setup) which is introduced since v3.0. The oldest

Really? This is what I got:

Linux version 2.6.32-565.el6.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC) ) #1 SMP Tue Jun 2 14:53:05 EDT 2015
Command line: ro root=UUID=b6bbd80c-a321-4350-9d87-ba8ec1f45917 LANG=en_US.UTF-8 SYSFONT=latarcyrheb-sun16 KEYTABLE=us console=ttyS0,115200 crashkernel=auto selinux=0 earlyprintk=ttyS0,115200 log_buf_len
KERNEL supported cpus:
Intel GenuineIntel
AMD AuthenticAMD
Centaur CentaurHauls
BIOS-provided physical RAM map:
BIOS-e820: 0000000000000000 - 000000000009d800 (usable)
BIOS-e820: 000000000009d800 - 00000000000a0000 (reserved)
BIOS-e820: 00000000000e0000 - 0000000000100000 (reserved)
BIOS-e820: 0000000000100000 - 00000000c69ee000 (usable)
BIOS-e820: 00000000c69ee000 - 00000000c69f5000 (ACPI NVS)
BIOS-e820: 00000000c69f5000 - 00000000c6e38000 (usable)
BIOS-e820: 00000000c6e38000 - 00000000c73c9000 (reserved)
BIOS-e820: 00000000c73c9000 - 00000000d8dac000 (usable)
BIOS-e820: 00000000d8dac000 - 00000000d8e44000 (reserved)
BIOS-e820: 00000000d8e44000 - 00000000d8e95000 (usable)
BIOS-e820: 00000000d8e95000 - 00000000d8fc8000 (ACPI NVS)
BIOS-e820: 00000000d8fc8000 - 00000000d9fff000 (reserved)
BIOS-e820: 00000000d9fff000 - 00000000da000000 (usable)
BIOS-e820: 00000000db000000 - 00000000df200000 (reserved)
BIOS-e820: 00000000f8000000 - 00000000fc000000 (reserved)
BIOS-e820: 00000000fec00000 - 00000000fec01000 (reserved)
BIOS-e820: 00000000fed00000 - 00000000fed04000 (reserved)
BIOS-e820: 00000000fed1c000 - 00000000fed20000 (reserved)
BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved)
BIOS-e820: 00000000ff000000 - 0000000100000000 (reserved)
BIOS-e820: 0000000100000000 - 000000021ee00000 (usable)
bootconsole [earlyser0] enabled
PANIC: early exception 0e rip 10:ffffffff812a1a4d error 0 cr2 0
Pid: 0, comm: swapper Not tainted 2.6.32-565.el6.x86_64 #1
Call Trace:
[<ffffffff81043069>] ? native_read_cr2+0x9/0x10
[<ffffffff81c3719e>] ? early_idt_handler+0x5e/0x71
[<ffffffff812a1a4d>] ? _parse_integer_fixup_radix+0xd/0x70
[<ffffffff8129b29a>] ? simple_strtoull+0x1a/0x50
[<ffffffff8128fde7>] ? memparse+0x17/0x90
[<ffffffff81c58166>] ? log_buf_len_setup+0x15/0x47
[<ffffffff81c37790>] ? do_early_param+0x5d/0x89
[<ffffffff8109dcc7>] ? parse_args+0x197/0x340
[<ffffffff81c37733>] ? do_early_param+0x0/0x89
[<ffffffff81c377da>] ? parse_early_options+0x1e/0x20
[<ffffffff81c37cf2>] ? parse_early_param+0x31/0x3d
[<ffffffff81c3d548>] ? setup_arch+0x36f/0xc69
[<ffffffff8153783d>] ? printk+0x41/0x44
[<ffffffff81c37dda>] ? start_kernel+0xdc/0x431
[<ffffffff81c3733a>] ? x86_64_start_reservations+0x125/0x129
[<ffffffff81c37453>] ? x86_64_start_kernel+0x115/0x124
RIP _parse_integer_fixup_radix+0xd/0x70

> LTS version is 3.16 now. Should I send v4 and add a statement about
> the supported version range in commit log?

Fixes tags and stable info can be added by the maintainer that pulls in
the patch. I was just commenting on it for them.

>
> >
> >
> >> Cc: [email protected]
> >> Cc: [email protected]
> >> Cc: [email protected]
> >> ---
> >> v2:
> >> Split out the addition of pr_fmt and the unsigned update
> > Which unsigned update? As it does switch to unsigned to "unsigned int",
> > but that change is fine to me with this.
>
> No problem. It's the history of v2.
>
> In v1 you suggested "unsigned int size" should be in a separate patch and
> I did that in v2. Then Sergey suggested "unsigned int size" should be in the
> 1/2 patch to avoid checkpatch.pl warning. With your conformation, I add it
> back here in v3.
>

Yeah, I'm fine with the addition. It should still be stated in the
main change log. The version history is cut from git commits.

Thanks!

-- Steve

2018-09-25 11:25:44

by Petr Mladek

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] printk: Fix panic caused by passing log_buf_len to command line

On Sat 2018-09-22 23:40:51, [email protected] wrote:
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index 9bf5404..d9821c0 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -1048,7 +1048,14 @@ static void __init log_buf_len_update(unsigned size)
> /* save requested log_buf_len since it's too early to process it */
> static int __init log_buf_len_setup(char *str)
> {
> - unsigned size = memparse(str, &str);
> + unsigned int size;
> +
> + if (!str) {
> + pr_err("boot command line parameter value not provided\n");

This message is too generic. It would be hard to guess what parameter was
affected. Also it is not fatal, so I would just use warning,
something like:

pr_warn("Warning: No value defined for the command line parameter: log_bug_len\n");

> + return -EINVAL;
> + }
> +
> + size = memparse(str, &str);
>
> log_buf_len_update(size);

Best Regards,
Petr

2018-09-25 11:35:22

by Petr Mladek

[permalink] [raw]
Subject: Re: [PATCH v3 2/2] printk: Add KBUILD_MODNAME and correct wrong casting

On Sat 2018-09-22 23:40:52, [email protected] wrote:
> From: He Zhe <[email protected]>
>
> Add KBUILD_MODNAME to make prints more clear and correct wrong casting that
> might cut off the normal output.
>
> Signed-off-by: He Zhe <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
> ---
> v2:
> Correct one more place
> v3:
> Correct wrong casting
>
> kernel/printk/printk.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index d9821c0..6b059a0 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -16,6 +16,8 @@
> * 01Mar01 Andrew Morton
> */
>
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +

This patch should remove all explicit prefixes to avoid duplication.
I see one:

pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n");


> #include <linux/kernel.h>
> #include <linux/mm.h>
> #include <linux/tty.h>
> @@ -2358,8 +2360,9 @@ void console_unlock(void)
> printk_safe_enter_irqsave(flags);
> raw_spin_lock(&logbuf_lock);
> if (console_seq < log_first_seq) {
> - len = sprintf(text, "** %u printk messages dropped **\n",
> - (unsigned)(log_first_seq - console_seq));
> + len = sprintf(text,
> + "** %llu printk messages dropped **\n",
> + log_first_seq - console_seq);

On the contrary, please, put this fix into a separate patch. It is a
candidate for stable backports.

Best Regards,
Petr

2018-09-25 11:39:08

by Sergey Senozhatsky

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] printk: Fix panic caused by passing log_buf_len to command line

On (09/22/18 23:40), [email protected] wrote:
> @@ -1048,7 +1048,14 @@ static void __init log_buf_len_update(unsigned size)
> /* save requested log_buf_len since it's too early to process it */
> static int __init log_buf_len_setup(char *str)
> {
> - unsigned size = memparse(str, &str);
> + unsigned int size;
> +
> + if (!str) {
> + pr_err("boot command line parameter value not provided\n");
> + return -EINVAL;
> + }

Hmm, I thought we agreed on dropping this error print out. It's not exactly
useful; we still have the default buffer size.

-ss

2018-09-25 11:58:10

by Petr Mladek

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] printk: Fix panic caused by passing log_buf_len to command line

On Tue 2018-09-25 20:38:40, Sergey Senozhatsky wrote:
> On (09/22/18 23:40), [email protected] wrote:
> > @@ -1048,7 +1048,14 @@ static void __init log_buf_len_update(unsigned size)
> > /* save requested log_buf_len since it's too early to process it */
> > static int __init log_buf_len_setup(char *str)
> > {
> > - unsigned size = memparse(str, &str);
> > + unsigned int size;
> > +
> > + if (!str) {
> > + pr_err("boot command line parameter value not provided\n");
> > + return -EINVAL;
> > + }
>
> Hmm, I thought we agreed on dropping this error print out. It's not exactly
> useful; we still have the default buffer size.

Yeah, we should either use a better message or drop it. I am fine with both
solutions.

Best Regards,
Petr