diff mbox

[v2] tty/serial: atmel: use port->name as name in request_irq()

Message ID 20180504081447.enontsm6jod4xa6g@linutronix.de (mailing list archive)
State New, archived
Headers show

Commit Message

Sebastian Andrzej Siewior May 4, 2018, 8:14 a.m. UTC
I was puzzled while looking at /proc/interrupts and random things showed
up between reboots. This occurred more often but I realised it later. The
"correct" output should be:
|38:      11861  atmel-aic5   2 Level     ttyS0

but I saw sometimes
|38:       6426  atmel-aic5   2 Level     tty1

and accounted it wrongly as correct. This is use after free and the
former example randomly got the "old" pointer which pointed to the same
content. With SLAB_FREELIST_RANDOM and HARDENED I even got
|38:       7067  atmel-aic5   2 Level     E=Started User Manager for UID 0

or other nonsense.
As it turns out the tty, pointer that is accessed in atmel_startup(), is
freed() before atmel_shutdown(). It seems to happen quite often that the
tty for ttyS0 is allocated and freed while ->shutdown is not invoked. I
don't do anything special - just a systemd boot :)

Use port->name as the IRQ name for request_irq(). This exists as long as
the driver is loaded so no use-after-free here.
For backports before v4.12 I suggest to use `"atmel_serial"' instead
`port->name' (that member was introduced in f7048b15900f ("tty: serial_core:
Add name field to uart_port struct").

Cc: stable@vger.kernel.org
Fixes: 761ed4a94582 ("tty: serial_core: convert uart_close to use tty_port_close")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
v1…v2: - Bisected and added a Fixes tag
       - added a note for backporters to v4.9 … v4.12 (pointed out by
	 Richard Genoud)

 drivers/tty/serial/atmel_serial.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

Comments

Richard Genoud May 4, 2018, 10:28 a.m. UTC | #1
On 04/05/2018 10:14, Sebastian Andrzej Siewior wrote:
> I was puzzled while looking at /proc/interrupts and random things showed
> up between reboots. This occurred more often but I realised it later. The
> "correct" output should be:
> |38:      11861  atmel-aic5   2 Level     ttyS0
> 
> but I saw sometimes
> |38:       6426  atmel-aic5   2 Level     tty1
> 
> and accounted it wrongly as correct. This is use after free and the
> former example randomly got the "old" pointer which pointed to the same
> content. With SLAB_FREELIST_RANDOM and HARDENED I even got
> |38:       7067  atmel-aic5   2 Level     E=Started User Manager for UID 0
> 
> or other nonsense.
> As it turns out the tty, pointer that is accessed in atmel_startup(), is
> freed() before atmel_shutdown(). It seems to happen quite often that the
> tty for ttyS0 is allocated and freed while ->shutdown is not invoked. I
> don't do anything special - just a systemd boot :)
> 
> Use port->name as the IRQ name for request_irq(). This exists as long as
> the driver is loaded so no use-after-free here.
> For backports before v4.12 I suggest to use `"atmel_serial"' instead
> `port->name' (that member was introduced in f7048b15900f ("tty: serial_core:
> Add name field to uart_port struct").
> 
> Cc: stable@vger.kernel.org
I think it's safer to use:
Cc: stable@vger.kernel.org # 4.14
Because the stable team may miss your comment, and even if they don't, I
think it's not their role to adapt the patch to 4.9.x (and test it !)
IMHO, the best way is to add # 4.14 and when it's applied on 4.14.x,
send a tested backport for 4.9.x

Besides that, you can add my:
Acked-by: Richard Genoud <richard.genoud@gmail.com>

Rob, do you agree with this fix ?


