diff options
-rw-r--r-- | arch/sparc64/solaris/misc.c | 4 | ||||
-rw-r--r-- | arch/um/kernel/exec.c | 7 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 237 | ||||
-rw-r--r-- | drivers/s390/char/fs3270.c | 12 | ||||
-rw-r--r-- | fs/dquot.c | 14 | ||||
-rw-r--r-- | fs/open.c | 1 | ||||
-rw-r--r-- | include/linux/tty.h | 11 | ||||
-rw-r--r-- | kernel/acct.c | 9 | ||||
-rw-r--r-- | kernel/auditsc.c | 2 | ||||
-rw-r--r-- | kernel/exit.c | 4 | ||||
-rw-r--r-- | kernel/sys.c | 6 | ||||
-rw-r--r-- | security/selinux/hooks.c | 11 |
12 files changed, 186 insertions, 132 deletions
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index 9ed997982f8d..e84241d5f7f4 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c | |||
@@ -423,9 +423,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid) | |||
423 | Solaris setpgrp and setsid? */ | 423 | Solaris setpgrp and setsid? */ |
424 | ret = sys_setpgid(0, 0); | 424 | ret = sys_setpgid(0, 0); |
425 | if (ret) return ret; | 425 | if (ret) return ret; |
426 | mutex_lock(&tty_mutex); | 426 | proc_clear_tty(current); |
427 | current->signal->tty = NULL; | ||
428 | mutex_unlock(&tty_mutex); | ||
429 | return process_group(current); | 427 | return process_group(current); |
430 | } | 428 | } |
431 | case 2: /* getsid */ | 429 | case 2: /* getsid */ |
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 0561c43b4685..8d56ec6cca79 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c | |||
@@ -39,12 +39,13 @@ static long execve1(char *file, char __user * __user *argv, | |||
39 | char __user *__user *env) | 39 | char __user *__user *env) |
40 | { | 40 | { |
41 | long error; | 41 | long error; |
42 | struct tty_struct *tty; | ||
42 | 43 | ||
43 | #ifdef CONFIG_TTY_LOG | 44 | #ifdef CONFIG_TTY_LOG |
44 | mutex_lock(&tty_mutex); | 45 | mutex_lock(&tty_mutex); |
45 | task_lock(current); /* FIXME: is this needed ? */ | 46 | tty = get_current_tty(); |
46 | log_exec(argv, current->signal->tty); | 47 | if (tty) |
47 | task_unlock(current); | 48 | log_exec(argv, tty); |
48 | mutex_unlock(&tty_mutex); | 49 | mutex_unlock(&tty_mutex); |
49 | #endif | 50 | #endif |
50 | error = do_execve(file, argv, env, ¤t->thread.regs); | 51 | error = do_execve(file, argv, env, ¤t->thread.regs); |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index b3cfc8bc613c..0c856a6f3677 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -126,7 +126,7 @@ EXPORT_SYMBOL(tty_std_termios); | |||
126 | 126 | ||
127 | LIST_HEAD(tty_drivers); /* linked list of tty drivers */ | 127 | LIST_HEAD(tty_drivers); /* linked list of tty drivers */ |
128 | 128 | ||
129 | /* Semaphore to protect creating and releasing a tty. This is shared with | 129 | /* Mutex to protect creating and releasing a tty. This is shared with |
130 | vt.c for deeply disgusting hack reasons */ | 130 | vt.c for deeply disgusting hack reasons */ |
131 | DEFINE_MUTEX(tty_mutex); | 131 | DEFINE_MUTEX(tty_mutex); |
132 | EXPORT_SYMBOL(tty_mutex); | 132 | EXPORT_SYMBOL(tty_mutex); |
@@ -250,7 +250,7 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) | |||
250 | "!= #fd's(%d) in %s\n", | 250 | "!= #fd's(%d) in %s\n", |
251 | tty->name, tty->count, count, routine); | 251 | tty->name, tty->count, count, routine); |
252 | return count; | 252 | return count; |
253 | } | 253 | } |
254 | #endif | 254 | #endif |
255 | return 0; | 255 | return 0; |
256 | } | 256 | } |
@@ -259,18 +259,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) | |||
259 | * Tty buffer allocation management | 259 | * Tty buffer allocation management |
260 | */ | 260 | */ |
261 | 261 | ||
262 | |||
263 | /** | ||
264 | * tty_buffer_free_all - free buffers used by a tty | ||
265 | * @tty: tty to free from | ||
266 | * | ||
267 | * Remove all the buffers pending on a tty whether queued with data | ||
268 | * or in the free ring. Must be called when the tty is no longer in use | ||
269 | * | ||
270 | * Locking: none | ||
271 | */ | ||
272 | |||
273 | |||
274 | /** | 262 | /** |
275 | * tty_buffer_free_all - free buffers used by a tty | 263 | * tty_buffer_free_all - free buffers used by a tty |
276 | * @tty: tty to free from | 264 | * @tty: tty to free from |
@@ -614,7 +602,7 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); | |||
614 | * they are not on hot paths so a little discipline won't do | 602 | * they are not on hot paths so a little discipline won't do |
615 | * any harm. | 603 | * any harm. |
616 | * | 604 | * |
617 | * Locking: takes termios_sem | 605 | * Locking: takes termios_mutex |
618 | */ | 606 | */ |
619 | 607 | ||
620 | static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | 608 | static void tty_set_termios_ldisc(struct tty_struct *tty, int num) |
@@ -915,7 +903,7 @@ static void tty_ldisc_enable(struct tty_struct *tty) | |||
915 | * context. | 903 | * context. |
916 | * | 904 | * |
917 | * Locking: takes tty_ldisc_lock. | 905 | * Locking: takes tty_ldisc_lock. |
918 | * called functions take termios_sem | 906 | * called functions take termios_mutex |
919 | */ | 907 | */ |
920 | 908 | ||
921 | static int tty_set_ldisc(struct tty_struct *tty, int ldisc) | 909 | static int tty_set_ldisc(struct tty_struct *tty, int ldisc) |
@@ -1267,12 +1255,12 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush); | |||
1267 | * | 1255 | * |
1268 | * Locking: | 1256 | * Locking: |
1269 | * BKL | 1257 | * BKL |
1270 | * redirect lock for undoing redirection | 1258 | * redirect lock for undoing redirection |
1271 | * file list lock for manipulating list of ttys | 1259 | * file list lock for manipulating list of ttys |
1272 | * tty_ldisc_lock from called functions | 1260 | * tty_ldisc_lock from called functions |
1273 | * termios_sem resetting termios data | 1261 | * termios_mutex resetting termios data |
1274 | * tasklist_lock to walk task list for hangup event | 1262 | * tasklist_lock to walk task list for hangup event |
1275 | * | 1263 | * ->siglock to protect ->signal/->sighand |
1276 | */ | 1264 | */ |
1277 | static void do_tty_hangup(struct work_struct *work) | 1265 | static void do_tty_hangup(struct work_struct *work) |
1278 | { | 1266 | { |
@@ -1354,14 +1342,18 @@ static void do_tty_hangup(struct work_struct *work) | |||
1354 | read_lock(&tasklist_lock); | 1342 | read_lock(&tasklist_lock); |
1355 | if (tty->session > 0) { | 1343 | if (tty->session > 0) { |
1356 | do_each_task_pid(tty->session, PIDTYPE_SID, p) { | 1344 | do_each_task_pid(tty->session, PIDTYPE_SID, p) { |
1345 | spin_lock_irq(&p->sighand->siglock); | ||
1357 | if (p->signal->tty == tty) | 1346 | if (p->signal->tty == tty) |
1358 | p->signal->tty = NULL; | 1347 | p->signal->tty = NULL; |
1359 | if (!p->signal->leader) | 1348 | if (!p->signal->leader) { |
1349 | spin_unlock_irq(&p->sighand->siglock); | ||
1360 | continue; | 1350 | continue; |
1361 | group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); | 1351 | } |
1362 | group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); | 1352 | __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p); |
1353 | __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p); | ||
1363 | if (tty->pgrp > 0) | 1354 | if (tty->pgrp > 0) |
1364 | p->signal->tty_old_pgrp = tty->pgrp; | 1355 | p->signal->tty_old_pgrp = tty->pgrp; |
1356 | spin_unlock_irq(&p->sighand->siglock); | ||
1365 | } while_each_task_pid(tty->session, PIDTYPE_SID, p); | 1357 | } while_each_task_pid(tty->session, PIDTYPE_SID, p); |
1366 | } | 1358 | } |
1367 | read_unlock(&tasklist_lock); | 1359 | read_unlock(&tasklist_lock); |
@@ -1453,6 +1445,14 @@ int tty_hung_up_p(struct file * filp) | |||
1453 | 1445 | ||
1454 | EXPORT_SYMBOL(tty_hung_up_p); | 1446 | EXPORT_SYMBOL(tty_hung_up_p); |
1455 | 1447 | ||
1448 | static void session_clear_tty(pid_t session) | ||
1449 | { | ||
1450 | struct task_struct *p; | ||
1451 | do_each_task_pid(session, PIDTYPE_SID, p) { | ||
1452 | proc_clear_tty(p); | ||
1453 | } while_each_task_pid(session, PIDTYPE_SID, p); | ||
1454 | } | ||
1455 | |||
1456 | /** | 1456 | /** |
1457 | * disassociate_ctty - disconnect controlling tty | 1457 | * disassociate_ctty - disconnect controlling tty |
1458 | * @on_exit: true if exiting so need to "hang up" the session | 1458 | * @on_exit: true if exiting so need to "hang up" the session |
@@ -1469,31 +1469,35 @@ EXPORT_SYMBOL(tty_hung_up_p); | |||
1469 | * The argument on_exit is set to 1 if called when a process is | 1469 | * The argument on_exit is set to 1 if called when a process is |
1470 | * exiting; it is 0 if called by the ioctl TIOCNOTTY. | 1470 | * exiting; it is 0 if called by the ioctl TIOCNOTTY. |
1471 | * | 1471 | * |
1472 | * Locking: tty_mutex is taken to protect current->signal->tty | 1472 | * Locking: |
1473 | * BKL is taken for hysterical raisins | 1473 | * BKL is taken for hysterical raisins |
1474 | * Tasklist lock is taken (under tty_mutex) to walk process | 1474 | * tty_mutex is taken to protect tty |
1475 | * lists for the session. | 1475 | * ->siglock is taken to protect ->signal/->sighand |
1476 | * tasklist_lock is taken to walk process list for sessions | ||
1477 | * ->siglock is taken to protect ->signal/->sighand | ||
1476 | */ | 1478 | */ |
1477 | 1479 | ||
1478 | void disassociate_ctty(int on_exit) | 1480 | void disassociate_ctty(int on_exit) |
1479 | { | 1481 | { |
1480 | struct tty_struct *tty; | 1482 | struct tty_struct *tty; |
1481 | struct task_struct *p; | ||
1482 | int tty_pgrp = -1; | 1483 | int tty_pgrp = -1; |
1484 | int session; | ||
1483 | 1485 | ||
1484 | lock_kernel(); | 1486 | lock_kernel(); |
1485 | 1487 | ||
1486 | mutex_lock(&tty_mutex); | 1488 | mutex_lock(&tty_mutex); |
1487 | tty = current->signal->tty; | 1489 | tty = get_current_tty(); |
1488 | if (tty) { | 1490 | if (tty) { |
1489 | tty_pgrp = tty->pgrp; | 1491 | tty_pgrp = tty->pgrp; |
1490 | mutex_unlock(&tty_mutex); | 1492 | mutex_unlock(&tty_mutex); |
1493 | /* XXX: here we race, there is nothing protecting tty */ | ||
1491 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) | 1494 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) |
1492 | tty_vhangup(tty); | 1495 | tty_vhangup(tty); |
1493 | } else { | 1496 | } else { |
1494 | if (current->signal->tty_old_pgrp) { | 1497 | pid_t old_pgrp = current->signal->tty_old_pgrp; |
1495 | kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); | 1498 | if (old_pgrp) { |
1496 | kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); | 1499 | kill_pg(old_pgrp, SIGHUP, on_exit); |
1500 | kill_pg(old_pgrp, SIGCONT, on_exit); | ||
1497 | } | 1501 | } |
1498 | mutex_unlock(&tty_mutex); | 1502 | mutex_unlock(&tty_mutex); |
1499 | unlock_kernel(); | 1503 | unlock_kernel(); |
@@ -1505,19 +1509,29 @@ void disassociate_ctty(int on_exit) | |||
1505 | kill_pg(tty_pgrp, SIGCONT, on_exit); | 1509 | kill_pg(tty_pgrp, SIGCONT, on_exit); |
1506 | } | 1510 | } |
1507 | 1511 | ||
1508 | /* Must lock changes to tty_old_pgrp */ | 1512 | spin_lock_irq(¤t->sighand->siglock); |
1509 | mutex_lock(&tty_mutex); | ||
1510 | current->signal->tty_old_pgrp = 0; | 1513 | current->signal->tty_old_pgrp = 0; |
1511 | tty->session = 0; | 1514 | session = current->signal->session; |
1512 | tty->pgrp = -1; | 1515 | spin_unlock_irq(¤t->sighand->siglock); |
1516 | |||
1517 | mutex_lock(&tty_mutex); | ||
1518 | /* It is possible that do_tty_hangup has free'd this tty */ | ||
1519 | tty = get_current_tty(); | ||
1520 | if (tty) { | ||
1521 | tty->session = 0; | ||
1522 | tty->pgrp = 0; | ||
1523 | } else { | ||
1524 | #ifdef TTY_DEBUG_HANGUP | ||
1525 | printk(KERN_DEBUG "error attempted to write to tty [0x%p]" | ||
1526 | " = NULL", tty); | ||
1527 | #endif | ||
1528 | } | ||
1529 | mutex_unlock(&tty_mutex); | ||
1513 | 1530 | ||
1514 | /* Now clear signal->tty under the lock */ | 1531 | /* Now clear signal->tty under the lock */ |
1515 | read_lock(&tasklist_lock); | 1532 | read_lock(&tasklist_lock); |
1516 | do_each_task_pid(current->signal->session, PIDTYPE_SID, p) { | 1533 | session_clear_tty(session); |
1517 | p->signal->tty = NULL; | ||
1518 | } while_each_task_pid(current->signal->session, PIDTYPE_SID, p); | ||
1519 | read_unlock(&tasklist_lock); | 1534 | read_unlock(&tasklist_lock); |
1520 | mutex_unlock(&tty_mutex); | ||
1521 | unlock_kernel(); | 1535 | unlock_kernel(); |
1522 | } | 1536 | } |
1523 | 1537 | ||
@@ -2337,16 +2351,10 @@ static void release_dev(struct file * filp) | |||
2337 | * tty. | 2351 | * tty. |
2338 | */ | 2352 | */ |
2339 | if (tty_closing || o_tty_closing) { | 2353 | if (tty_closing || o_tty_closing) { |
2340 | struct task_struct *p; | ||
2341 | |||
2342 | read_lock(&tasklist_lock); | 2354 | read_lock(&tasklist_lock); |
2343 | do_each_task_pid(tty->session, PIDTYPE_SID, p) { | 2355 | session_clear_tty(tty->session); |
2344 | p->signal->tty = NULL; | ||
2345 | } while_each_task_pid(tty->session, PIDTYPE_SID, p); | ||
2346 | if (o_tty) | 2356 | if (o_tty) |
2347 | do_each_task_pid(o_tty->session, PIDTYPE_SID, p) { | 2357 | session_clear_tty(o_tty->session); |
2348 | p->signal->tty = NULL; | ||
2349 | } while_each_task_pid(o_tty->session, PIDTYPE_SID, p); | ||
2350 | read_unlock(&tasklist_lock); | 2358 | read_unlock(&tasklist_lock); |
2351 | } | 2359 | } |
2352 | 2360 | ||
@@ -2443,9 +2451,9 @@ static void release_dev(struct file * filp) | |||
2443 | * The termios state of a pty is reset on first open so that | 2451 | * The termios state of a pty is reset on first open so that |
2444 | * settings don't persist across reuse. | 2452 | * settings don't persist across reuse. |
2445 | * | 2453 | * |
2446 | * Locking: tty_mutex protects current->signal->tty, get_tty_driver and | 2454 | * Locking: tty_mutex protects tty, get_tty_driver and init_dev work. |
2447 | * init_dev work. tty->count should protect the rest. | 2455 | * tty->count should protect the rest. |
2448 | * task_lock is held to update task details for sessions | 2456 | * ->siglock protects ->signal/->sighand |
2449 | */ | 2457 | */ |
2450 | 2458 | ||
2451 | static int tty_open(struct inode * inode, struct file * filp) | 2459 | static int tty_open(struct inode * inode, struct file * filp) |
@@ -2467,12 +2475,13 @@ retry_open: | |||
2467 | mutex_lock(&tty_mutex); | 2475 | mutex_lock(&tty_mutex); |
2468 | 2476 | ||
2469 | if (device == MKDEV(TTYAUX_MAJOR,0)) { | 2477 | if (device == MKDEV(TTYAUX_MAJOR,0)) { |
2470 | if (!current->signal->tty) { | 2478 | tty = get_current_tty(); |
2479 | if (!tty) { | ||
2471 | mutex_unlock(&tty_mutex); | 2480 | mutex_unlock(&tty_mutex); |
2472 | return -ENXIO; | 2481 | return -ENXIO; |
2473 | } | 2482 | } |
2474 | driver = current->signal->tty->driver; | 2483 | driver = tty->driver; |
2475 | index = current->signal->tty->index; | 2484 | index = tty->index; |
2476 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ | 2485 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ |
2477 | /* noctty = 1; */ | 2486 | /* noctty = 1; */ |
2478 | goto got_driver; | 2487 | goto got_driver; |
@@ -2547,17 +2556,16 @@ got_driver: | |||
2547 | filp->f_op = &tty_fops; | 2556 | filp->f_op = &tty_fops; |
2548 | goto retry_open; | 2557 | goto retry_open; |
2549 | } | 2558 | } |
2559 | |||
2560 | mutex_lock(&tty_mutex); | ||
2561 | spin_lock_irq(¤t->sighand->siglock); | ||
2550 | if (!noctty && | 2562 | if (!noctty && |
2551 | current->signal->leader && | 2563 | current->signal->leader && |
2552 | !current->signal->tty && | 2564 | !current->signal->tty && |
2553 | tty->session == 0) { | 2565 | tty->session == 0) |
2554 | task_lock(current); | 2566 | __proc_set_tty(current, tty); |
2555 | current->signal->tty = tty; | 2567 | spin_unlock_irq(¤t->sighand->siglock); |
2556 | task_unlock(current); | 2568 | mutex_unlock(&tty_mutex); |
2557 | current->signal->tty_old_pgrp = 0; | ||
2558 | tty->session = current->signal->session; | ||
2559 | tty->pgrp = process_group(current); | ||
2560 | } | ||
2561 | return 0; | 2569 | return 0; |
2562 | } | 2570 | } |
2563 | 2571 | ||
@@ -2747,7 +2755,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p) | |||
2747 | * | 2755 | * |
2748 | * Copies the kernel idea of the window size into the user buffer. | 2756 | * Copies the kernel idea of the window size into the user buffer. |
2749 | * | 2757 | * |
2750 | * Locking: tty->termios_sem is taken to ensure the winsize data | 2758 | * Locking: tty->termios_mutex is taken to ensure the winsize data |
2751 | * is consistent. | 2759 | * is consistent. |
2752 | */ | 2760 | */ |
2753 | 2761 | ||
@@ -2774,8 +2782,8 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg) | |||
2774 | * Locking: | 2782 | * Locking: |
2775 | * Called function use the console_sem is used to ensure we do | 2783 | * Called function use the console_sem is used to ensure we do |
2776 | * not try and resize the console twice at once. | 2784 | * not try and resize the console twice at once. |
2777 | * The tty->termios_sem is used to ensure we don't double | 2785 | * The tty->termios_mutex is used to ensure we don't double |
2778 | * resize and get confused. Lock order - tty->termios.sem before | 2786 | * resize and get confused. Lock order - tty->termios_mutex before |
2779 | * console sem | 2787 | * console sem |
2780 | */ | 2788 | */ |
2781 | 2789 | ||
@@ -2880,25 +2888,28 @@ static int fionbio(struct file *file, int __user *p) | |||
2880 | * leader to set this tty as the controlling tty for the session. | 2888 | * leader to set this tty as the controlling tty for the session. |
2881 | * | 2889 | * |
2882 | * Locking: | 2890 | * Locking: |
2883 | * Takes tasklist lock internally to walk sessions | ||
2884 | * Takes task_lock() when updating signal->tty | ||
2885 | * Takes tty_mutex() to protect tty instance | 2891 | * Takes tty_mutex() to protect tty instance |
2886 | * | 2892 | * Takes tasklist_lock internally to walk sessions |
2893 | * Takes ->siglock() when updating signal->tty | ||
2887 | */ | 2894 | */ |
2888 | 2895 | ||
2889 | static int tiocsctty(struct tty_struct *tty, int arg) | 2896 | static int tiocsctty(struct tty_struct *tty, int arg) |
2890 | { | 2897 | { |
2891 | struct task_struct *p; | 2898 | int ret = 0; |
2892 | |||
2893 | if (current->signal->leader && | 2899 | if (current->signal->leader && |
2894 | (current->signal->session == tty->session)) | 2900 | (current->signal->session == tty->session)) |
2895 | return 0; | 2901 | return ret; |
2902 | |||
2903 | mutex_lock(&tty_mutex); | ||
2896 | /* | 2904 | /* |
2897 | * The process must be a session leader and | 2905 | * The process must be a session leader and |
2898 | * not have a controlling tty already. | 2906 | * not have a controlling tty already. |
2899 | */ | 2907 | */ |
2900 | if (!current->signal->leader || current->signal->tty) | 2908 | if (!current->signal->leader || current->signal->tty) { |
2901 | return -EPERM; | 2909 | ret = -EPERM; |
2910 | goto unlock; | ||
2911 | } | ||
2912 | |||
2902 | if (tty->session > 0) { | 2913 | if (tty->session > 0) { |
2903 | /* | 2914 | /* |
2904 | * This tty is already the controlling | 2915 | * This tty is already the controlling |
@@ -2908,24 +2919,18 @@ static int tiocsctty(struct tty_struct *tty, int arg) | |||
2908 | /* | 2919 | /* |
2909 | * Steal it away | 2920 | * Steal it away |
2910 | */ | 2921 | */ |
2911 | |||
2912 | read_lock(&tasklist_lock); | 2922 | read_lock(&tasklist_lock); |
2913 | do_each_task_pid(tty->session, PIDTYPE_SID, p) { | 2923 | session_clear_tty(tty->session); |
2914 | p->signal->tty = NULL; | ||
2915 | } while_each_task_pid(tty->session, PIDTYPE_SID, p); | ||
2916 | read_unlock(&tasklist_lock); | 2924 | read_unlock(&tasklist_lock); |
2917 | } else | 2925 | } else { |
2918 | return -EPERM; | 2926 | ret = -EPERM; |
2927 | goto unlock; | ||
2928 | } | ||
2919 | } | 2929 | } |
2920 | mutex_lock(&tty_mutex); | 2930 | proc_set_tty(current, tty); |
2921 | task_lock(current); | 2931 | unlock: |
2922 | current->signal->tty = tty; | ||
2923 | task_unlock(current); | ||
2924 | mutex_unlock(&tty_mutex); | 2932 | mutex_unlock(&tty_mutex); |
2925 | current->signal->tty_old_pgrp = 0; | 2933 | return ret; |
2926 | tty->session = current->signal->session; | ||
2927 | tty->pgrp = process_group(current); | ||
2928 | return 0; | ||
2929 | } | 2934 | } |
2930 | 2935 | ||
2931 | /** | 2936 | /** |
@@ -2937,7 +2942,7 @@ static int tiocsctty(struct tty_struct *tty, int arg) | |||
2937 | * Obtain the process group of the tty. If there is no process group | 2942 | * Obtain the process group of the tty. If there is no process group |
2938 | * return an error. | 2943 | * return an error. |
2939 | * | 2944 | * |
2940 | * Locking: none. Reference to ->signal->tty is safe. | 2945 | * Locking: none. Reference to current->signal->tty is safe. |
2941 | */ | 2946 | */ |
2942 | 2947 | ||
2943 | static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) | 2948 | static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) |
@@ -2995,7 +3000,7 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t | |||
2995 | * Obtain the session id of the tty. If there is no session | 3000 | * Obtain the session id of the tty. If there is no session |
2996 | * return an error. | 3001 | * return an error. |
2997 | * | 3002 | * |
2998 | * Locking: none. Reference to ->signal->tty is safe. | 3003 | * Locking: none. Reference to current->signal->tty is safe. |
2999 | */ | 3004 | */ |
3000 | 3005 | ||
3001 | static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) | 3006 | static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) |
@@ -3214,14 +3219,11 @@ int tty_ioctl(struct inode * inode, struct file * file, | |||
3214 | clear_bit(TTY_EXCLUSIVE, &tty->flags); | 3219 | clear_bit(TTY_EXCLUSIVE, &tty->flags); |
3215 | return 0; | 3220 | return 0; |
3216 | case TIOCNOTTY: | 3221 | case TIOCNOTTY: |
3217 | /* FIXME: taks lock or tty_mutex ? */ | ||
3218 | if (current->signal->tty != tty) | 3222 | if (current->signal->tty != tty) |
3219 | return -ENOTTY; | 3223 | return -ENOTTY; |
3220 | if (current->signal->leader) | 3224 | if (current->signal->leader) |
3221 | disassociate_ctty(0); | 3225 | disassociate_ctty(0); |
3222 | task_lock(current); | 3226 | proc_clear_tty(current); |
3223 | current->signal->tty = NULL; | ||
3224 | task_unlock(current); | ||
3225 | return 0; | 3227 | return 0; |
3226 | case TIOCSCTTY: | 3228 | case TIOCSCTTY: |
3227 | return tiocsctty(tty, arg); | 3229 | return tiocsctty(tty, arg); |
@@ -3321,7 +3323,7 @@ static void __do_SAK(struct work_struct *work) | |||
3321 | 3323 | ||
3322 | if (!tty) | 3324 | if (!tty) |
3323 | return; | 3325 | return; |
3324 | session = tty->session; | 3326 | session = tty->session; |
3325 | 3327 | ||
3326 | /* We don't want an ldisc switch during this */ | 3328 | /* We don't want an ldisc switch during this */ |
3327 | disc = tty_ldisc_ref(tty); | 3329 | disc = tty_ldisc_ref(tty); |
@@ -3834,9 +3836,52 @@ int tty_unregister_driver(struct tty_driver *driver) | |||
3834 | cdev_del(&driver->cdev); | 3836 | cdev_del(&driver->cdev); |
3835 | return 0; | 3837 | return 0; |
3836 | } | 3838 | } |
3837 | |||
3838 | EXPORT_SYMBOL(tty_unregister_driver); | 3839 | EXPORT_SYMBOL(tty_unregister_driver); |
3839 | 3840 | ||
3841 | dev_t tty_devnum(struct tty_struct *tty) | ||
3842 | { | ||
3843 | return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; | ||
3844 | } | ||
3845 | EXPORT_SYMBOL(tty_devnum); | ||
3846 | |||
3847 | void proc_clear_tty(struct task_struct *p) | ||
3848 | { | ||
3849 | spin_lock_irq(&p->sighand->siglock); | ||
3850 | p->signal->tty = NULL; | ||
3851 | spin_unlock_irq(&p->sighand->siglock); | ||
3852 | } | ||
3853 | EXPORT_SYMBOL(proc_clear_tty); | ||
3854 | |||
3855 | void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) | ||
3856 | { | ||
3857 | if (tty) { | ||
3858 | tty->session = tsk->signal->session; | ||
3859 | tty->pgrp = process_group(tsk); | ||
3860 | } | ||
3861 | tsk->signal->tty = tty; | ||
3862 | tsk->signal->tty_old_pgrp = 0; | ||
3863 | } | ||
3864 | |||
3865 | void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) | ||
3866 | { | ||
3867 | spin_lock_irq(&tsk->sighand->siglock); | ||
3868 | __proc_set_tty(tsk, tty); | ||
3869 | spin_unlock_irq(&tsk->sighand->siglock); | ||
3870 | } | ||
3871 | |||
3872 | struct tty_struct *get_current_tty(void) | ||
3873 | { | ||
3874 | struct tty_struct *tty; | ||
3875 | WARN_ON_ONCE(!mutex_is_locked(&tty_mutex)); | ||
3876 | tty = current->signal->tty; | ||
3877 | /* | ||
3878 | * session->tty can be changed/cleared from under us, make sure we | ||
3879 | * issue the load. The obtained pointer, when not NULL, is valid as | ||
3880 | * long as we hold tty_mutex. | ||
3881 | */ | ||
3882 | barrier(); | ||
3883 | return tty; | ||
3884 | } | ||
3840 | 3885 | ||
3841 | /* | 3886 | /* |
3842 | * Initialize the console device. This is called *early*, so | 3887 | * Initialize the console device. This is called *early*, so |
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 78f8bda81dae..ef205ddd31a4 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c | |||
@@ -424,11 +424,15 @@ fs3270_open(struct inode *inode, struct file *filp) | |||
424 | minor = iminor(filp->f_dentry->d_inode); | 424 | minor = iminor(filp->f_dentry->d_inode); |
425 | /* Check for minor 0 multiplexer. */ | 425 | /* Check for minor 0 multiplexer. */ |
426 | if (minor == 0) { | 426 | if (minor == 0) { |
427 | if (!current->signal->tty) | 427 | struct tty_struct *tty; |
428 | mutex_lock(&tty_mutex); | ||
429 | tty = get_current_tty(); | ||
430 | if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) { | ||
431 | mutex_unlock(&tty_mutex); | ||
428 | return -ENODEV; | 432 | return -ENODEV; |
429 | if (current->signal->tty->driver->major != IBM_TTY3270_MAJOR) | 433 | } |
430 | return -ENODEV; | 434 | minor = tty->index + RAW3270_FIRSTMINOR; |
431 | minor = current->signal->tty->index + RAW3270_FIRSTMINOR; | 435 | mutex_unlock(&tty_mutex); |
432 | } | 436 | } |
433 | /* Check if some other program is already using fullscreen mode. */ | 437 | /* Check if some other program is already using fullscreen mode. */ |
434 | fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); | 438 | fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); |
diff --git a/fs/dquot.c b/fs/dquot.c index f9cd5e23ebdf..89066b19124d 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -828,6 +828,7 @@ static inline int need_print_warning(struct dquot *dquot) | |||
828 | static void print_warning(struct dquot *dquot, const char warntype) | 828 | static void print_warning(struct dquot *dquot, const char warntype) |
829 | { | 829 | { |
830 | char *msg = NULL; | 830 | char *msg = NULL; |
831 | struct tty_struct *tty; | ||
831 | int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS_B : | 832 | int flag = (warntype == BHARDWARN || warntype == BSOFTLONGWARN) ? DQ_BLKS_B : |
832 | ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES_B : 0); | 833 | ((warntype == IHARDWARN || warntype == ISOFTLONGWARN) ? DQ_INODES_B : 0); |
833 | 834 | ||
@@ -835,14 +836,15 @@ static void print_warning(struct dquot *dquot, const char warntype) | |||
835 | return; | 836 | return; |
836 | 837 | ||
837 | mutex_lock(&tty_mutex); | 838 | mutex_lock(&tty_mutex); |
838 | if (!current->signal->tty) | 839 | tty = get_current_tty(); |
840 | if (!tty) | ||
839 | goto out_lock; | 841 | goto out_lock; |
840 | tty_write_message(current->signal->tty, dquot->dq_sb->s_id); | 842 | tty_write_message(tty, dquot->dq_sb->s_id); |
841 | if (warntype == ISOFTWARN || warntype == BSOFTWARN) | 843 | if (warntype == ISOFTWARN || warntype == BSOFTWARN) |
842 | tty_write_message(current->signal->tty, ": warning, "); | 844 | tty_write_message(tty, ": warning, "); |
843 | else | 845 | else |
844 | tty_write_message(current->signal->tty, ": write failed, "); | 846 | tty_write_message(tty, ": write failed, "); |
845 | tty_write_message(current->signal->tty, quotatypes[dquot->dq_type]); | 847 | tty_write_message(tty, quotatypes[dquot->dq_type]); |
846 | switch (warntype) { | 848 | switch (warntype) { |
847 | case IHARDWARN: | 849 | case IHARDWARN: |
848 | msg = " file limit reached.\r\n"; | 850 | msg = " file limit reached.\r\n"; |
@@ -863,7 +865,7 @@ static void print_warning(struct dquot *dquot, const char warntype) | |||
863 | msg = " block quota exceeded.\r\n"; | 865 | msg = " block quota exceeded.\r\n"; |
864 | break; | 866 | break; |
865 | } | 867 | } |
866 | tty_write_message(current->signal->tty, msg); | 868 | tty_write_message(tty, msg); |
867 | out_lock: | 869 | out_lock: |
868 | mutex_unlock(&tty_mutex); | 870 | mutex_unlock(&tty_mutex); |
869 | } | 871 | } |
@@ -1087,6 +1087,7 @@ EXPORT_SYMBOL(sys_close); | |||
1087 | asmlinkage long sys_vhangup(void) | 1087 | asmlinkage long sys_vhangup(void) |
1088 | { | 1088 | { |
1089 | if (capable(CAP_SYS_TTY_CONFIG)) { | 1089 | if (capable(CAP_SYS_TTY_CONFIG)) { |
1090 | /* XXX: this needs locking */ | ||
1090 | tty_vhangup(current->signal->tty); | 1091 | tty_vhangup(current->signal->tty); |
1091 | return 0; | 1092 | return 0; |
1092 | } | 1093 | } |
diff --git a/include/linux/tty.h b/include/linux/tty.h index f717f0898238..1d29999a3439 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -309,6 +309,12 @@ extern void tty_ldisc_flush(struct tty_struct *tty); | |||
309 | extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 309 | extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd, |
310 | unsigned long arg); | 310 | unsigned long arg); |
311 | 311 | ||
312 | extern dev_t tty_devnum(struct tty_struct *tty); | ||
313 | extern void proc_clear_tty(struct task_struct *p); | ||
314 | extern void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); | ||
315 | extern void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); | ||
316 | extern struct tty_struct *get_current_tty(void); | ||
317 | |||
312 | extern struct mutex tty_mutex; | 318 | extern struct mutex tty_mutex; |
313 | 319 | ||
314 | /* n_tty.c */ | 320 | /* n_tty.c */ |
@@ -335,10 +341,5 @@ extern void console_print(const char *); | |||
335 | extern int vt_ioctl(struct tty_struct *tty, struct file * file, | 341 | extern int vt_ioctl(struct tty_struct *tty, struct file * file, |
336 | unsigned int cmd, unsigned long arg); | 342 | unsigned int cmd, unsigned long arg); |
337 | 343 | ||
338 | static inline dev_t tty_devnum(struct tty_struct *tty) | ||
339 | { | ||
340 | return MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index; | ||
341 | } | ||
342 | |||
343 | #endif /* __KERNEL__ */ | 344 | #endif /* __KERNEL__ */ |
344 | #endif | 345 | #endif |
diff --git a/kernel/acct.c b/kernel/acct.c index dc12db8600e7..ca5619039367 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
@@ -428,6 +428,7 @@ static void do_acct_process(struct file *file) | |||
428 | u64 elapsed; | 428 | u64 elapsed; |
429 | u64 run_time; | 429 | u64 run_time; |
430 | struct timespec uptime; | 430 | struct timespec uptime; |
431 | struct tty_struct *tty; | ||
431 | 432 | ||
432 | /* | 433 | /* |
433 | * First check to see if there is enough free_space to continue | 434 | * First check to see if there is enough free_space to continue |
@@ -485,12 +486,8 @@ static void do_acct_process(struct file *file) | |||
485 | #endif | 486 | #endif |
486 | 487 | ||
487 | mutex_lock(&tty_mutex); | 488 | mutex_lock(&tty_mutex); |
488 | /* FIXME: Whoever is responsible for current->signal locking needs | 489 | tty = get_current_tty(); |
489 | to use the same locking all over the kernel and document it */ | 490 | ac.ac_tty = tty ? old_encode_dev(tty_devnum(tty)) : 0; |
490 | read_lock(&tasklist_lock); | ||
491 | ac.ac_tty = current->signal->tty ? | ||
492 | old_encode_dev(tty_devnum(current->signal->tty)) : 0; | ||
493 | read_unlock(&tasklist_lock); | ||
494 | mutex_unlock(&tty_mutex); | 491 | mutex_unlock(&tty_mutex); |
495 | 492 | ||
496 | spin_lock_irq(¤t->sighand->siglock); | 493 | spin_lock_irq(¤t->sighand->siglock); |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 40722e26de98..b6cb802fbcd1 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -826,10 +826,12 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
826 | context->return_code); | 826 | context->return_code); |
827 | 827 | ||
828 | mutex_lock(&tty_mutex); | 828 | mutex_lock(&tty_mutex); |
829 | read_lock(&tasklist_lock); | ||
829 | if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) | 830 | if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) |
830 | tty = tsk->signal->tty->name; | 831 | tty = tsk->signal->tty->name; |
831 | else | 832 | else |
832 | tty = "(none)"; | 833 | tty = "(none)"; |
834 | read_unlock(&tasklist_lock); | ||
833 | audit_log_format(ab, | 835 | audit_log_format(ab, |
834 | " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" | 836 | " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" |
835 | " ppid=%d pid=%d auid=%u uid=%u gid=%u" | 837 | " ppid=%d pid=%d auid=%u uid=%u gid=%u" |
diff --git a/kernel/exit.c b/kernel/exit.c index 4e3f919edc48..fa235779b6a3 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -384,9 +384,7 @@ void daemonize(const char *name, ...) | |||
384 | exit_mm(current); | 384 | exit_mm(current); |
385 | 385 | ||
386 | set_special_pids(1, 1); | 386 | set_special_pids(1, 1); |
387 | mutex_lock(&tty_mutex); | 387 | proc_clear_tty(current); |
388 | current->signal->tty = NULL; | ||
389 | mutex_unlock(&tty_mutex); | ||
390 | 388 | ||
391 | /* Block and flush all signals */ | 389 | /* Block and flush all signals */ |
392 | sigfillset(&blocked); | 390 | sigfillset(&blocked); |
diff --git a/kernel/sys.c b/kernel/sys.c index a0c1a29a507f..1ac2d1c5d84e 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1484,7 +1484,6 @@ asmlinkage long sys_setsid(void) | |||
1484 | pid_t session; | 1484 | pid_t session; |
1485 | int err = -EPERM; | 1485 | int err = -EPERM; |
1486 | 1486 | ||
1487 | mutex_lock(&tty_mutex); | ||
1488 | write_lock_irq(&tasklist_lock); | 1487 | write_lock_irq(&tasklist_lock); |
1489 | 1488 | ||
1490 | /* Fail if I am already a session leader */ | 1489 | /* Fail if I am already a session leader */ |
@@ -1504,12 +1503,15 @@ asmlinkage long sys_setsid(void) | |||
1504 | 1503 | ||
1505 | group_leader->signal->leader = 1; | 1504 | group_leader->signal->leader = 1; |
1506 | __set_special_pids(session, session); | 1505 | __set_special_pids(session, session); |
1506 | |||
1507 | spin_lock(&group_leader->sighand->siglock); | ||
1507 | group_leader->signal->tty = NULL; | 1508 | group_leader->signal->tty = NULL; |
1508 | group_leader->signal->tty_old_pgrp = 0; | 1509 | group_leader->signal->tty_old_pgrp = 0; |
1510 | spin_unlock(&group_leader->sighand->siglock); | ||
1511 | |||
1509 | err = process_group(group_leader); | 1512 | err = process_group(group_leader); |
1510 | out: | 1513 | out: |
1511 | write_unlock_irq(&tasklist_lock); | 1514 | write_unlock_irq(&tasklist_lock); |
1512 | mutex_unlock(&tty_mutex); | ||
1513 | return err; | 1515 | return err; |
1514 | } | 1516 | } |
1515 | 1517 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 44e9cd470543..f5df8c70a9b5 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -1695,9 +1695,10 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1695 | struct tty_struct *tty; | 1695 | struct tty_struct *tty; |
1696 | struct fdtable *fdt; | 1696 | struct fdtable *fdt; |
1697 | long j = -1; | 1697 | long j = -1; |
1698 | int drop_tty = 0; | ||
1698 | 1699 | ||
1699 | mutex_lock(&tty_mutex); | 1700 | mutex_lock(&tty_mutex); |
1700 | tty = current->signal->tty; | 1701 | tty = get_current_tty(); |
1701 | if (tty) { | 1702 | if (tty) { |
1702 | file_list_lock(); | 1703 | file_list_lock(); |
1703 | file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); | 1704 | file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list); |
@@ -1710,12 +1711,14 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
1710 | struct inode *inode = file->f_dentry->d_inode; | 1711 | struct inode *inode = file->f_dentry->d_inode; |
1711 | if (inode_has_perm(current, inode, | 1712 | if (inode_has_perm(current, inode, |
1712 | FILE__READ | FILE__WRITE, NULL)) { | 1713 | FILE__READ | FILE__WRITE, NULL)) { |
1713 | /* Reset controlling tty. */ | 1714 | drop_tty = 1; |
1714 | current->signal->tty = NULL; | ||
1715 | current->signal->tty_old_pgrp = 0; | ||
1716 | } | 1715 | } |
1717 | } | 1716 | } |
1718 | file_list_unlock(); | 1717 | file_list_unlock(); |
1718 | |||
1719 | /* Reset controlling tty. */ | ||
1720 | if (drop_tty) | ||
1721 | proc_set_tty(current, NULL); | ||
1719 | } | 1722 | } |
1720 | mutex_unlock(&tty_mutex); | 1723 | mutex_unlock(&tty_mutex); |
1721 | 1724 | ||