Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ae289dc

Browse files
heicarstMartin Schwidefsky
authored andcommittedNov 15, 2012
s390/3215: fix tty close handling
The 3215 console always has the RAW3215_FIXED flag set, which causes raw3215_shutdown() not to wait for outstanding I/O requests if an attached tty gets closed. The flag however can be simply removed, so we can guarantee that all requests belonging to the tty have been processed when the tty is closed. However the tasklet that belongs to the 3215 device may be scheduled even if there is no tty attached anymore, since we have a race between console and tty processing. Thefore unconditional tty_wakekup() in raw3215_wakeup() can cause the following NULL pointer dereference: 3.465368 Unable to handle kernel pointer dereference at virtual kernel address (null) 3.465448 Oops: 0004 #1 SMP 3.465454 Modules linked in: 3.465459 CPU: 1 Not tainted 3.6.0 #1 3.465462 Process swapper/1 (pid: 0, task: 000000003ffa4428, ksp: 000000003ffb7ce0) 3.465466 Krnl PSW : 0404100180000000 0000000000162f86 (__wake_up+0x46/0xb8) 3.465480 R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:0 CC:1 PM:0 EA:3 Krnl GPRS: fffffffffffffffe 0000000000000000 0000000000000160 0000000000000001 3.465492 0000000000000001 0000000000000004 0000000000000004 000000000096b490 3.465499 0000000000000001 0000000000000100 0000000000000001 0000000000000001 3.465506 070000003fc87d60 0000000000000160 000000003fc87d68 000000003fc87d00 3.465526 Krnl Code: 0000000000162f76: e3c0f0a80004 lg %r12,168(%r15) 0000000000162f7c: 58000370 l %r0,880 #0000000000162f80: c007ffffffff00 xilf %r0,4294967295 >0000000000162f86: ba102000 cs %r1,%r0,0(%r2) 0000000000162f8a: 1211 ltr %r1,%r1 0000000000162f8c: a774002f brc 7,162fea 0000000000162f90: b904002d lgr %r2,%r13 0000000000162f94: b904003a lgr %r3,%r10 3.465597 Call Trace: 3.465599 (<0400000000000000> 0x400000000000000) 3.465602 <000000000048c77e> raw3215_wakeup+0x2e/0x40 3.465607 <0000000000134d66> tasklet_action+0x96/0x168 3.465612 <000000000013423c> __do_softirq+0xd8/0x21c 3.465615 <0000000000134678> irq_exit+0xa8/0xac 3.465617 <000000000046c232> do_IRQ+0x182/0x248 3.465621 <00000000005c8296> io_return+0x0/0x8 3.465625 <00000000005c7cac> vtime_stop_cpu+0x4c/0xb8 3.465629 (<0000000000194e06> tick_nohz_idle_enter+0x4e/0x74) 3.465633 <0000000000104760> cpu_idle+0x170/0x184 3.465636 <00000000005b5182> smp_start_secondary+0xd6/0xe0 3.465641 <00000000005c86be> restart_int_handler+0x56/0x6c 3.465643 <0000000000000000> 0x0 3.465645 Last Breaking-Event-Address: 3.465647 <0000000000403136> tty_wakeup+0x46/0x98 3.465652 3.465654 Kernel panic - not syncing: Fatal exception in interrupt 01: HCPGIR450W CP entered; disabled wait PSW 00020001 80000000 00000000 0010F63C The easiest solution is simply to check if tty is NULL in the tasklet. If it is NULL nothing is to do (no tty attached), otherwise tty_wakeup() can be called, since we hold a reference to the tty. This is not nice... but it is a small patch and it works. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
1 parent 4bffbb3 commit ae289dc

File tree

1 file changed

+5
-7
lines changed

1 file changed

+5
-7
lines changed
 

‎drivers/s390/char/con3215.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
#define RAW3215_NR_CCWS 3
4545
#define RAW3215_TIMEOUT HZ/10 /* time for delayed output */
4646

47-
#define RAW3215_FIXED 1 /* 3215 console device is not be freed */
4847
#define RAW3215_WORKING 4 /* set if a request is being worked on */
4948
#define RAW3215_THROTTLED 8 /* set if reading is disabled */
5049
#define RAW3215_STOPPED 16 /* set if writing is disabled */
@@ -339,8 +338,10 @@ static void raw3215_wakeup(unsigned long data)
339338
struct tty_struct *tty;
340339

341340
tty = tty_port_tty_get(&raw->port);
342-
tty_wakeup(tty);
343-
tty_kref_put(tty);
341+
if (tty) {
342+
tty_wakeup(tty);
343+
tty_kref_put(tty);
344+
}
344345
}
345346

346347
/*
@@ -629,8 +630,7 @@ static void raw3215_shutdown(struct raw3215_info *raw)
629630
DECLARE_WAITQUEUE(wait, current);
630631
unsigned long flags;
631632

632-
if (!(raw->port.flags & ASYNC_INITIALIZED) ||
633-
(raw->flags & RAW3215_FIXED))
633+
if (!(raw->port.flags & ASYNC_INITIALIZED))
634634
return;
635635
/* Wait for outstanding requests, then free irq */
636636
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
@@ -926,8 +926,6 @@ static int __init con3215_init(void)
926926
dev_set_drvdata(&cdev->dev, raw);
927927
cdev->handler = raw3215_irq;
928928

929-
raw->flags |= RAW3215_FIXED;
930-
931929
/* Request the console irq */
932930
if (raw3215_startup(raw) != 0) {
933931
raw3215_free_info(raw);

0 commit comments

Comments
 (0)
Please sign in to comment.