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: <20190926085855.debu7t46s7kgb26p@pathway.suse.cz>
Date:   Thu, 26 Sep 2019 10:58:55 +0200
From:   Petr Mladek <pmladek@...e.com>
To:     Sergey Senozhatsky <sergey.senozhatsky.work@...il.com>
Cc:     Uwe Kleine-König 
        <u.kleine-koenig@...gutronix.de>,
        Sergey Senozhatsky <sergey.senozhatsky@...il.com>,
        Steven Rostedt <rostedt@...dmis.org>,
        Tetsuo Handa <penguin-kernel@...ove.sakura.ne.jp>,
        linux-kernel@...r.kernel.org
Subject: Re: Regression in dbdda842fe96 ("printk: Add console owner and
 waiter logic to load balance console writes") [Was: Regression in
 fd5f7cde1b85 ("...")]

On Wed 2019-09-18 16:52:52, Sergey Senozhatsky wrote:
> On (09/18/19 09:11), Uwe Kleine-König wrote:
> > I rechecked and indeed fd5f7cde1b85's parent has the problem, too, so I
> > did a mistake during my bisection :-|
> > 
> > Redoing the bisection (a bit quicker this time) points to
> > 
> > dbdda842fe96 ("printk: Add console owner and waiter logic to load balance console writes")
> > 
> > Sorry for the confusion.
> 
> No worries!
> 
> [..]
> > > So I'd say that lockdep is correct, but there are several hacks which
> > > prevent actual deadlock.
>
> The basic idea is to handle sysrq out of port->lock.

Great idea!

> I didn't test it all (not even sure if it compiles).
> 
> ---
>  drivers/tty/serial/imx.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> index 87c58f9f6390..f0dd807b52df 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -731,9 +731,9 @@ static irqreturn_t imx_uart_rxint(int irq, void *dev_id)
>  	struct imx_port *sport = dev_id;
>  	unsigned int rx, flg, ignored = 0;
>  	struct tty_port *port = &sport->port.state->port;
> +	unsigned long flags;
>  
> -	spin_lock(&sport->port.lock);
> -
> +	uart_port_lock_irqsave(&sport->port, flags);

uart_port_lock_irqsave() does not exist. Instead the current users
do:

     spin_lock_irqsave(&port->lock, flags);

>  	while (imx_uart_readl(sport, USR2) & USR2_RDR) {
>  		u32 usr2;
>  
> @@ -749,8 +749,8 @@ static irqreturn_t imx_uart_rxint(int irq, void *dev_id)
>  				continue;
>  		}
>  
> -		if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx))
> -			continue;
> +		if (uart_prepare_sysrq_char(&sport->port, (unsigned char)rx))
> +			break;
>  
>  		if (unlikely(rx & URXD_ERR)) {
>  			if (rx & URXD_BRK)
> @@ -792,7 +792,7 @@ static irqreturn_t imx_uart_rxint(int irq, void *dev_id)
>  	}
>  
>  out:
> -	spin_unlock(&sport->port.lock);
> +	uart_unlock_and_check_sysrq(&sport->port, flags);

This API has been introduced for exactly this reason. See the commit
6e1935819db0c91ce4a5af ("serial: core: Allow processing sysrq at port
unlock time").

I like this approach. It allows to remove hacks with locks.

Well, Sergey's patch is nice example that the API is a bit confusing.
I would either make it symmetric and make a variant without saving
irq flags:

    uart_lock(port);
    uart_unlock_and_handle_sysrq(port);

    uart_lock_irqsave(port, flags);
    uart_unlock_irqrestore_and_handle_sysrq(port);

Or I would keep the locking as is and add some API
just for the sysrq handling:


   int uart_store_sysrq_char(struct uart_port *port, unsigned int ch);
   unsigned int uart_get_sysrq_char(struct uart_port *port);

And use it the following way:

	int handle_irq()
	{
		unsined int sysrq, sysrq_ch;

		spin_lock(&port->lock);
		[...]
			sysrq = uart_store_sysrq_char(port, ch);
			if (!sysrq)
				[...]
		[...]

	out:
		sysrq_ch = uart_get_sysrq_char(port);
		spin_unlock(&port->lock);

		if (sysrq_ch)
			handle_sysrq(sysrq_ch);
	}

I prefer the 2nd option. It is more code. But it is more
self explanatory.

What do you think?

Best Regards,
Petr

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