public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Remove race between con_open and con_close
@ 2005-08-27 23:40 Paul Mackerras
  2005-08-27 23:56 ` Antonino A. Daplas
  2005-08-27 23:58 ` Russell King
  0 siblings, 2 replies; 4+ messages in thread
From: Paul Mackerras @ 2005-08-27 23:40 UTC (permalink / raw)
  To: torvalds, akpm, dwmw2, Alan Cox; +Cc: linux-kernel

I have a laptop (G3 powerbook) which will pretty reliably hit a race
between con_open and con_close late in the boot process and oops in
vt_ioctl due to tty->driver_data being NULL.

What happens is this: process A opens /dev/tty6; it comes into
con_open() (drivers/char/vt.c) and assign a non-NULL value to
tty->driver_data.  Then process A closes that and concurrently process
B opens /dev/tty6.  Process A gets through con_close() and clears
tty->driver_data, since tty->count == 1.  However, before process A
can decrement tty->count, we switch to process B (e.g. at the
down(&tty_sem) call at drivers/char/tty_io.c line 1626).

So process B gets to run and comes into con_open with tty->count == 2,
as tty->count is incremented (in init_dev) before con_open is called.
Because tty->count != 1, we don't set tty->driver_data.  Then when the
process tries to do anything with that fd, it oopses.

The simple and effective fix for this is to test tty->driver_data
rather than tty->count in con_open.  The testing and setting of
tty->driver_data is serialized with respect to the clearing of
tty->driver_data in con_close by the console_sem.  We can't get a
situation where con_open sees tty->driver_data != NULL and then
con_close on a different fd clears tty->driver_data, because
tty->count is incremented before con_open is called.  Thus this patch
eliminates the race, and in fact with this patch my laptop doesn't
oops.

Could this go into 2.6.13 please?

Signed-off-by: Paul Mackerras <paulus@samba.org>

diff -urN linux-2.6/drivers/char/vt.c pmac-2.6/drivers/char/vt.c
--- linux-2.6/drivers/char/vt.c	2005-07-17 10:59:52.000000000 +1000
+++ pmac-2.6/drivers/char/vt.c	2005-08-27 22:59:36.000000000 +1000
@@ -2433,7 +2433,7 @@
 	int ret = 0;
 
 	acquire_console_sem();
-	if (tty->count == 1) {
+	if (tty->driver_data == NULL) {
 		ret = vc_allocate(currcons);
 		if (ret == 0) {
 			struct vc_data *vc = vc_cons[currcons].d;

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

* Re: [PATCH] Remove race between con_open and con_close
  2005-08-27 23:40 [PATCH] Remove race between con_open and con_close Paul Mackerras
@ 2005-08-27 23:56 ` Antonino A. Daplas
  2005-08-27 23:58 ` Russell King
  1 sibling, 0 replies; 4+ messages in thread
From: Antonino A. Daplas @ 2005-08-27 23:56 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: torvalds, akpm, dwmw2, Alan Cox, linux-kernel

Paul Mackerras wrote:
> I have a laptop (G3 powerbook) which will pretty reliably hit a race
> between con_open and con_close late in the boot process and oops in
> vt_ioctl due to tty->driver_data being NULL.
> 
> What happens is this: process A opens /dev/tty6; it comes into
> con_open() (drivers/char/vt.c) and assign a non-NULL value to
> tty->driver_data.  Then process A closes that and concurrently process
> B opens /dev/tty6.  Process A gets through con_close() and clears
> tty->driver_data, since tty->count == 1.  However, before process A
> can decrement tty->count, we switch to process B (e.g. at the
> down(&tty_sem) call at drivers/char/tty_io.c line 1626).
> 
> So process B gets to run and comes into con_open with tty->count == 2,
> as tty->count is incremented (in init_dev) before con_open is called.
> Because tty->count != 1, we don't set tty->driver_data.  Then when the
> process tries to do anything with that fd, it oopses.
> 
> The simple and effective fix for this is to test tty->driver_data
> rather than tty->count in con_open.  The testing and setting of
> tty->driver_data is serialized with respect to the clearing of
> tty->driver_data in con_close by the console_sem.  We can't get a
> situation where con_open sees tty->driver_data != NULL and then
> con_close on a different fd clears tty->driver_data, because
> tty->count is incremented before con_open is called.  Thus this patch
> eliminates the race, and in fact with this patch my laptop doesn't
> oops.
> 
> Could this go into 2.6.13 please?

I agree this should go to 2.6.13.  Though you've been beaten to the punch
by Steven Rostedt.  This is already in the mm tree.

http://marc.theaimsgroup.com/?l=linux-kernel&m=112450820432121&w=2

Tony

> 
> Signed-off-by: Paul Mackerras <paulus@samba.org>
> 
> diff -urN linux-2.6/drivers/char/vt.c pmac-2.6/drivers/char/vt.c
> --- linux-2.6/drivers/char/vt.c	2005-07-17 10:59:52.000000000 +1000
> +++ pmac-2.6/drivers/char/vt.c	2005-08-27 22:59:36.000000000 +1000
> @@ -2433,7 +2433,7 @@
>  	int ret = 0;
>  
>  	acquire_console_sem();
> -	if (tty->count == 1) {
> +	if (tty->driver_data == NULL) {
>  		ret = vc_allocate(currcons);
>  		if (ret == 0) {
>  			struct vc_data *vc = vc_cons[currcons].d;
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 


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

* Re: [PATCH] Remove race between con_open and con_close
  2005-08-27 23:40 [PATCH] Remove race between con_open and con_close Paul Mackerras
  2005-08-27 23:56 ` Antonino A. Daplas
@ 2005-08-27 23:58 ` Russell King
  2005-08-28  0:41   ` Paul Mackerras
  1 sibling, 1 reply; 4+ messages in thread
From: Russell King @ 2005-08-27 23:58 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: torvalds, akpm, dwmw2, Alan Cox, linux-kernel

On Sun, Aug 28, 2005 at 09:40:01AM +1000, Paul Mackerras wrote:
> I have a laptop (G3 powerbook) which will pretty reliably hit a race
> between con_open and con_close late in the boot process and oops in
> vt_ioctl due to tty->driver_data being NULL.

Have you looked at how serial_core handles this kind of problem in
its open and close methods?  I put some comments in there because
of the issue, after thinking about it fairly carefully.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core

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

* Re: [PATCH] Remove race between con_open and con_close
  2005-08-27 23:58 ` Russell King
@ 2005-08-28  0:41   ` Paul Mackerras
  0 siblings, 0 replies; 4+ messages in thread
From: Paul Mackerras @ 2005-08-28  0:41 UTC (permalink / raw)
  To: Russell King; +Cc: torvalds, akpm, dwmw2, Alan Cox, linux-kernel

Russell King writes:

> Have you looked at how serial_core handles this kind of problem in
> its open and close methods?  I put some comments in there because
> of the issue, after thinking about it fairly carefully.

Yes, albeit briefly; the problem in con_open is much simpler because
we never need to block.

Paul.

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

end of thread, other threads:[~2005-08-28  0:41 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-08-27 23:40 [PATCH] Remove race between con_open and con_close Paul Mackerras
2005-08-27 23:56 ` Antonino A. Daplas
2005-08-27 23:58 ` Russell King
2005-08-28  0:41   ` Paul Mackerras

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox