diff options
author | jhb <jhb@FreeBSD.org> | 2008-08-04 19:49:05 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2008-08-04 19:49:05 +0000 |
commit | e6ae2f5414dbb59a0d5f60290194dfa8ab1472e5 (patch) | |
tree | 2e6b1d6ae2b0c257eef4f5c5132e60496c32604b /sys/kern/tty_pts.c | |
parent | 23d4d77b06dff468253bc52d1a1d9a6447bd1e68 (diff) | |
download | FreeBSD-src-e6ae2f5414dbb59a0d5f60290194dfa8ab1472e5.zip FreeBSD-src-e6ae2f5414dbb59a0d5f60290194dfa8ab1472e5.tar.gz |
- Close a race with concurrent open's of a pts master device which could
result in leaked tty structures.
- When constructing a new pty, allocate it's tty structure before adding
it to the list.
MFC after: 1 week
Diffstat (limited to 'sys/kern/tty_pts.c')
-rw-r--r-- | sys/kern/tty_pts.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c index 03f3e94..ff8838e 100644 --- a/sys/kern/tty_pts.c +++ b/sys/kern/tty_pts.c @@ -194,18 +194,16 @@ pty_new(void) pt = LIST_FIRST(&pt_free_list); if (pt) { LIST_REMOVE(pt, pt_list); - LIST_INSERT_HEAD(&pt_list, pt, pt_list); - mtx_unlock(&pt_mtx); } else { nb = next_avail_nb++; mtx_unlock(&pt_mtx); pt = malloc(sizeof(*pt), M_PTY, M_WAITOK | M_ZERO); + pt->pt_tty = ttyalloc(); mtx_lock(&pt_mtx); pt->pt_num = nb; - LIST_INSERT_HEAD(&pt_list, pt, pt_list); - mtx_unlock(&pt_mtx); - pt->pt_tty = ttyalloc(); } + LIST_INSERT_HEAD(&pt_list, pt, pt_list); + mtx_unlock(&pt_mtx); return (pt); } @@ -400,8 +398,16 @@ ptcopen(struct cdev *dev, int flag, int devtype, struct thread *td) * we need to recreate it. */ if (pt->pt_tty == NULL) { - pt->pt_tty = ttyalloc(); - dev->si_tty = pt->pt_tty; + tp = ttyalloc(); + mtx_lock(&pt_mtx); + if (pt->pt_tty == NULL) { + pt->pt_tty = tp; + dev->si_tty = pt->pt_tty; + mtx_unlock(&pt_mtx); + } else { + mtx_unlock(&pt_mtx); + ttyrel(tp); + } } tp = dev->si_tty; if (tp->t_oproc) |