All of lore.kernel.org
 help / color / mirror / Atom feed
* Should .dtr_rts do tty_port_tty_get?
@ 2011-03-25 10:45 Jiri Slaby
  2011-03-25 10:45 ` [PATCH 1/1] TTY: serial_core, fix dtr_rts NULL dereference Jiri Slaby
  0 siblings, 1 reply; 9+ messages in thread
From: Jiri Slaby @ 2011-03-25 10:45 UTC (permalink / raw)
  To: Greg KH; +Cc: Alan Cox, linux-serial, LKML, Jiri Slaby

Hi,

I'm playing with a serial device and got a nice oops. Maybe after some
weird stty's, I don't know. But it dies in uart_dtr_rts:
        .loc 1 1535 0
        movq    (%rbx), %r13    # port_1(D)->tty, D.26746
...
        .loc 1 1494 0
        testb   $2, 224(%r13)   #, D.26746_10->flags
                    ^^^^^^^^^
                      HERE

Because r13 (port->tty) is NULL. So the question is about the principle.
Should it call tty_port_tty_get or is it a bug in the TTY layer and
uart_dtr_rts should not be called with port->tty == NULL?

I'll attach a patch which does the former as a reply to this message.

BTW only serial_core needs tty in dtr_rts.

thanks,
-- 
js
suse labs

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/1] TTY: serial_core, fix dtr_rts NULL dereference
  2011-03-25 10:45 Should .dtr_rts do tty_port_tty_get? Jiri Slaby
@ 2011-03-25 10:45 ` Jiri Slaby
  2011-03-25 11:00   ` Alan Cox
  0 siblings, 1 reply; 9+ messages in thread
From: Jiri Slaby @ 2011-03-25 10:45 UTC (permalink / raw)
  To: gregkh; +Cc: linux-serial, jirislaby, Alan Cox

Under certain circumstances uart_dtr_rts might cause an oops. It dies
because port->tty is NULL. To fix this, let's take a reference of
port->tty by tty_port_tty_get. And if it is not there already, fail
gracefully.

After all, indeed drop the reference.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Greg KH <gregkh@suse.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
---
 drivers/tty/serial/serial_core.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index d6e7240..88a0472 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1531,8 +1531,12 @@ static void uart_dtr_rts(struct tty_port *port, int onoff)
 		 * If this is the first open to succeed,
 		 * adjust things to suit.
 		 */
-		if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags))
-			uart_update_termios(port->tty, state);
+		if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags)) {
+			struct tty_struct *tty = tty_port_tty_get(port);
+			if (tty)
+				uart_update_termios(tty, state);
+			tty_kref_put(tty);
+		}
 	}
 	else
 		uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
-- 
1.7.4.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] TTY: serial_core, fix dtr_rts NULL dereference
  2011-03-25 10:45 ` [PATCH 1/1] TTY: serial_core, fix dtr_rts NULL dereference Jiri Slaby
@ 2011-03-25 11:00   ` Alan Cox
  2011-03-25 14:43     ` Jiri Slaby
  0 siblings, 1 reply; 9+ messages in thread
From: Alan Cox @ 2011-03-25 11:00 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: gregkh, linux-serial, jirislaby

On Fri, 25 Mar 2011 11:45:56 +0100
Jiri Slaby <jslaby@suse.cz> wrote:

> Under certain circumstances uart_dtr_rts might cause an oops. It dies
> because port->tty is NULL. To fix this, let's take a reference of
> port->tty by tty_port_tty_get. And if it is not there already, fail
> gracefully.

The uart helper layer assumes here (and a couple of other spots) that the
IRQ handler for the tty takes the port lock.

I think the *right* fix is probably to pass port not port->tty into the
helper in the first place but that seems to ripple into a lot of drivers.

