Close two different races with concurrent opens of pty master devices

that could result in leaked ttys or a leaked pty + tty pair.

MFC after:	1 week
This commit is contained in:
John Baldwin 2008-08-04 19:51:23 +00:00
parent 0bc7bc0ec8
commit 0f3dd6ff0d

View File

@ -100,6 +100,9 @@ static struct cdevsw ptc_cdevsw = {
.d_flags = D_TTY | D_NEEDGIANT,
};
static struct mtx ptyinit_lock;
MTX_SYSINIT(ptyinit_lock, &ptyinit_lock, "ptyinit", MTX_DEF);
#define BUFSIZ 100 /* Chunk size iomoved to/from user */
struct ptsc {
@ -151,8 +154,16 @@ ptyinit(struct cdev *devc, struct thread *td)
pt->pt_tty = ttyalloc();
pt->pt_tty->t_sc = pt;
devc->si_drv1 = pt;
devc->si_tty = pt->pt_tty;
mtx_lock(&ptyinit_lock);
if (devc->si_drv1 == NULL) {
devc->si_drv1 = pt;
devc->si_tty = pt->pt_tty;
mtx_unlock(&ptyinit_lock);
} else {
mtx_unlock(&ptyinit_lock);
ttyrel(pt->pt_tty);
free(pt, M_PTY);
}
return (devc);
}
@ -335,9 +346,17 @@ 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();
pt->pt_tty->t_sc = pt;
dev->si_tty = pt->pt_tty;
tp = ttyalloc();
mtx_lock(&ptyinit_lock);
if (pt->pt_tty == NULL) {
pt->pt_tty = tp;
pt->pt_tty->t_sc = pt;
dev->si_tty = pt->pt_tty;
mtx_unlock(&ptyinit_lock);
} else {
mtx_unlock(&ptyinit_lock);
ttyrel(tp);
}
}
tp = dev->si_tty;