Commit b9b61107 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] First cut at setsid/tty locking

Use the existing "tty_sem" to protect against the process tty changes
too.
parent 0b064cdf
...@@ -918,9 +918,11 @@ void disassociate_ctty(int on_exit) ...@@ -918,9 +918,11 @@ void disassociate_ctty(int on_exit)
lock_kernel(); lock_kernel();
down(&tty_sem);
tty = current->signal->tty; tty = current->signal->tty;
if (tty) { if (tty) {
tty_pgrp = tty->pgrp; tty_pgrp = tty->pgrp;
up(&tty_sem);
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty); tty_vhangup(tty);
} else { } else {
...@@ -928,6 +930,7 @@ void disassociate_ctty(int on_exit) ...@@ -928,6 +930,7 @@ void disassociate_ctty(int on_exit)
kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit);
kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit);
} }
up(&tty_sem);
unlock_kernel(); unlock_kernel();
return; return;
} }
...@@ -937,15 +940,19 @@ void disassociate_ctty(int on_exit) ...@@ -937,15 +940,19 @@ void disassociate_ctty(int on_exit)
kill_pg(tty_pgrp, SIGCONT, on_exit); kill_pg(tty_pgrp, SIGCONT, on_exit);
} }
/* Must lock changes to tty_old_pgrp */
down(&tty_sem);
current->signal->tty_old_pgrp = 0; current->signal->tty_old_pgrp = 0;
tty->session = 0; tty->session = 0;
tty->pgrp = -1; tty->pgrp = -1;
/* Now clear signal->tty under the lock */
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
do_each_task_pid(current->signal->session, PIDTYPE_SID, p) { do_each_task_pid(current->signal->session, PIDTYPE_SID, p) {
p->signal->tty = NULL; p->signal->tty = NULL;
} while_each_task_pid(current->signal->session, PIDTYPE_SID, p); } while_each_task_pid(current->signal->session, PIDTYPE_SID, p);
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
up(&tty_sem);
unlock_kernel(); unlock_kernel();
} }
...@@ -1172,12 +1179,6 @@ static int init_dev(struct tty_driver *driver, int idx, ...@@ -1172,12 +1179,6 @@ static int init_dev(struct tty_driver *driver, int idx,
struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
int retval=0; int retval=0;
/*
* Check whether we need to acquire the tty semaphore to avoid
* race conditions. For now, play it safe.
*/
down(&tty_sem);
/* check whether we're reopening an existing tty */ /* check whether we're reopening an existing tty */
if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
tty = devpts_get_tty(idx); tty = devpts_get_tty(idx);
...@@ -1366,7 +1367,6 @@ static int init_dev(struct tty_driver *driver, int idx, ...@@ -1366,7 +1367,6 @@ static int init_dev(struct tty_driver *driver, int idx,
/* All paths come through here to release the semaphore */ /* All paths come through here to release the semaphore */
end_init: end_init:
up(&tty_sem);
return retval; return retval;
/* Release locally allocated memory ... nothing placed in slots */ /* Release locally allocated memory ... nothing placed in slots */
...@@ -1562,9 +1562,14 @@ static void release_dev(struct file * filp) ...@@ -1562,9 +1562,14 @@ static void release_dev(struct file * filp)
* each iteration we avoid any problems. * each iteration we avoid any problems.
*/ */
while (1) { while (1) {
/* Guard against races with tty->count changes elsewhere and
opens on /dev/tty */
down(&tty_sem);
tty_closing = tty->count <= 1; tty_closing = tty->count <= 1;
o_tty_closing = o_tty && o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0)); (o_tty->count <= (pty_master ? 1 : 0));
up(&tty_sem);
do_sleep = 0; do_sleep = 0;
if (tty_closing) { if (tty_closing) {
...@@ -1600,6 +1605,8 @@ static void release_dev(struct file * filp) ...@@ -1600,6 +1605,8 @@ static void release_dev(struct file * filp)
* both sides, and we've completed the last operation that could * both sides, and we've completed the last operation that could
* block, so it's safe to proceed with closing. * block, so it's safe to proceed with closing.
*/ */
down(&tty_sem);
if (pty_master) { if (pty_master) {
if (--o_tty->count < 0) { if (--o_tty->count < 0) {
printk(KERN_WARNING "release_dev: bad pty slave count " printk(KERN_WARNING "release_dev: bad pty slave count "
...@@ -1613,7 +1620,8 @@ static void release_dev(struct file * filp) ...@@ -1613,7 +1620,8 @@ static void release_dev(struct file * filp)
tty->count, tty_name(tty, buf)); tty->count, tty_name(tty, buf));
tty->count = 0; tty->count = 0;
} }
up(&tty_sem);
/* /*
* We've decremented tty->count, so we need to remove this file * We've decremented tty->count, so we need to remove this file
* descriptor off the tty->tty_files list; this serves two * descriptor off the tty->tty_files list; this serves two
...@@ -1760,10 +1768,14 @@ static int tty_open(struct inode * inode, struct file * filp) ...@@ -1760,10 +1768,14 @@ static int tty_open(struct inode * inode, struct file * filp)
noctty = filp->f_flags & O_NOCTTY; noctty = filp->f_flags & O_NOCTTY;
index = -1; index = -1;
retval = 0; retval = 0;
down(&tty_sem);
if (device == MKDEV(TTYAUX_MAJOR,0)) { if (device == MKDEV(TTYAUX_MAJOR,0)) {
if (!current->signal->tty) if (!current->signal->tty) {
up(&tty_sem);
return -ENXIO; return -ENXIO;
}
driver = current->signal->tty->driver; driver = current->signal->tty->driver;
index = current->signal->tty->index; index = current->signal->tty->index;
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
...@@ -1788,14 +1800,18 @@ static int tty_open(struct inode * inode, struct file * filp) ...@@ -1788,14 +1800,18 @@ static int tty_open(struct inode * inode, struct file * filp)
noctty = 1; noctty = 1;
goto got_driver; goto got_driver;
} }
up(&tty_sem);
return -ENODEV; return -ENODEV;
} }
driver = get_tty_driver(device, &index); driver = get_tty_driver(device, &index);
if (!driver) if (!driver) {
up(&tty_sem);
return -ENODEV; return -ENODEV;
}
got_driver: got_driver:
retval = init_dev(driver, index, &tty); retval = init_dev(driver, index, &tty);
up(&tty_sem);
if (retval) if (retval)
return retval; return retval;
...@@ -1881,7 +1897,10 @@ static int ptmx_open(struct inode * inode, struct file * filp) ...@@ -1881,7 +1897,10 @@ static int ptmx_open(struct inode * inode, struct file * filp)
} }
up(&allocated_ptys_lock); up(&allocated_ptys_lock);
down(&tty_sem);
retval = init_dev(ptm_driver, index, &tty); retval = init_dev(ptm_driver, index, &tty);
up(&tty_sem);
if (retval) if (retval)
goto out; goto out;
......
...@@ -332,7 +332,9 @@ void daemonize(const char *name, ...) ...@@ -332,7 +332,9 @@ void daemonize(const char *name, ...)
exit_mm(current); exit_mm(current);
set_special_pids(1, 1); set_special_pids(1, 1);
down(&tty_sem);
current->signal->tty = NULL; current->signal->tty = NULL;
up(&tty_sem);
/* Block and flush all signals */ /* Block and flush all signals */
sigfillset(&blocked); sigfillset(&blocked);
......
...@@ -1075,6 +1075,7 @@ asmlinkage long sys_setsid(void) ...@@ -1075,6 +1075,7 @@ asmlinkage long sys_setsid(void)
if (!thread_group_leader(current)) if (!thread_group_leader(current))
return -EINVAL; return -EINVAL;
down(&tty_sem);
write_lock_irq(&tasklist_lock); write_lock_irq(&tasklist_lock);
pid = find_pid(PIDTYPE_PGID, current->pid); pid = find_pid(PIDTYPE_PGID, current->pid);
...@@ -1088,6 +1089,7 @@ asmlinkage long sys_setsid(void) ...@@ -1088,6 +1089,7 @@ asmlinkage long sys_setsid(void)
err = process_group(current); err = process_group(current);
out: out:
write_unlock_irq(&tasklist_lock); write_unlock_irq(&tasklist_lock);
up(&tty_sem);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment