|
Lines 122-127
Link Here
|
| 122 |
LIST_HEAD(tty_drivers); /* linked list of tty drivers */ |
122 |
LIST_HEAD(tty_drivers); /* linked list of tty drivers */ |
| 123 |
struct tty_ldisc ldiscs[NR_LDISCS]; /* line disc dispatch table */ |
123 |
struct tty_ldisc ldiscs[NR_LDISCS]; /* line disc dispatch table */ |
| 124 |
|
124 |
|
|
|
125 |
/* Semaphore to protect creating and releasing a tty */ |
| 126 |
DECLARE_MUTEX(tty_sem); |
| 127 |
|
| 125 |
#ifdef CONFIG_UNIX98_PTYS |
128 |
#ifdef CONFIG_UNIX98_PTYS |
| 126 |
extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ |
129 |
extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ |
| 127 |
extern int pty_limit; /* Config limit on Unix98 ptys */ |
130 |
extern int pty_limit; /* Config limit on Unix98 ptys */ |
|
Lines 567-575
Link Here
|
| 567 |
|
570 |
|
| 568 |
lock_kernel(); |
571 |
lock_kernel(); |
| 569 |
|
572 |
|
|
|
573 |
down(&tty_sem); |
| 570 |
tty = current->signal->tty; |
574 |
tty = current->signal->tty; |
| 571 |
if (tty) { |
575 |
if (tty) { |
| 572 |
tty_pgrp = tty->pgrp; |
576 |
tty_pgrp = tty->pgrp; |
|
|
577 |
up(&tty_sem); |
| 573 |
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) |
578 |
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) |
| 574 |
tty_vhangup(tty); |
579 |
tty_vhangup(tty); |
| 575 |
} else { |
580 |
} else { |
|
Lines 577-582
Link Here
|
| 577 |
kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); |
582 |
kill_pg(current->signal->tty_old_pgrp, SIGHUP, on_exit); |
| 578 |
kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); |
583 |
kill_pg(current->signal->tty_old_pgrp, SIGCONT, on_exit); |
| 579 |
} |
584 |
} |
|
|
585 |
up(&tty_sem); |
| 580 |
unlock_kernel(); |
586 |
unlock_kernel(); |
| 581 |
return; |
587 |
return; |
| 582 |
} |
588 |
} |
|
Lines 586-599
Link Here
|
| 586 |
kill_pg(tty_pgrp, SIGCONT, on_exit); |
592 |
kill_pg(tty_pgrp, SIGCONT, on_exit); |
| 587 |
} |
593 |
} |
| 588 |
|
594 |
|
|
|
595 |
/* Must lock changes to tty_old_pgrp */ |
| 596 |
down(&tty_sem); |
| 589 |
current->signal->tty_old_pgrp = 0; |
597 |
current->signal->tty_old_pgrp = 0; |
| 590 |
tty->session = 0; |
598 |
tty->session = 0; |
| 591 |
tty->pgrp = -1; |
599 |
tty->pgrp = -1; |
| 592 |
|
600 |
|
|
|
601 |
/* Now clear signal->tty under the lock */ |
| 593 |
read_lock(&tasklist_lock); |
602 |
read_lock(&tasklist_lock); |
| 594 |
for_each_task_pid(current->signal->session, PIDTYPE_SID, p, l, pid) |
603 |
for_each_task_pid(current->signal->session, PIDTYPE_SID, p, l, pid) |
| 595 |
p->signal->tty = NULL; |
604 |
p->signal->tty = NULL; |
| 596 |
read_unlock(&tasklist_lock); |
605 |
read_unlock(&tasklist_lock); |
|
|
606 |
up(&tty_sem); |
| 597 |
unlock_kernel(); |
607 |
unlock_kernel(); |
| 598 |
} |
608 |
} |
| 599 |
|
609 |
|
|
Lines 758-776
Link Here
|
| 758 |
return tty_write(file, buf, count, ppos); |
768 |
return tty_write(file, buf, count, ppos); |
| 759 |
} |
769 |
} |
| 760 |
|
770 |
|
| 761 |
/* Semaphore to protect creating and releasing a tty */ |
|
|
| 762 |
static DECLARE_MUTEX(tty_sem); |
| 763 |
|
| 764 |
static void down_tty_sem(int index) |
| 765 |
{ |
| 766 |
down(&tty_sem); |
| 767 |
} |
| 768 |
|
| 769 |
static void up_tty_sem(int index) |
| 770 |
{ |
| 771 |
up(&tty_sem); |
| 772 |
} |
| 773 |
|
| 774 |
static void release_mem(struct tty_struct *tty, int idx); |
771 |
static void release_mem(struct tty_struct *tty, int idx); |
| 775 |
|
772 |
|
| 776 |
static char ptychar[] = "pqrstuvwxyzabcde"; |
773 |
static char ptychar[] = "pqrstuvwxyzabcde"; |
|
Lines 803-814
Link Here
|
| 803 |
struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; |
800 |
struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; |
| 804 |
int retval=0; |
801 |
int retval=0; |
| 805 |
|
802 |
|
| 806 |
/* |
|
|
| 807 |
* Check whether we need to acquire the tty semaphore to avoid |
| 808 |
* race conditions. For now, play it safe. |
| 809 |
*/ |
| 810 |
down_tty_sem(idx); |
| 811 |
|
| 812 |
/* check whether we're reopening an existing tty */ |
803 |
/* check whether we're reopening an existing tty */ |
| 813 |
if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { |
804 |
if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { |
| 814 |
tty = devpts_get_tty(idx); |
805 |
tty = devpts_get_tty(idx); |
|
Lines 989-997
Link Here
|
| 989 |
success: |
980 |
success: |
| 990 |
*ret_tty = tty; |
981 |
*ret_tty = tty; |
| 991 |
|
982 |
|
| 992 |
/* All paths come through here to release the semaphore */ |
|
|
| 993 |
end_init: |
983 |
end_init: |
| 994 |
up_tty_sem(idx); |
|
|
| 995 |
return retval; |
984 |
return retval; |
| 996 |
|
985 |
|
| 997 |
/* Release locally allocated memory ... nothing placed in slots */ |
986 |
/* Release locally allocated memory ... nothing placed in slots */ |
|
Lines 1184-1192
Link Here
|
| 1184 |
* each iteration we avoid any problems. |
1173 |
* each iteration we avoid any problems. |
| 1185 |
*/ |
1174 |
*/ |
| 1186 |
while (1) { |
1175 |
while (1) { |
|
|
1176 |
/* Guard against races with tty->count changes elsewhere and |
| 1177 |
opens on /dev/tty */ |
| 1178 |
|
| 1179 |
down(&tty_sem); |
| 1187 |
tty_closing = tty->count <= 1; |
1180 |
tty_closing = tty->count <= 1; |
| 1188 |
o_tty_closing = o_tty && |
1181 |
o_tty_closing = o_tty && |
| 1189 |
(o_tty->count <= (pty_master ? 1 : 0)); |
1182 |
(o_tty->count <= (pty_master ? 1 : 0)); |
|
|
1183 |
up(&tty_sem); |
| 1190 |
do_sleep = 0; |
1184 |
do_sleep = 0; |
| 1191 |
|
1185 |
|
| 1192 |
if (tty_closing) { |
1186 |
if (tty_closing) { |
|
Lines 1222-1227
Link Here
|
| 1222 |
* both sides, and we've completed the last operation that could |
1216 |
* both sides, and we've completed the last operation that could |
| 1223 |
* block, so it's safe to proceed with closing. |
1217 |
* block, so it's safe to proceed with closing. |
| 1224 |
*/ |
1218 |
*/ |
|
|
1219 |
|
| 1220 |
down(&tty_sem); |
| 1225 |
if (pty_master) { |
1221 |
if (pty_master) { |
| 1226 |
if (--o_tty->count < 0) { |
1222 |
if (--o_tty->count < 0) { |
| 1227 |
printk(KERN_WARNING "release_dev: bad pty slave count " |
1223 |
printk(KERN_WARNING "release_dev: bad pty slave count " |
|
Lines 1235-1241
Link Here
|
| 1235 |
tty->count, tty_name(tty, buf)); |
1231 |
tty->count, tty_name(tty, buf)); |
| 1236 |
tty->count = 0; |
1232 |
tty->count = 0; |
| 1237 |
} |
1233 |
} |
| 1238 |
|
1234 |
up(&tty_sem); |
|
|
1235 |
|
| 1239 |
/* |
1236 |
/* |
| 1240 |
* We've decremented tty->count, so we need to remove this file |
1237 |
* We've decremented tty->count, so we need to remove this file |
| 1241 |
* descriptor off the tty->tty_files list; this serves two |
1238 |
* descriptor off the tty->tty_files list; this serves two |
|
Lines 1343-1353
Link Here
|
| 1343 |
int index; |
1340 |
int index; |
| 1344 |
dev_t device = inode->i_rdev; |
1341 |
dev_t device = inode->i_rdev; |
| 1345 |
unsigned short saved_flags = filp->f_flags; |
1342 |
unsigned short saved_flags = filp->f_flags; |
|
|
1343 |
|
| 1346 |
retry_open: |
1344 |
retry_open: |
| 1347 |
noctty = filp->f_flags & O_NOCTTY; |
1345 |
noctty = filp->f_flags & O_NOCTTY; |
|
|
1346 |
|
| 1347 |
down(&tty_sem); |
| 1348 |
|
| 1348 |
if (device == MKDEV(TTYAUX_MAJOR,0)) { |
1349 |
if (device == MKDEV(TTYAUX_MAJOR,0)) { |
| 1349 |
if (!current->signal->tty) |
1350 |
if (!current->signal->tty) { |
|
|
1351 |
up(&tty_sem); |
| 1350 |
return -ENXIO; |
1352 |
return -ENXIO; |
|
|
1353 |
} |
| 1351 |
driver = current->signal->tty->driver; |
1354 |
driver = current->signal->tty->driver; |
| 1352 |
index = current->signal->tty->index; |
1355 |
index = current->signal->tty->index; |
| 1353 |
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ |
1356 |
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ |
|
Lines 1377-1382
Link Here
|
| 1377 |
noctty = 1; |
1380 |
noctty = 1; |
| 1378 |
goto got_driver; |
1381 |
goto got_driver; |
| 1379 |
} |
1382 |
} |
|
|
1383 |
up(&tty_sem); |
| 1380 |
return -ENODEV; |
1384 |
return -ENODEV; |
| 1381 |
} |
1385 |
} |
| 1382 |
|
1386 |
|
|
Lines 1402-1423
Link Here
|
| 1402 |
goto ptmx_found; /* ok! */ |
1406 |
goto ptmx_found; /* ok! */ |
| 1403 |
} |
1407 |
} |
| 1404 |
} |
1408 |
} |
|
|
1409 |
up(&tty_sem); |
| 1405 |
return -EIO; /* no free ptys */ |
1410 |
return -EIO; /* no free ptys */ |
| 1406 |
ptmx_found: |
1411 |
ptmx_found: |
| 1407 |
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
1412 |
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
| 1408 |
if (devpts_pty_new(tty->link)) { |
1413 |
if (devpts_pty_new(tty->link)) { |
| 1409 |
/* BADNESS - need to destroy both ptm and pts! */ |
1414 |
/* BADNESS - need to destroy both ptm and pts! */ |
|
|
1415 |
up(&tty_sem); |
| 1410 |
return -ENOMEM; |
1416 |
return -ENOMEM; |
| 1411 |
} |
1417 |
} |
| 1412 |
noctty = 1; |
1418 |
noctty = 1; |
|
|
1419 |
up(&tty_sem); |
| 1413 |
} else |
1420 |
} else |
| 1414 |
#endif |
1421 |
#endif |
| 1415 |
{ |
1422 |
{ |
| 1416 |
driver = get_tty_driver(device, &index); |
1423 |
driver = get_tty_driver(device, &index); |
| 1417 |
if (!driver) |
1424 |
if (!driver) { |
|
|
1425 |
up(&tty_sem); |
| 1418 |
return -ENODEV; |
1426 |
return -ENODEV; |
|
|
1427 |
} |
| 1419 |
got_driver: |
1428 |
got_driver: |
| 1420 |
retval = init_dev(driver, index, &tty); |
1429 |
retval = init_dev(driver, index, &tty); |
|
|
1430 |
up(&tty_sem); |
| 1421 |
if (retval) |
1431 |
if (retval) |
| 1422 |
return retval; |
1432 |
return retval; |
| 1423 |
} |
1433 |
} |