aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Slaby <jslaby@suse.cz>2012-04-13 04:31:32 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-13 13:54:43 -0400
commita2f892060f174e5f90041167ca00eb9e68badcb8 (patch)
treedaf87a58266da05e2e8a3f06538df2cfd360d3bc
parent59d59b0600e541b4e94b891148c92f2e2d18f7c0 (diff)
TTY: hvc, fix TTY refcounting
A -next commit "TTY: HVC, use tty from tty_port" switched the driver to use tty_port helper for tty refcounting. But it omitted to remove manual tty refcounting from open, close and hangup. So now we are getting random crashes caused by use-after-free: Unable to handle kernel paging request for data at address 0xc0000003f9d550 Faulting instruction address: 0xc0000000001b7f40 Oops: Kernel access of bad area, sig: 11 [#1] ... NIP: c0000000001b7f40 LR: c0000000001b7f14 CTR: c0000000000e04f0 ... NIP [c0000000001b7f40] .__kmalloc+0x70/0x230 LR [c0000000001b7f14] .__kmalloc+0x44/0x230 Call Trace: [c0000003f68bf930] [c0000003f68bf9b0] 0xc0000003f68bf9b0 (unreliable) [c0000003f68bf9e0] [c0000000001e5424] .alloc_fdmem+0x24/0x70 [c0000003f68bfa60] [c0000000001e54f8] .alloc_fdtable+0x88/0x130 [c0000003f68bfaf0] [c0000000001e5924] .dup_fd+0x384/0x450 [c0000003f68bfbd0] [c00000000009a310] .copy_process+0x880/0x11d0 [c0000003f68bfcd0] [c00000000009aee0] .do_fork+0x70/0x400 [c0000003f68bfdc0] [c0000000000141c4] .sys_clone+0x54/0x70 [c0000003f68bfe30] [c000000000009aa0] .ppc_clone+0x8/0xc Fix that by complete removal of tty_kref_get/put in open/close/hangup paths. Signed-off-by: Jiri Slaby <jslaby@suse.cz> Reported-and-tested-by: Michael Neuling <mikey@neuling.org> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Cc: ppc-dev <linuxppc-dev@lists.ozlabs.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/hvc/hvc_console.c5
1 files changed, 0 insertions, 5 deletions
diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 6c45cbf3fc91..2d691eb7c40a 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -317,8 +317,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
317 /* Check and then increment for fast path open. */ 317 /* Check and then increment for fast path open. */
318 if (hp->port.count++ > 0) { 318 if (hp->port.count++ > 0) {
319 spin_unlock_irqrestore(&hp->port.lock, flags); 319 spin_unlock_irqrestore(&hp->port.lock, flags);
320 /* FIXME why taking a reference here? */
321 tty_kref_get(tty);
322 hvc_kick(); 320 hvc_kick();
323 return 0; 321 return 0;
324 } /* else count == 0 */ 322 } /* else count == 0 */
@@ -338,7 +336,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
338 */ 336 */
339 if (rc) { 337 if (rc) {
340 tty_port_tty_set(&hp->port, NULL); 338 tty_port_tty_set(&hp->port, NULL);
341 tty_kref_put(tty);
342 tty->driver_data = NULL; 339 tty->driver_data = NULL;
343 tty_port_put(&hp->port); 340 tty_port_put(&hp->port);
344 printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc); 341 printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
@@ -393,7 +390,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
393 spin_unlock_irqrestore(&hp->port.lock, flags); 390 spin_unlock_irqrestore(&hp->port.lock, flags);
394 } 391 }
395 392
396 tty_kref_put(tty);
397 tty_port_put(&hp->port); 393 tty_port_put(&hp->port);
398} 394}
399 395
@@ -433,7 +429,6 @@ static void hvc_hangup(struct tty_struct *tty)
433 429
434 while(temp_open_count) { 430 while(temp_open_count) {
435 --temp_open_count; 431 --temp_open_count;
436 tty_kref_put(tty);
437 tty_port_put(&hp->port); 432 tty_port_put(&hp->port);
438 } 433 }
439} 434}