From 0f3dd6ff0d43f512dcc0878b3ecb53f4f5c4ca44 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Mon, 4 Aug 2008 19:51:23 +0000 Subject: [PATCH] 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 --- sys/kern/tty_pty.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index 5d28fe627cbd..3827e82b9384 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -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;