(passing port->tty to things that then go tty->port is braindead and
causes half the mess in the tty/serial code)


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] TTY: serial_core, fix dtr_rts NULL dereference
  2011-03-25 11:00   ` Alan Cox
@ 2011-03-25 14:43     ` Jiri Slaby
  2011-03-25 20:49       ` Alan Cox
  0 siblings, 1 reply; 9+ messages in thread
From: Jiri Slaby @ 2011-03-25 14:43 UTC (permalink / raw)
  To: Alan Cox; +Cc: Jiri Slaby, gregkh, linux-serial

On 03/25/2011 12:00 PM, Alan Cox wrote:
> On Fri, 25 Mar 2011 11:45:56 +0100
> Jiri Slaby <jslaby@suse.cz> wrote:
> 
>> Under certain circumstances uart_dtr_rts might cause an oops. It dies
>> because port->tty is NULL. To fix this, let's take a reference of
>> port->tty by tty_port_tty_get. And if it is not there already, fail
>> gracefully.
> 
> The uart helper layer assumes here (and a couple of other spots) that the
> IRQ handler for the tty takes the port lock.

The oopsing path is through open BTW:
-> uart_open
 -> tty_port_block_til_ready
  -> tty_port_raise_dtr_rts
   -> uart_dtr_rts

> I think the *right* fix is probably to pass port not port->tty into the
> helper in the first place but that seems to ripple into a lot of drivers.
> 
> (passing port->tty to things that then go tty->port is braindead and
> causes half the mess in the tty/serial code)

I seem to miss the point. uart_update_termios needs tty, not port.

thanks,
-- 
js
suse labs

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] TTY: serial_core, fix dtr_rts NULL dereference
  2011-03-25 14:43     ` Jiri Slaby
@ 2011-03-25 20:49       ` Alan Cox
  2011-03-29 15:10         ` Jiri Slaby
  0 siblings, 1 reply; 9+ messages in thread
From: Alan Cox @ 2011-03-25 20:49 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: Jiri Slaby, gregkh, linux-serial

> > The uart helper layer assumes here (and a couple of other spots) that the
> > IRQ handler for the tty takes the port lock.
> 
> The oopsing path is through open BTW:
> -> uart_open
>  -> tty_port_block_til_ready
>   -> tty_port_raise_dtr_rts
>    -> uart_dtr_rts
> 
> > I think the *right* fix is probably to pass port not port->tty into the
> > helper in the first place but that seems to ripple into a lot of drivers.
> > 
> > (passing port->tty to things that then go tty->port is braindead and
> > causes half the mess in the tty/serial code)
> 
> I seem to miss the point. uart_update_termios needs tty, not port.


Actually I think it needs shooting having looked more closely

It does 3 things

1. It copies a flag across as part of a console hack. That should be done
elsewhere - eg in uart_startup

2. It sets the speed, which was already done by uart_startup

3. It goes poking around in the CBAUD flag before playing with DTR and
RTS which will have no effect as we *already* set the flags in
uart_dtr_rts

Am I missing something ?





^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/1] TTY: serial_core, fix dtr_rts NULL dereference
  2011-03-25 20:49       ` Alan Cox
@ 2011-03-29 15:10         ` Jiri Slaby
  2011-03-29 22:10           ` [PATCH 1/3] serial: core, move termios handling to uart_startup Jiri Slaby
  0 siblings, 1 reply; 9+ messages in thread
From: Jiri Slaby @ 2011-03-29 15:10 UTC (permalink / raw)
  To: Alan Cox; +Cc: Jiri Slaby, gregkh, linux-serial, Arnd Bergmann

On 03/25/2011 09:49 PM, Alan Cox wrote:
>>> The uart helper layer assumes here (and a couple of other spots) that the
>>> IRQ handler for the tty takes the port lock.
>>
>> The oopsing path is through open BTW:
>> -> uart_open
>>  -> tty_port_block_til_ready
>>   -> tty_port_raise_dtr_rts
>>    -> uart_dtr_rts
>>
>>> I think the *right* fix is probably to pass port not port->tty into the
>>> helper in the first place but that seems to ripple into a lot of drivers.
>>>
>>> (passing port->tty to things that then go tty->port is braindead and
>>> causes half the mess in the tty/serial code)
>>
>> I seem to miss the point. uart_update_termios needs tty, not port.
> 
> 
> Actually I think it needs shooting having looked more closely

Hmm, looking more closely, it's broken and should be converted to
tty_port in full. I'll take a look if I can do something about that.

> It does 3 things
> 
> 1. It copies a flag across as part of a console hack. That should be done
> elsewhere - eg in uart_startup

Perhaps.

> 2. It sets the speed, which was already done by uart_startup

Note that uart_startup is called with init_hw = 0 from uart_open. So the
speed is not set yet. So we should set the speed in uart_startup
unconditionally, I guess.

> 3. It goes poking around in the CBAUD flag before playing with DTR and
> RTS which will have no effect as we *already* set the flags in
> uart_dtr_rts

ACK

.dtr_rts did only dtr_rts when added by you. Then Arnd moved
uart_update_termios into that in 3f582b8c11.

I'll post a patch as a short-term fix shortly.

thanks,
-- 
js
suse labs

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] serial: core, move termios handling to uart_startup
  2011-03-29 15:10         ` Jiri Slaby
@ 2011-03-29 22:10           ` Jiri Slaby
  2011-03-29 22:10             ` [PATCH 2/3] serial: core, do not set DTR/RTS twice on startup Jiri Slaby
  2011-03-29 22:10             ` [PATCH 3/3] serial: core, remove uart_update_termios Jiri Slaby
  0 siblings, 2 replies; 9+ messages in thread
From: Jiri Slaby @ 2011-03-29 22:10 UTC (permalink / raw)
  To: gregkh; +Cc: linux-kernel, jirislaby, Alan Cox, Arnd Bergmann

We should not fiddle with speed and cflags in .dtr_rts hook. Actually
we might not have tty at that moment already.

So move the console cflag copy and speed setup into uart_startup.
Actually the speed setup is already there, but we need to call it
unconditionally (uart_startup is called from uart_open with hw_init =
0).

This means we move uart_change_speed before dtr/rts setup in .dtr_rts.
But this should not matter as the setup should be called after
uart_change_speed anyway.
Before:                             After:
dtr/rts setup (dtr_rts)             uart_change_speed (startup)
uart_change_speed (update_termios)  dtr/rts setup (dtr_rts)
dtr/rts setup (update_termios)      dtr/rts setup (update_termios)

The second setup will dismiss with the next patch.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Arnd Bergmann <arnd@arndb.de>
---
 drivers/tty/serial/serial_core.c |   24 +++++++++---------------
 1 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index d6e7240..47657cf 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -172,12 +172,16 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, int in
 
 	retval = uport->ops->startup(uport);
 	if (retval == 0) {
-		if (init_hw) {
-			/*
-			 * Initialise the hardware port settings.
-			 */
-			uart_change_speed(tty, state, NULL);
+		if (uart_console(uport) && uport->cons->cflag) {
+			tty->termios->c_cflag = uport->cons->cflag;
+			uport->cons->cflag = 0;
+		}
+		/*
+		 * Initialise the hardware port settings.
+		 */
+		uart_change_speed(tty, state, NULL);
 
+		if (init_hw) {
 			/*
 			 * Setup the RTS and DTR signals once the
 			 * port is open and ready to respond.
@@ -1481,11 +1485,6 @@ static void uart_update_termios(struct tty_struct *tty,
 {
 	struct uart_port *port = state->uart_port;
 
-	if (uart_console(port) && port->cons->cflag) {
-		tty->termios->c_cflag = port->cons->cflag;
-		port->cons->cflag = 0;
-	}
-
 	/*
 	 * If the device failed to grab its irq resources,
 	 * or some other error occurred, don't try to talk
@@ -1493,11 +1492,6 @@ static void uart_update_termios(struct tty_struct *tty,
 	 */
 	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
 		/*
-		 * Make termios settings take effect.
-		 */
-		uart_change_speed(tty, state, NULL);
-
-		/*
 		 * And finally enable the RTS and DTR signals.
 		 */
 		if (tty->termios->c_cflag & CBAUD)
-- 
1.7.4.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/3] serial: core, do not set DTR/RTS twice on startup
  2011-03-29 22:10           ` [PATCH 1/3] serial: core, move termios handling to uart_startup Jiri Slaby
@ 2011-03-29 22:10             ` Jiri Slaby
  2011-03-29 22:10             ` [PATCH 3/3] serial: core, remove uart_update_termios Jiri Slaby
  1 sibling, 0 replies; 9+ messages in thread
From: Jiri Slaby @ 2011-03-29 22:10 UTC (permalink / raw)
  To: gregkh; +Cc: linux-kernel, jirislaby, Alan Cox, Arnd Bergmann

In .dtr_rts we do:
  uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS)
and call uart_update_termios. It does:
  uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS)