> Fixes: 761ed4a94582 ("tty: serial_core: convert uart_close to use tty_port_close")
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> v1…v2: - Bisected and added a Fixes tag
>        - added a note for backporters to v4.9 … v4.12 (pointed out by
> 	 Richard Genoud)
> 
>  drivers/tty/serial/atmel_serial.c | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index e287fe8f10fc..d3189816740e 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -1757,7 +1757,6 @@ static int atmel_startup(struct uart_port *port)
>  {
>  	struct platform_device *pdev = to_platform_device(port->dev);
>  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
> -	struct tty_struct *tty = port->state->port.tty;
>  	int retval;
>  
>  	/*
> @@ -1772,8 +1771,7 @@ static int atmel_startup(struct uart_port *port)
>  	 * Allocate the IRQ
>  	 */
>  	retval = request_irq(port->irq, atmel_interrupt,
> -			IRQF_SHARED | IRQF_COND_SUSPEND,
> -			tty ? tty->name : "atmel_serial", port);
> +			     IRQF_SHARED | IRQF_COND_SUSPEND, port->name, port);
>  	if (retval) {
>  		dev_err(port->dev, "atmel_startup - Can't get irq\n");
>  		return retval;
> 

Thanks !
Rob Herring (Arm) May 4, 2018, 8:23 p.m. UTC | #2
On Fri, May 4, 2018 at 5:28 AM, Richard Genoud <richard.genoud@gmail.com> wrote:
> On 04/05/2018 10:14, Sebastian Andrzej Siewior wrote:
>> I was puzzled while looking at /proc/interrupts and random things showed
>> up between reboots. This occurred more often but I realised it later. The
>> "correct" output should be:
>> |38:      11861  atmel-aic5   2 Level     ttyS0
>>
>> but I saw sometimes
>> |38:       6426  atmel-aic5   2 Level     tty1
>>
>> and accounted it wrongly as correct. This is use after free and the
>> former example randomly got the "old" pointer which pointed to the same
>> content. With SLAB_FREELIST_RANDOM and HARDENED I even got
>> |38:       7067  atmel-aic5   2 Level     E=Started User Manager for UID 0
>>
>> or other nonsense.
>> As it turns out the tty, pointer that is accessed in atmel_startup(), is
>> freed() before atmel_shutdown(). It seems to happen quite often that the
>> tty for ttyS0 is allocated and freed while ->shutdown is not invoked. I
>> don't do anything special - just a systemd boot :)
>>
>> Use port->name as the IRQ name for request_irq(). This exists as long as
>> the driver is loaded so no use-after-free here.
>> For backports before v4.12 I suggest to use `"atmel_serial"' instead
>> `port->name' (that member was introduced in f7048b15900f ("tty: serial_core:
>> Add name field to uart_port struct").
>>
>> Cc: stable@vger.kernel.org
> I think it's safer to use:
> Cc: stable@vger.kernel.org # 4.14
> Because the stable team may miss your comment, and even if they don't, I
> think it's not their role to adapt the patch to 4.9.x (and test it !)
> IMHO, the best way is to add # 4.14 and when it's applied on 4.14.x,
> send a tested backport for 4.9.x
>
> Besides that, you can add my:
> Acked-by: Richard Genoud <richard.genoud@gmail.com>
>
> Rob, do you agree with this fix ?

Yes, one less dependency on tty struct in serial drivers is a good
thing. However, I find port->name to be a somewhat pointless addition.
Most platform drivers (which most serial drivers are) use the device
name for registering their IRQ. And now serial drivers may not even
have a tty with serdev. Using the device name would also solve your
backporting issue. But either way:

Acked-by: Rob Herring <robh@kernel.org>

Rob
diff mbox

Patch

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index e287fe8f10fc..d3189816740e 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1757,7 +1757,6 @@  static int atmel_startup(struct uart_port *port)
 {
 	struct platform_device *pdev = to_platform_device(port->dev);
 	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
-	struct tty_struct *tty = port->state->port.tty;
 	int retval;
 
 	/*
@@ -1772,8 +1771,7 @@  static int atmel_startup(struct uart_port *port)
 	 * Allocate the IRQ
 	 */
 	retval = request_irq(port->irq, atmel_interrupt,
-			IRQF_SHARED | IRQF_COND_SUSPEND,
-			tty ? tty->name : "atmel_serial", port);
+			     IRQF_SHARED | IRQF_COND_SUSPEND, port->name, port);
 	if (retval) {
 		dev_err(port->dev, "atmel_startup - Can't get irq\n");
 		return retval;