X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/fe8ab488e9161c46dd9885d58fc52996dc0249ff..HEAD:/bsd/kern/tty_dev.c diff --git a/bsd/kern/tty_dev.c b/bsd/kern/tty_dev.c index 87f3cd7ee..28fa8508d 100644 --- a/bsd/kern/tty_dev.c +++ b/bsd/kern/tty_dev.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 1997-2013 Apple Inc. All rights reserved. + * Copyright (c) 1997-2020 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,7 +22,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* @@ -75,13 +75,14 @@ #include #include #include -#include /* _devfs_setattr() */ -#include /* _devfs_setattr() */ +#include /* _devfs_setattr() */ +#include /* _devfs_setattr() */ #include #include #include #include -#include /* DEVFS_LOCK()/DEVFS_UNLOCK() */ +#include /* DEVFS_LOCK()/DEVFS_UNLOCK() */ +#include #if CONFIG_MACF #include @@ -96,21 +97,21 @@ static int _devfs_setattr(void *, unsigned short, uid_t, gid_t); * Forward declarations */ static void ptcwakeup(struct tty *tp, int flag); -__XNU_PRIVATE_EXTERN d_open_t ptsopen; -__XNU_PRIVATE_EXTERN d_close_t ptsclose; -__XNU_PRIVATE_EXTERN d_read_t ptsread; -__XNU_PRIVATE_EXTERN d_write_t ptswrite; -__XNU_PRIVATE_EXTERN d_ioctl_t ptyioctl; /* common ioctl */ -__XNU_PRIVATE_EXTERN d_stop_t ptsstop; -__XNU_PRIVATE_EXTERN d_reset_t ptsreset; -__XNU_PRIVATE_EXTERN d_select_t ptsselect; -__XNU_PRIVATE_EXTERN d_open_t ptcopen; -__XNU_PRIVATE_EXTERN d_close_t ptcclose; -__XNU_PRIVATE_EXTERN d_read_t ptcread; -__XNU_PRIVATE_EXTERN d_write_t ptcwrite; -__XNU_PRIVATE_EXTERN d_stop_t ptcstop; /* NO-OP */ -__XNU_PRIVATE_EXTERN d_reset_t ptcreset; -__XNU_PRIVATE_EXTERN d_select_t ptcselect; +__XNU_PRIVATE_EXTERN d_open_t ptsopen; +__XNU_PRIVATE_EXTERN d_close_t ptsclose; +__XNU_PRIVATE_EXTERN d_read_t ptsread; +__XNU_PRIVATE_EXTERN d_write_t ptswrite; +__XNU_PRIVATE_EXTERN d_ioctl_t ptyioctl; /* common ioctl */ +__XNU_PRIVATE_EXTERN d_stop_t ptsstop; +__XNU_PRIVATE_EXTERN d_reset_t ptsreset; +__XNU_PRIVATE_EXTERN d_select_t ptsselect; +__XNU_PRIVATE_EXTERN d_open_t ptcopen; +__XNU_PRIVATE_EXTERN d_close_t ptcclose; +__XNU_PRIVATE_EXTERN d_read_t ptcread; +__XNU_PRIVATE_EXTERN d_write_t ptcwrite; +__XNU_PRIVATE_EXTERN d_stop_t ptcstop; /* NO-OP */ +__XNU_PRIVATE_EXTERN d_reset_t ptcreset; +__XNU_PRIVATE_EXTERN d_select_t ptcselect; /* * XXX Should be devfs function... and use VATTR mechanisms, per @@ -125,11 +126,11 @@ __XNU_PRIVATE_EXTERN d_select_t ptcselect; static int _devfs_setattr(void * handle, unsigned short mode, uid_t uid, gid_t gid) { - devdirent_t *direntp = (devdirent_t *)handle; - devnode_t *devnodep; - int error = EACCES; - vfs_context_t ctx = vfs_context_current();; - struct vnode_attr va; + devdirent_t *direntp = (devdirent_t *)handle; + devnode_t *devnodep; + int error = EACCES; + vfs_context_t ctx = vfs_context_current();; + struct vnode_attr va; VATTR_INIT(&va); VATTR_SET(&va, va_uid, uid); @@ -161,8 +162,9 @@ _devfs_setattr(void * handle, unsigned short mode, uid_t uid, gid_t gid) snprintf(name, sizeof(name), "/dev/%s", direntp->de_name); NDINIT(&nd, LOOKUP, OP_SETATTR, FOLLOW, UIO_SYSSPACE, CAST_USER_ADDR_T(name), ctx); error = namei(&nd); - if (error) + if (error) { goto out; + } error = vnode_setattr(nd.ni_vp, &va, ctx); vnode_put(nd.ni_vp); nameidone(&nd); @@ -170,10 +172,10 @@ _devfs_setattr(void * handle, unsigned short mode, uid_t uid, gid_t gid) } out: - return(error); + return error; } -#define BUFSIZ 100 /* Chunk size iomoved to/from user */ +#define BUFSIZ 100 /* Chunk size iomoved to/from user */ static struct tty_dev_t *tty_dev_head; @@ -268,37 +270,41 @@ ptsopen(dev_t dev, int flag, __unused int devtype, __unused struct proc *p) tty_lock(tp); if ((tp->t_state & TS_ISOPEN) == 0) { - termioschars(&tp->t_termios); /* Set up default chars */ + termioschars(&tp->t_termios); /* Set up default chars */ tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; - ttsetwater(tp); /* would be done in xxparam() */ + ttsetwater(tp); /* would be done in xxparam() */ } else if ((tp->t_state & TS_XCLUDE) && kauth_cred_issuser(kauth_cred_get())) { - error = EBUSY; + error = EBUSY; goto out; } - if (tp->t_oproc) /* Ctrlr still around. */ + if (tp->t_oproc) { /* Ctrlr still around. */ (void)(*linesw[tp->t_line].l_modem)(tp, 1); + } while ((tp->t_state & TS_CARR_ON) == 0) { - if (flag&FNONBLOCK) + if (flag & FNONBLOCK) { break; + } error = ttysleep(tp, TSA_CARR_ON(tp), TTIPRI | PCATCH, __FUNCTION__, 0); - if (error) + if (error) { goto out; + } } error = (*linesw[tp->t_line].l_open)(dev, tp); /* Successful open; mark as open by the slave */ pti->pt_flags |= PF_OPEN_S; CLR(tp->t_state, TS_IOCTL_NOT_OK); - if (error == 0) - ptcwakeup(tp, FREAD|FWRITE); + if (error == 0) { + ptcwakeup(tp, FREAD | FWRITE); + } out: tty_unlock(tp); - return (error); + return error; } __private_extern__ int @@ -311,27 +317,35 @@ ptsclose(dev_t dev, int flag, __unused int mode, __unused proc_t p) * are fixed. They are hanging with a deadlock * where close() will not complete without t_timeout set */ -#define FIX_VSX_HANG 1 -#ifdef FIX_VSX_HANG +#define FIX_VSX_HANG 1 +#ifdef FIX_VSX_HANG int save_timeout; #endif struct tty_dev_t *driver; struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver); struct tty *tp; - - if (pti == NULL) - return (ENXIO); + + if (pti == NULL) { + return ENXIO; + } tp = pti->pt_tty; tty_lock(tp); -#ifdef FIX_VSX_HANG +#ifdef FIX_VSX_HANG save_timeout = tp->t_timeout; tp->t_timeout = 60; #endif + /* + * Close the line discipline and backing TTY structures. + */ err = (*linesw[tp->t_line].l_close)(tp, flag); - ptsstop(tp, FREAD|FWRITE); - (void) ttyclose(tp); -#ifdef FIX_VSX_HANG + (void)ttyclose(tp); + + /* + * Flush data and notify any waiters on the master side of this PTY. + */ + ptsstop(tp, FREAD | FWRITE); +#ifdef FIX_VSX_HANG tp->t_timeout = save_timeout; #endif tty_unlock(tp); @@ -342,7 +356,7 @@ ptsclose(dev_t dev, int flag, __unused int mode, __unused proc_t p) /* unconditional, just like ttyclose() */ pty_free_ioctl(dev, PF_OPEN_S); - return (err); + return err; } __private_extern__ int @@ -355,8 +369,9 @@ ptsread(dev_t dev, struct uio *uio, int flag) struct uthread *ut; struct pgrp *pg; - if (pti == NULL) - return (ENXIO); + if (pti == NULL) { + return ENXIO; + } tp = pti->pt_tty; tty_lock(tp); @@ -393,8 +408,9 @@ again: tty_lock(tp); error = ttysleep(tp, &ptsread, TTIPRI | PCATCH | PTTYBLOCK, __FUNCTION__, hz); - if (error) - goto out; + if (error) { + goto out; + } } if (tp->t_canq.c_cc == 0) { if (flag & IO_NDELAY) { @@ -402,8 +418,9 @@ again: goto out; } error = ttysleep(tp, TSA_PTS_READ(tp), TTIPRI | PCATCH, __FUNCTION__, 0); - if (error) - goto out; + if (error) { + goto out; + } goto again; } while (tp->t_canq.c_cc > 1 && uio_resid(uio) > 0) { @@ -415,20 +432,23 @@ again: cc = MIN(cc, tp->t_canq.c_cc - 1); cc = q_to_b(&tp->t_canq, (u_char *)buf, cc); error = uiomove(buf, cc, uio); - if (error) + if (error) { break; + } } - if (tp->t_canq.c_cc == 1) + if (tp->t_canq.c_cc == 1) { (void) getc(&tp->t_canq); - if (tp->t_canq.c_cc) - goto out; - } else - if (tp->t_oproc) - error = (*linesw[tp->t_line].l_read)(tp, uio, flag); + } + if (tp->t_canq.c_cc) { + goto out; + } + } else if (tp->t_oproc) { + error = (*linesw[tp->t_line].l_read)(tp, uio, flag); + } ptcwakeup(tp, FWRITE); out: tty_unlock(tp); - return (error); + return error; } /* @@ -443,19 +463,21 @@ ptswrite(dev_t dev, struct uio *uio, int flag) struct tty *tp; int error; - if (pti == NULL) - return (ENXIO); + if (pti == NULL) { + return ENXIO; + } tp = pti->pt_tty; tty_lock(tp); - if (tp->t_oproc == 0) + if (tp->t_oproc == 0) { error = EIO; - else - error = (*linesw[tp->t_line].l_write)(tp, uio, flag); + } else { + error = (*linesw[tp->t_line].l_write)(tp, uio, flag); + } tty_unlock(tp); - return (error); + return error; } /* @@ -470,10 +492,12 @@ static void ptsstart(struct tty *tp) { struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL); - if (pti == NULL) + if (pti == NULL) { + goto out; + } + if (tp->t_state & TS_TTSTOP) { goto out; - if (tp->t_state & TS_TTSTOP) - goto out; + } if (pti->pt_flags & PF_STOPPED) { pti->pt_flags &= ~PF_STOPPED; pti->pt_send = TIOCPKT_START; @@ -483,6 +507,16 @@ out: return; } +static void +ptcwakeup_knote(struct selinfo *sip, long hint) +{ + if ((sip->si_flags & SI_KNPOSTING) == 0) { + sip->si_flags |= SI_KNPOSTING; + KNOTE(&sip->si_note, hint); + sip->si_flags &= ~SI_KNPOSTING; + } +} + /* * Locks: Assumes tty_lock() is held over this call. */ @@ -490,16 +524,19 @@ static void ptcwakeup(struct tty *tp, int flag) { struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL); - if (pti == NULL) + if (pti == NULL) { return; + } if (flag & FREAD) { selwakeup(&pti->pt_selr); wakeup(TSA_PTC_READ(tp)); + ptcwakeup_knote(&pti->pt_selr, 1); } if (flag & FWRITE) { selwakeup(&pti->pt_selw); wakeup(TSA_PTC_WRITE(tp)); + ptcwakeup_knote(&pti->pt_selw, 1); } } @@ -509,9 +546,9 @@ ptcopen(dev_t dev, __unused int flag, __unused int devtype, __unused proc_t p) struct tty_dev_t *driver; struct ptmx_ioctl *pti = pty_get_ioctl(dev, PF_OPEN_M, &driver); if (pti == NULL) { - return (ENXIO); + return ENXIO; } else if (pti == (struct ptmx_ioctl*)-1) { - return (EREDRIVEOPEN); + return EREDRIVEOPEN; } struct tty *tp = pti->pt_tty; @@ -554,29 +591,46 @@ ptcclose(dev_t dev, __unused int flags, __unused int fmt, __unused proc_t p) struct tty_dev_t *driver; struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver); struct tty *tp; + struct knote *kn; + + if (!pti) { + return ENXIO; + } - if (pti == NULL) - return (ENXIO); tp = pti->pt_tty; tty_lock(tp); - (void)(*linesw[tp->t_line].l_modem)(tp, 0); - /* - * XXX MDMBUF makes no sense for ptys but would inhibit the above - * l_modem(). CLOCAL makes sense but isn't supported. Special - * l_modem()s that ignore carrier drop make no sense for ptys but - * may be in use because other parts of the line discipline make - * sense for ptys. Recover by doing everything that a normal - * ttymodem() would have done except for sending a SIGHUP. + * XXX MDMBUF makes no sense for PTYs, but would inhibit an `l_modem`. + * CLOCAL makes sense but isn't supported. Special `l_modem`s that ignore + * carrier drop make no sense for PTYs but may be in use because other parts + * of the line discipline make sense for PTYs. Recover by doing everything + * that a normal `ttymodem` would have done except for sending SIGHUP. */ + (void)(*linesw[tp->t_line].l_modem)(tp, 0); if (tp->t_state & TS_ISOPEN) { tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED); tp->t_state |= TS_ZOMBIE; ttyflush(tp, FREAD | FWRITE); } - tp->t_oproc = 0; /* mark closed */ + /* + * Null out the backing TTY struct's open procedure to prevent starting + * slaves through `ptsstart`. + */ + tp->t_oproc = NULL; + + /* + * Clear any select or kevent waiters under the lock. + */ + SLIST_FOREACH(kn, &pti->pt_selr.si_note, kn_selnext) { + KNOTE_DETACH(&pti->pt_selr.si_note, kn); + } + selthreadclear(&pti->pt_selr); + SLIST_FOREACH(kn, &pti->pt_selw.si_note, kn_selnext) { + KNOTE_DETACH(&pti->pt_selw.si_note, kn); + } + selthreadclear(&pti->pt_selw); tty_unlock(tp); @@ -587,7 +641,7 @@ ptcclose(dev_t dev, __unused int flags, __unused int fmt, __unused proc_t p) } #endif - return (0); + return 0; } __private_extern__ int @@ -598,8 +652,9 @@ ptcread(dev_t dev, struct uio *uio, int flag) char buf[BUFSIZ]; int error = 0, cc; - if (pti == NULL) - return (ENXIO); + if (pti == NULL) { + return ENXIO; + } tp = pti->pt_tty; tty_lock(tp); @@ -613,43 +668,65 @@ ptcread(dev_t dev, struct uio *uio, int flag) if (tp->t_state & TS_ISOPEN) { if (pti->pt_flags & PF_PKT && pti->pt_send) { error = ureadc((int)pti->pt_send, uio); - if (error) + if (error) { goto out; + } if (pti->pt_send & TIOCPKT_IOCTL) { - cc = MIN((int)uio_resid(uio), - (int)sizeof(tp->t_termios)); - uiomove((caddr_t)&tp->t_termios, cc, - uio); +#ifdef __LP64__ + if (uio->uio_segflg == UIO_USERSPACE32) { + static struct termios32 tio32; + cc = MIN((int)uio_resid(uio), (int)sizeof(tio32)); + termios64to32((struct user_termios *)&tp->t_termios, + (struct termios32 *)&tio32); + uiomove((caddr_t)&tio32, cc, uio); +#else + if (uio->uio_segflg == UIO_USERSPACE64) { + static struct user_termios tio64; + cc = MIN((int)uio_resid(uio), (int)sizeof(tio64)); + termios32to64((struct termios32 *)&tp->t_termios, + (struct user_termios *)&tio64); + uiomove((caddr_t)&tio64, cc, uio); +#endif + } else { + cc = MIN((int)uio_resid(uio), (int)sizeof(tp->t_termios)); + uiomove((caddr_t)&tp->t_termios, cc, uio); + } } pti->pt_send = 0; goto out; } if (pti->pt_flags & PF_UCNTL && pti->pt_ucntl) { error = ureadc((int)pti->pt_ucntl, uio); - if (error) + if (error) { goto out; + } pti->pt_ucntl = 0; goto out; } - if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) + if (tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) { break; + } + } + if ((tp->t_state & TS_CONNECTED) == 0) { + goto out; /* EOF */ } - if ((tp->t_state & TS_CONNECTED) == 0) - goto out; /* EOF */ if (flag & IO_NDELAY) { error = EWOULDBLOCK; goto out; } error = ttysleep(tp, TSA_PTC_READ(tp), TTIPRI | PCATCH, __FUNCTION__, 0); - if (error) - goto out; + if (error) { + goto out; + } } - if (pti->pt_flags & (PF_PKT|PF_UCNTL)) + if (pti->pt_flags & (PF_PKT | PF_UCNTL)) { error = ureadc(0, uio); + } while (uio_resid(uio) > 0 && error == 0) { cc = q_to_b(&tp->t_outq, (u_char *)buf, MIN((int)uio_resid(uio), BUFSIZ)); - if (cc <= 0) + if (cc <= 0) { break; + } error = uiomove(buf, cc, uio); } (*linesw[tp->t_line].l_start)(tp); @@ -657,7 +734,7 @@ ptcread(dev_t dev, struct uio *uio, int flag) out: tty_unlock(tp); - return (error); + return error; } /* @@ -671,22 +748,26 @@ ptsstop(struct tty* tp, int flush) struct ptmx_ioctl *pti = pty_get_ioctl(tp->t_dev, 0, NULL); int flag; - if (pti == NULL) - return (ENXIO); + if (pti == NULL) { + return ENXIO; + } /* note: FLUSHREAD and FLUSHWRITE already ok */ if (flush == 0) { flush = TIOCPKT_STOP; pti->pt_flags |= PF_STOPPED; - } else + } else { pti->pt_flags &= ~PF_STOPPED; + } pti->pt_send |= flush; /* change of perspective */ flag = 0; - if (flush & FREAD) + if (flush & FREAD) { flag |= FWRITE; - if (flush & FWRITE) + } + if (flush & FWRITE) { flag |= FREAD; + } ptcwakeup(tp, flag); return 0; } @@ -694,7 +775,7 @@ ptsstop(struct tty* tp, int flush) __private_extern__ int ptsreset(__unused int uban) { - return (0); + return 0; } int @@ -704,11 +785,13 @@ ptsselect(dev_t dev, int rw, void *wql, proc_t p) struct tty *tp; int retval = 0; - if (pti == NULL) - return (ENXIO); + if (pti == NULL) { + return ENXIO; + } tp = pti->pt_tty; - if (tp == NULL) - return (ENXIO); + if (tp == NULL) { + return ENXIO; + } tty_lock(tp); @@ -733,7 +816,7 @@ ptsselect(dev_t dev, int rw, void *wql, proc_t p) } if ((tp->t_outq.c_cc <= tp->t_lowat) && - ISSET(tp->t_state, TS_CONNECTED)) { + ISSET(tp->t_state, TS_CONNECTED)) { retval = tp->t_hiwat - tp->t_outq.c_cc; break; } @@ -743,7 +826,7 @@ ptsselect(dev_t dev, int rw, void *wql, proc_t p) } tty_unlock(tp); - return (retval); + return retval; } __private_extern__ int @@ -754,8 +837,9 @@ ptcselect(dev_t dev, int rw, void *wql, proc_t p) struct tty *tp; int retval = 0; - if (pti == NULL) - return (ENXIO); + if (pti == NULL) { + return ENXIO; + } tp = pti->pt_tty; tty_lock(tp); @@ -764,22 +848,21 @@ ptcselect(dev_t dev, int rw, void *wql, proc_t p) goto out; } switch (rw) { - case FREAD: /* * Need to block timeouts (ttrstart). */ - if ((tp->t_state&TS_ISOPEN) && - tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) { + if ((tp->t_state & TS_ISOPEN) && + tp->t_outq.c_cc && (tp->t_state & TS_TTSTOP) == 0) { retval = (driver->fix_7828447) ? tp->t_outq.c_cc : 1; break; } - /* FALLTHROUGH */ + OS_FALLTHROUGH; - case 0: /* exceptional */ - if ((tp->t_state&TS_ISOPEN) && - ((pti->pt_flags & PF_PKT && pti->pt_send) || - (pti->pt_flags & PF_UCNTL && pti->pt_ucntl))) { + case 0: /* exceptional */ + if ((tp->t_state & TS_ISOPEN) && + (((pti->pt_flags & PF_PKT) && pti->pt_send) || + ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))) { retval = 1; break; } @@ -788,45 +871,44 @@ ptcselect(dev_t dev, int rw, void *wql, proc_t p) case FWRITE: - if (tp->t_state&TS_ISOPEN) { + if (tp->t_state & TS_ISOPEN) { if (pti->pt_flags & PF_REMOTE) { - if (tp->t_canq.c_cc == 0) { - retval = (driver->fix_7828447) ? (TTYHOG - 1) : 1; - break; - } + if (tp->t_canq.c_cc == 0) { + retval = (driver->fix_7828447) ? (TTYHOG - 1) : 1; + break; + } } else { - retval = (TTYHOG - 2) - (tp->t_rawq.c_cc + tp->t_canq.c_cc); - if (retval > 0) { - retval = (driver->fix_7828447) ? retval : 1; - break; - } - if (tp->t_canq.c_cc == 0 && (tp->t_lflag&ICANON)) { - retval = 1; - break; - } - retval = 0; + retval = (TTYHOG - 2) - (tp->t_rawq.c_cc + tp->t_canq.c_cc); + if (retval > 0) { + retval = (driver->fix_7828447) ? retval : 1; + break; + } + if (tp->t_canq.c_cc == 0 && (tp->t_lflag & ICANON)) { + retval = 1; + break; + } + retval = 0; } } selrecord(p, &pti->pt_selw, wql); break; - } out: tty_unlock(tp); - return (retval); + return retval; } __private_extern__ int ptcstop(__unused struct tty *tp, __unused int flush) { - return (0); + return 0; } __private_extern__ int ptcreset(__unused int uban) { - return (0); + return 0; } __private_extern__ int @@ -840,26 +922,30 @@ ptcwrite(dev_t dev, struct uio *uio, int flag) int wcnt = 0; int error = 0; - if (pti == NULL) - return (ENXIO); + if (pti == NULL) { + return ENXIO; + } tp = pti->pt_tty; tty_lock(tp); again: - if ((tp->t_state & TS_ISOPEN) == 0) + if ((tp->t_state & TS_ISOPEN) == 0) { goto block; + } if (pti->pt_flags & PF_REMOTE) { - if (tp->t_canq.c_cc) + if (tp->t_canq.c_cc) { goto block; + } while ((uio_resid(uio) > 0 || cc > 0) && - tp->t_canq.c_cc < TTYHOG - 1) { + tp->t_canq.c_cc < TTYHOG - 1) { if (cc == 0) { cc = MIN((int)uio_resid(uio), BUFSIZ); cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); cp = locbuf; error = uiomove((caddr_t)cp, cc, uio); - if (error) + if (error) { goto out; + } /* check again for safety */ if ((tp->t_state & TS_ISOPEN) == 0) { /* adjust as usual */ @@ -878,8 +964,9 @@ again: * we don't fail here since (TTYHOG - 1) is * not a multiple of CBSIZE. */ - if (cc > 0) + if (cc > 0) { break; + } } } /* adjust for data copied in but not written */ @@ -894,8 +981,9 @@ again: cc = MIN((int)uio_resid(uio), BUFSIZ); cp = locbuf; error = uiomove((caddr_t)cp, cc, uio); - if (error) + if (error) { goto out; + } /* check again for safety */ if ((tp->t_state & TS_ISOPEN) == 0) { /* adjust for data copied in but not written */ @@ -906,7 +994,7 @@ again: } while (cc > 0) { if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && - (tp->t_canq.c_cc > 0 || !(tp->t_lflag&ICANON))) { + (tp->t_canq.c_cc > 0 || !(tp->t_lflag & ICANON))) { wakeup(TSA_HUP_OR_INPUT(tp)); goto block; } @@ -919,7 +1007,7 @@ again: out: tty_unlock(tp); - return (error); + return error; block: /* @@ -935,8 +1023,9 @@ block: if (flag & IO_NDELAY) { /* adjust for data copied in but not written */ uio_setresid(uio, (uio_resid(uio) + cc)); - if (wcnt == 0) + if (wcnt == 0) { error = EWOULDBLOCK; + } goto out; } error = ttysleep(tp, TSA_PTC_WRITE(tp), TTOPRI | PCATCH, __FUNCTION__, 0); @@ -948,6 +1037,9 @@ block: goto again; } +/* + * ptyioctl: Assumes dev was opened and lock was initilized + */ __private_extern__ int ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { @@ -957,8 +1049,14 @@ ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) int stop, error = 0; int allow_ext_ioctl = 1; - if (pti == NULL) - return (ENXIO); + if (pti == NULL || pti->pt_tty == NULL) { + return ENXIO; + } + + if (cmd == KMIOCDISABLCONS) { + return 0; + } + tp = pti->pt_tty; tty_lock(tp); @@ -999,10 +1097,8 @@ ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) tp->t_lflag &= ~EXTPROC; } goto out; - } else - if (cdevsw[major(dev)].d_open == ptcopen) { + } else if (cdevsw[major(dev)].d_open == ptcopen) { switch (cmd) { - case TIOCGPGRP: /* * We aviod calling ttioctl on the controller since, @@ -1013,32 +1109,35 @@ ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) case TIOCPKT: if (*(int *)data) { - if (pti->pt_flags & PF_UCNTL) { + if (pti->pt_flags & PF_UCNTL) { error = EINVAL; goto out; } pti->pt_flags |= PF_PKT; - } else + } else { pti->pt_flags &= ~PF_PKT; + } goto out; case TIOCUCNTL: if (*(int *)data) { - if (pti->pt_flags & PF_PKT) { + if (pti->pt_flags & PF_PKT) { error = EINVAL; goto out; } pti->pt_flags |= PF_UCNTL; - } else + } else { pti->pt_flags &= ~PF_UCNTL; + } goto out; case TIOCREMOTE: - if (*(int *)data) + if (*(int *)data) { pti->pt_flags |= PF_REMOTE; - else + } else { pti->pt_flags &= ~PF_REMOTE; - ttyflush(tp, FREAD|FWRITE); + } + ttyflush(tp, FREAD | FWRITE); goto out; case TIOCSETP: @@ -1059,11 +1158,13 @@ ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) error = EINVAL; goto out; } - if ((tp->t_lflag&NOFLSH) == 0) - ttyflush(tp, FREAD|FWRITE); + if ((tp->t_lflag & NOFLSH) == 0) { + ttyflush(tp, FREAD | FWRITE); + } if ((*(unsigned int *)data == SIGINFO) && - ((tp->t_lflag&NOKERNINFO) == 0)) + ((tp->t_lflag & NOKERNINFO) == 0)) { ttyinfo_locked(tp); + } /* * SAFE: All callers drop the lock on return and * SAFE: the linesw[] will short circut this call @@ -1075,31 +1176,31 @@ ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) tty_lock(tp); goto out; - case TIOCPTYGRANT: /* grantpt(3) */ + case TIOCPTYGRANT: /* grantpt(3) */ /* * Change the uid of the slave to that of the calling * thread, change the gid of the slave to GID_TTY, * change the mode to 0620 (rw--w----). */ - { - error = _devfs_setattr(pti->pt_devhandle, 0620, kauth_getuid(), GID_TTY); - if (major(dev) == driver->master) { - if (driver->mac_notify) { + { + error = _devfs_setattr(pti->pt_devhandle, 0620, kauth_getuid(), GID_TTY); + if (major(dev) == driver->master) { + if (driver->mac_notify) { #if CONFIG_MACF - if (!error) { - tty_unlock(tp); - mac_pty_notify_grant(p, tp, dev, NULL); - tty_lock(tp); - } -#endif - } else { - error = 0; + if (!error) { + tty_unlock(tp); + mac_pty_notify_grant(p, tp, dev, NULL); + tty_lock(tp); } +#endif + } else { + error = 0; } - goto out; } + goto out; + } - case TIOCPTYGNAME: /* ptsname(3) */ + case TIOCPTYGNAME: /* ptsname(3) */ /* * Report the name of the slave device in *data * (128 bytes max.). Use the same template string @@ -1108,8 +1209,8 @@ ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) pty_get_name(dev, data, 128); error = 0; goto out; - - case TIOCPTYUNLK: /* unlockpt(3) */ + + case TIOCPTYUNLK: /* unlockpt(3) */ /* * Unlock the slave device so that it can be opened. */ @@ -1160,8 +1261,8 @@ ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) /* * If external processing and packet mode send ioctl packet. */ - if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) { - switch(cmd) { + if ((tp->t_lflag & EXTPROC) && (pti->pt_flags & PF_PKT)) { + switch (cmd) { case TIOCSETA_32: case TIOCSETAW_32: case TIOCSETAF_32: @@ -1177,12 +1278,13 @@ ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) case TIOCLSET: pti->pt_send |= TIOCPKT_IOCTL; ptcwakeup(tp, FREAD); + break; default: break; } } stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s')) - && CCEQ(cc[VSTART], CTRL('q')); + && CCEQ(cc[VSTART], CTRL('q')); if (pti->pt_flags & PF_NOSTOP) { if (stop) { pti->pt_send &= ~TIOCPKT_NOSTOP; @@ -1201,5 +1303,5 @@ ptyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) out: tty_unlock(tp); - return (error); + return error; }