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:   Mon, 2 Jan 2023 16:52:05 +0100
From:   Petr Mladek <pmladek@...e.com>
To:     John Ogness <john.ogness@...utronix.de>
Cc:     Sergey Senozhatsky <senozhatsky@...omium.org>,
        Steven Rostedt <rostedt@...dmis.org>,
        Thomas Gleixner <tglx@...utronix.de>,
        linux-kernel@...r.kernel.org
Subject: Re: [PATCH printk v3 5/6] printk: introduce
 console_get_next_message() and console_message

On Wed 2022-12-21 21:33:03, John Ogness wrote:
> Code for performing the console output is intermixed with code
> that is formatting the output for that console. Introduce a new
> helper function console_get_next_message() to handle the reading
> and formatting of the console text. The helper does not require
> any locking so that in the future it can be used for other console
> printing contexts as well.
> 
> This also introduces a new struct console_message to wrap the
> struct console_buffers adding meta-data about its contents. This
> allows users of console_get_next_message() to receive all relevant
> information about the message that was read and formatted.
> 
> The reason a wrapper struct is introduced instead of adding the
> meta-data to struct console_buffers is because the upcoming atomic
> consoles will need per-cpu and per-context console_buffers. It
> would not make sense to make the meta-data also per-cpu and
> per-context as that data can be easily stored on the stack of the
> console printing context.
> 
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index 2e5e2eda1fa1..7cac636600f8 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -2725,34 +2725,34 @@ static void __console_unlock(void)
>  }
>  
>  /*
> - * Print one record for the given console. The record printed is whatever
> - * record is the next available record for the given console.
> + * Read and format the specified record (or a later record if the specified
> + * record is not available).
>   *
> - * @handover will be set to true if a printk waiter has taken over the
> - * console_lock, in which case the caller is no longer holding both the
> - * console_lock and the SRCU read lock. Otherwise it is set to false.
> + * @cmsg will contain the formatted result. @cmsg->cbufs must point to a
> + * struct console_buffers.
>   *
> - * @cookie is the cookie from the SRCU read lock.
> + * @seq is the record to read and format. If it is not available, the next
> + * valid record is read.
>   *
> - * Returns false if the given console has no next record to print, otherwise
> - * true.
> + * @is_extended specifies the message should be formatted for extended
> + * console output.
>   *
> - * Requires the console_lock and the SRCU read lock.
> + * Returns false if no record is available. Otherwise true and all fields
> + * of @cmsg are valid. (See the documentation of struct console_message
> + * for information about the @cmsg fields.)
>   */
> -static bool console_emit_next_record(struct console *con, bool *handover, int cookie)
> -{
> -	bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED;
> -	static char dropped_text[DROPPED_TEXT_MAX];
> -	static struct console_buffers cbufs;
> -	const size_t scratchbuf_sz = sizeof(cbufs.scratchbuf);
> -	const size_t outbuf_sz = sizeof(cbufs.outbuf);
> -	char *scratchbuf = &cbufs.scratchbuf[0];
> -	char *outbuf = &cbufs.outbuf[0];
> +static bool console_get_next_message(struct console_message *cmsg, u64 seq,
> +				     bool is_extended)
> +{
> +	struct console_buffers *cbufs = cmsg->cbufs;
> +	const size_t scratchbuf_sz = sizeof(cbufs->scratchbuf);
> +	const size_t outbuf_sz = sizeof(cbufs->outbuf);
> +	char *scratchbuf = &cbufs->scratchbuf[0];
> +	char *outbuf = &cbufs->outbuf[0];
>  	static int panic_console_dropped;
>  	struct printk_info info;
>  	struct printk_record r;
> -	unsigned long flags;
> -	size_t len;
> +	size_t len = 0;
>  
>  	/*
>  	 * Formatting extended messages requires a separate buffer, so use the
> @@ -2766,33 +2766,77 @@ static bool console_emit_next_record(struct console *con, bool *handover, int co
>  	else
>  		prb_rec_init_rd(&r, &info, outbuf, outbuf_sz);
>  
> -	*handover = false;
> -
> -	if (!prb_read_valid(prb, con->seq, &r))
> +	if (!prb_read_valid(prb, seq, &r))
>  		return false;
>  
> -	if (con->seq != r.info->seq) {
> -		con->dropped += r.info->seq - con->seq;
> -		con->seq = r.info->seq;
> -		if (panic_in_progress() && panic_console_dropped++ > 10) {
> -			suppress_panic_printk = 1;
> -			pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n");
> -		}
> +	cmsg->outbuf_seq = r.info->seq;
> +	cmsg->dropped = r.info->seq - seq;
> +
> +	/*
> +	 * Check for dropped messages in panic here so that printk
> +	 * suppression can occur as early as possible if necessary.
> +	 */
> +	if (cmsg->dropped &&
> +	    panic_in_progress() &&
> +	    panic_console_dropped++ > 10) {
> +		suppress_panic_printk = 1;
> +		pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n");
>  	}
>  
>  	/* Skip record that has level above the console loglevel. */
> -	if (suppress_message_printing(r.info->level)) {
> -		con->seq++;
> -		goto skip;
> -	}
> +	if (suppress_message_printing(r.info->level))
> +		goto out;
>  
>  	if (is_extended) {
>  		len = info_print_ext_header(outbuf, outbuf_sz, r.info);
>  		len += msg_print_ext_body(outbuf + len, outbuf_sz - len,
> -					  &r.text_buf[0], r.info->text_len, &r.info->dev_info);
> +					  r.text_buf, r.info->text_len, &r.info->dev_info);

This probably was not intended.

If you agree then I could revert this change when pushing.
Or feel free to send respin of this patch.


>  	} else {
>  		len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time);
>  	}
> +out:
> +	cmsg->outbuf_len = len;
> +	return true;
> +}

Otherwise, it looks good:

Reviewed-by: Petr Mladek <pmladek@...e.com>

Best Regards,
Petr

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