once again. As the only callsite of uart_update_termios is .dtr_rts,
remove the uart_set_mctrl from uart_update_termios to not set it twice.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Arnd Bergmann <arnd@arndb.de>
---
 drivers/tty/serial/serial_core.c |   14 --------------
 1 files changed, 0 insertions(+), 14 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 47657cf..3aae8ed 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1483,20 +1483,6 @@ static void uart_hangup(struct tty_struct *tty)
 static void uart_update_termios(struct tty_struct *tty,
 						struct uart_state *state)
 {
-	struct uart_port *port = state->uart_port;
-
-	/*
-	 * If the device failed to grab its irq resources,
-	 * or some other error occurred, don't try to talk
-	 * to the port hardware.
-	 */
-	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
-		/*
-		 * And finally enable the RTS and DTR signals.
-		 */
-		if (tty->termios->c_cflag & CBAUD)
-			uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-	}
 }
 
 static int uart_carrier_raised(struct tty_port *port)
-- 
1.7.4.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/3] serial: core, remove uart_update_termios
  2011-03-29 22:10           ` [PATCH 1/3] serial: core, move termios handling to uart_startup Jiri Slaby
  2011-03-29 22:10             ` [PATCH 2/3] serial: core, do not set DTR/RTS twice on startup Jiri Slaby
@ 2011-03-29 22:10             ` Jiri Slaby
  1 sibling, 0 replies; 9+ messages in thread
From: Jiri Slaby @ 2011-03-29 22:10 UTC (permalink / raw)
  To: gregkh; +Cc: linux-kernel, jirislaby, Alan Cox, Arnd Bergmann

Now, uart_update_termios is empty, so it's time to remove it. We no
longer need a live tty in .dtr_rts. So this should prune all the bugs
where tty is zeroed in port->tty during tty_port_block_til_ready.

There is one thing to note. We don't set ASYNC_NORMAL_ACTIVE now. It's
because this is done already in tty_port_block_til_ready.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Arnd Bergmann <arnd@arndb.de>
---
 drivers/tty/serial/serial_core.c |   25 +------------------------
 1 files changed, 1 insertions(+), 24 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 3aae8ed..d4bd465 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1470,21 +1470,6 @@ static void uart_hangup(struct tty_struct *tty)
 	mutex_unlock(&port->mutex);
 }
 
-/**
- *	uart_update_termios	-	update the terminal hw settings
- *	@tty: tty associated with UART
- *	@state: UART to update
- *
- *	Copy across the serial console cflag setting into the termios settings
- *	for the initial open of the port.  This allows continuity between the
- *	kernel settings, and the settings init adopts when it opens the port
- *	for the first time.
- */
-static void uart_update_termios(struct tty_struct *tty,
-						struct uart_state *state)
-{
-}
-
 static int uart_carrier_raised(struct tty_port *port)
 {
 	struct uart_state *state = container_of(port, struct uart_state, port);
@@ -1504,16 +1489,8 @@ static void uart_dtr_rts(struct tty_port *port, int onoff)
 	struct uart_state *state = container_of(port, struct uart_state, port);
 	struct uart_port *uport = state->uart_port;
 
-	if (onoff) {
+	if (onoff)
 		uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
-
-		/*
-		 * If this is the first open to succeed,
-		 * adjust things to suit.
-		 */
-		if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags))
-			uart_update_termios(port->tty, state);
-	}
 	else
 		uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
 }
-- 
1.7.4.1



^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2011-03-29 22:11 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-25 10:45 Should .dtr_rts do tty_port_tty_get? Jiri Slaby
2011-03-25 10:45 ` [PATCH 1/1] TTY: serial_core, fix dtr_rts NULL dereference Jiri Slaby
2011-03-25 11:00   ` Alan Cox
2011-03-25 14:43     ` Jiri Slaby
2011-03-25 20:49       ` Alan Cox
2011-03-29 15:10         ` Jiri Slaby
2011-03-29 22:10           ` [PATCH 1/3] serial: core, move termios handling to uart_startup Jiri Slaby
2011-03-29 22:10             ` [PATCH 2/3] serial: core, do not set DTR/RTS twice on startup Jiri Slaby
2011-03-29 22:10             ` [PATCH 3/3] serial: core, remove uart_update_termios Jiri Slaby

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.