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]
Date:	Wed, 08 Apr 2015 07:32:53 -0400
From:	Peter Hurley <peter@...leysoftware.com>
To:	Alexander Kuleshov <kuleshovmail@...il.com>,
	Thomas Gleixner <tglx@...utronix.de>,
	Ingo Molnar <mingo@...hat.com>,
	"H. Peter Anvin" <hpa@...or.com>,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Yinghai Lu <yinghai@...nel.org>
CC:	linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/2] x86/earlyprintk: setup earlyprintk as early as possible

Hi Alexander,

On 04/08/2015 05:31 AM, Alexander Kuleshov wrote:
> As setup_early_printk passed to the early_param, it will be usable only after
> 'parse_early_param' function will be called from the 'setup_arch'. So we have
> earlyprintk during early boot and decompression. Next point after decompression
> of the kernel where we can use early_printk is after call of the
> 'parse_early_param'.
> 
> This patch makes setup_early_printk visible for head{32,64}.c So 'early_printk'
> function will be usabable after decompression of the kernel and before
> parse_early_param will be called. It also must be safe if CONFIG_CMDLINE_BOOL
> and CONFIG_CMDLINE_OVERRIDE are set, because setup_cmdline function will be
> called before setup_early_printk.
> 
> Tested it with qemu, so early_printk() is usable and prints to serial console
> right after setup_early_printk function called from arch/x86/kerne/head64.c
> 
> Changes v1->v2:
> 
> * Comment added before the setup_early_printk call;
> * Added information about testing to the commit message.
> 
> Changes v2->v3:
> 
> * Call setup_cmdline before setup_early_printk;
> * setup_early_printk call wrapped with the setup_early_serial_console which
> checks that 'serial' given to the earlyprintk command line option. This
> prevents call of the setup_early_printk with the given pciserial/dbgp/efi,
> because they are using early_ioremap.
> 
> Signed-off-by: Alexander Kuleshov <kuleshovmail@...il.com>
> ---
>  arch/x86/kernel/early_printk.c |  2 +-
>  arch/x86/kernel/head.c         | 14 ++++++++++++++
>  arch/x86/kernel/head32.c       |  2 ++
>  arch/x86/kernel/head64.c       |  7 ++++++-
>  include/linux/printk.h         |  4 ++++
>  kernel/printk/printk.c         | 11 +++++++----
>  6 files changed, 34 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
> index a62536a..19a94e0 100644
> --- a/arch/x86/kernel/early_printk.c
> +++ b/arch/x86/kernel/early_printk.c
> @@ -329,7 +329,7 @@ static inline void early_console_register(struct console *con, int keep_early)
>  	register_console(early_console);
>  }
>  
> -static int __init setup_early_printk(char *buf)
> +int __init setup_early_printk(char *buf)
>  {
>  	int keep;
>  
> diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c
> index 992f442..b6e72aa 100644
> --- a/arch/x86/kernel/head.c
> +++ b/arch/x86/kernel/head.c
> @@ -69,3 +69,17 @@ void __init reserve_ebda_region(void)
>  	/* reserve all memory between lowmem and the 1MB mark */
>  	memblock_reserve(lowmem, 0x100000 - lowmem);
>  }
> +
> +void setup_early_serial_console() {

If you put this function in kernel/early_printk.c, then
setup_early_printk() can remain file scope.

> +#ifdef CONFIG_EARLY_PRINTK
> +	char *arg;
> +
> +	arg = strstr(boot_command_line, "earlyprintk=serial");
> +	if (!arg)
> +		arg = strstr(boot_command_line, "earlyprintk=ttyS");
> +	if (!arg)
> +		return;
> +
> +	setup_early_printk(boot_command_line);

Like Ingo already pointed out, you need to emit a printk() after the
call to setup_early_printk() which validates that earlier-than-early
is working.

Because this isn't. setup_early_printk() expects the argument
to point to the start of the earlyprintk= parameter; ie.,

       earlyprintk=ttyS0,115200
                   ^
                  buf


> +#endif
> +}
> diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
> index 7ad0ad0..64c7a80 100644
> --- a/arch/x86/kernel/head32.c
> +++ b/arch/x86/kernel/head32.c
> @@ -32,6 +32,8 @@ static void __init i386_default_early_setup(void)
>  asmlinkage __visible void __init i386_start_kernel(void)
>  {
>  	setup_cmdline();
> +	/* setup serial console as early as possible */
> +	setup_early_serial_console();
>  	cr4_init_shadow();
>  	sanitize_boot_params(&boot_params);
>  
> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
> index 6eea2de..f0c03bd 100644
> --- a/arch/x86/kernel/head64.c
> +++ b/arch/x86/kernel/head64.c
> @@ -172,12 +172,15 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
>  
>  	copy_bootdata(__va(real_mode_data));
>  	setup_cmdline();
> +	/* setup serial console as early as possible */
> +	setup_early_serial_console();
>  
>  	/*
>  	 * Load microcode early on BSP.
>  	 */
>  	load_ucode_bsp();
>  
> +
>  	if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG)
>  		early_printk("Kernel alive\n");
>  
> @@ -193,8 +196,10 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data)
>  void __init x86_64_start_reservations(char *real_mode_data)
>  {
>  	/* version is always not zero if it is copied */
> -	if (!boot_params.hdr.version)
> +	if (!boot_params.hdr.version) {
>  		copy_bootdata(__va(real_mode_data));
> +		setup_early_serial_console();
> +	}
>  
>  	reserve_ebda_region();
>  
> diff --git a/include/linux/printk.h b/include/linux/printk.h
> index baa3f97..17358dd 100644
> --- a/include/linux/printk.h
> +++ b/include/linux/printk.h
> @@ -115,9 +115,13 @@ int no_printk(const char *fmt, ...)
>  #ifdef CONFIG_EARLY_PRINTK
>  extern asmlinkage __printf(1, 2)
>  void early_printk(const char *fmt, ...);
> +int setup_early_printk(char *buf);
> +void setup_early_serial_console(void);
>  #else
>  static inline __printf(1, 2) __cold
>  void early_printk(const char *s, ...) { }
> +int setup_early_printk(char *buf) { }
> +static void setup_early_serial_console(void) { }
>  #endif

These can't go here, because this will break the build of every non-x86
arch, since these symbols will not be defined in those arches. These need
to be in x86 includes only.

>  
>  typedef int(*printk_func_t)(const char *fmt, va_list args);
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index bb0635b..e56285c 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -2409,11 +2409,14 @@ void register_console(struct console *newcon)
>  	struct console_cmdline *c;
>  
>  	if (console_drivers)
> -		for_each_console(bcon)
> -			if (WARN(bcon == newcon,
> -					"console '%s%d' already registered\n",
> -					bcon->name, bcon->index))
> +		for_each_console(bcon) {
> +			/* not again */
> +			if (bcon == newcon) {
> +				printk(KERN_INFO "console '%s%d' already registered\n",
> +					bcon->name, bcon->index);
>  				return;
> +			}
> +		}

The WARN is still required here because the register_console() caller
is not always obvious.

A better way to achieve what you want is to not re-register the console
to begin with. Looking at early_console_register() and setup_early_printk(),
it seems like re-registration would already be prevented (since early_console
!= 0 after the first call to early_console_register())?  Have you tried this?

Regards,
Peter Hurley

>  
>  	/*
>  	 * before we register a new CON_BOOT console, make sure we don't
> 

--
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