diff options
Diffstat (limited to 'usr/src/uts/common/io')
-rw-r--r-- | usr/src/uts/common/io/gentty.c | 114 | ||||
-rw-r--r-- | usr/src/uts/common/io/l_strplumb.c | 27 | ||||
-rw-r--r-- | usr/src/uts/common/io/ptm.c | 62 |
3 files changed, 137 insertions, 66 deletions
diff --git a/usr/src/uts/common/io/gentty.c b/usr/src/uts/common/io/gentty.c index 9cb3e23b87..431e80245d 100644 --- a/usr/src/uts/common/io/gentty.c +++ b/usr/src/uts/common/io/gentty.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 1990-1992,1996,1998-2003 Sun Microsystems, Inc. + * Copyright 2006 Sun Microsystems, Inc. * All rights reserved. * Use is subject to license terms. */ @@ -198,17 +197,20 @@ syopen(dev_t *devp, int flag, int otyp, struct cred *cr) { dev_t ttyd; vnode_t *ttyvp; - sess_t *sp = curproc->p_sessp; + sess_t *sp; int error; - if ((ttyd = sp->s_dev) == NODEV) + if ((sp = tty_hold()) == NULL) + return (EINTR); + + if (sp->s_dev == NODEV) { + tty_rele(sp); return (ENXIO); - TTY_HOLD(sp); - if ((ttyvp = sp->s_vp) == NULL) { - TTY_RELE(sp); - return (EIO); } + ttyd = sp->s_dev; + ttyvp = sp->s_vp; + /* * Open the control terminal. The control terminal may be * opened multiple times and it is closed in freectty(). @@ -237,10 +239,12 @@ syopen(dev_t *devp, int flag, int otyp, struct cred *cr) ASSERT(vn_matchops(ttyvp, spec_getvnodeops())); csp = VTOS(VTOS(ttyvp)->s_commonvp); mutex_enter(&csp->s_lock); + ASSERT(csp->s_count > 1); csp->s_count--; mutex_exit(&csp->s_lock); } - TTY_RELE(sp); + + tty_rele(sp); return (error); } @@ -255,41 +259,41 @@ syclose(dev_t dev, int flag, int otyp, struct cred *cr) int syread(dev_t dev, struct uio *uiop, struct cred *cr) { - vnode_t *ttyvp; - sess_t *sp = curproc->p_sessp; + sess_t *sp; int error; - if (sp->s_dev == NODEV) + if ((sp = tty_hold()) == NULL) + return (EINTR); + + if (sp->s_dev == NODEV) { + tty_rele(sp); return (ENXIO); - TTY_HOLD(sp); - if ((ttyvp = sp->s_vp) == NULL) { - TTY_RELE(sp); - return (EIO); } - error = VOP_READ(ttyvp, uiop, 0, cr, NULL); - TTY_RELE(sp); - return (error); + error = VOP_READ(sp->s_vp, uiop, 0, cr, NULL); + + tty_rele(sp); + return (error); } /* ARGSUSED */ int sywrite(dev_t dev, struct uio *uiop, struct cred *cr) { - vnode_t *ttyvp; - sess_t *sp = curproc->p_sessp; + sess_t *sp; int error; - if (sp->s_dev == NODEV) + if ((sp = tty_hold()) == NULL) + return (EINTR); + + if (sp->s_dev == NODEV) { + tty_rele(sp); return (ENXIO); - TTY_HOLD(sp); - if ((ttyvp = sp->s_vp) == NULL) { - TTY_RELE(sp); - return (EIO); } - error = VOP_WRITE(ttyvp, uiop, 0, cr, NULL); - TTY_RELE(sp); + error = VOP_WRITE(sp->s_vp, uiop, 0, cr, NULL); + + tty_rele(sp); return (error); } @@ -299,19 +303,32 @@ int syioctl(dev_t dev, int cmd, intptr_t arg, int mode, struct cred *cr, int *rvalp) { - vnode_t *ttyvp; - sess_t *sp = curproc->p_sessp; + sess_t *sp; int error; - if (sp->s_dev == NODEV) + if (cmd == TIOCNOTTY) { + /* + * we can't allow this ioctl. the reason is that it + * attempts to remove the ctty for a session. to do + * this the ctty can't be in use but we grab a hold on + * the current ctty (via tty_hold) to perform this ioctl. + * if we were to allow this ioctl to pass through we + * would deadlock with ourselves. + */ + return (EINVAL); + } + + if ((sp = tty_hold()) == NULL) + return (EINTR); + + if (sp->s_dev == NODEV) { + tty_rele(sp); return (ENXIO); - TTY_HOLD(sp); - if ((ttyvp = sp->s_vp) == NULL) { - TTY_RELE(sp); - return (EIO); } - error = VOP_IOCTL(ttyvp, cmd, arg, mode, cr, rvalp); - TTY_RELE(sp); + + error = VOP_IOCTL(sp->s_vp, cmd, arg, mode, cr, rvalp); + + tty_rele(sp); return (error); } @@ -322,18 +339,19 @@ int sypoll(dev_t dev, short events, int anyyet, short *reventsp, struct pollhead **phpp) { - vnode_t *ttyvp; - sess_t *sp = curproc->p_sessp; + sess_t *sp; int error; - if (sp->s_dev == NODEV) + if ((sp = tty_hold()) == NULL) + return (EINTR); + + if (sp->s_dev == NODEV) { + tty_rele(sp); return (ENXIO); - TTY_HOLD(sp); - if ((ttyvp = sp->s_vp) == NULL) { - TTY_RELE(sp); - return (EIO); } - error = VOP_POLL(ttyvp, events, anyyet, reventsp, phpp); - TTY_RELE(sp); + + error = VOP_POLL(sp->s_vp, events, anyyet, reventsp, phpp); + + tty_rele(sp); return (error); } diff --git a/usr/src/uts/common/io/l_strplumb.c b/usr/src/uts/common/io/l_strplumb.c index 287ad1f08f..3997874684 100644 --- a/usr/src/uts/common/io/l_strplumb.c +++ b/usr/src/uts/common/io/l_strplumb.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -228,7 +227,7 @@ kstr_autopush(int op, major_t *maj, minor_t *min, minor_t *lastmin, li = ldi_ident_from_anon(); if (op == SET_AUTOPUSH || op == CLR_AUTOPUSH) { error = ldi_open_by_name(SAD_ADM, FREAD|FWRITE, - CRED(), &lh, li); + kcred, &lh, li); if (error) { printf("kstr_autopush: open failed error %d\n", error); ldi_ident_release(li); @@ -236,7 +235,7 @@ kstr_autopush(int op, major_t *maj, minor_t *min, minor_t *lastmin, } } else { error = ldi_open_by_name(SAD_USR, FREAD|FWRITE, - CRED(), &lh, li); + kcred, &lh, li); if (error) { printf("kstr_autopush: open failed error %d\n", error); ldi_ident_release(li); @@ -253,11 +252,11 @@ kstr_autopush(int op, major_t *maj, minor_t *min, minor_t *lastmin, push.sap_minor = *min; error = ldi_ioctl(lh, SAD_GAP, (intptr_t)&push, - FKIOCTL, CRED(), &rval); + FKIOCTL, kcred, &rval); if (error) { printf("kstr_autopush: ioctl failed, error %d\n", error); - (void) ldi_close(lh, FREAD|FWRITE, CRED()); + (void) ldi_close(lh, FREAD|FWRITE, kcred); return (error); } switch (push.sap_cmd) { @@ -288,7 +287,7 @@ kstr_autopush(int op, major_t *maj, minor_t *min, minor_t *lastmin, (void) strcpy(mods[i], push.sap_list[i]); mods[i] = NULL; } - (void) ldi_close(lh, FREAD|FWRITE, CRED()); + (void) ldi_close(lh, FREAD|FWRITE, kcred); return (0); case CLR_AUTOPUSH: @@ -299,12 +298,12 @@ kstr_autopush(int op, major_t *maj, minor_t *min, minor_t *lastmin, push.sap_major = *maj; error = ldi_ioctl(lh, SAD_SAP, (intptr_t)&push, - FKIOCTL, CRED(), &rval); + FKIOCTL, kcred, &rval); if (error) { printf("kstr_autopush: ioctl failed, error %d\n", error); } - (void) ldi_close(lh, FREAD|FWRITE, CRED()); + (void) ldi_close(lh, FREAD|FWRITE, kcred); return (error); case SET_AUTOPUSH: @@ -338,16 +337,16 @@ kstr_autopush(int op, major_t *maj, minor_t *min, minor_t *lastmin, push.sap_list[i][0] = '\0'; error = ldi_ioctl(lh, SAD_SAP, (intptr_t)&push, - FKIOCTL, CRED(), &rval); + FKIOCTL, kcred, &rval); if (error) { printf("kstr_autopush: ioctl failed, error %d\n", error); } - (void) ldi_close(lh, FREAD|FWRITE, CRED()); + (void) ldi_close(lh, FREAD|FWRITE, kcred); return (error); default: - (void) ldi_close(lh, FREAD|FWRITE, CRED()); + (void) ldi_close(lh, FREAD|FWRITE, kcred); return (EINVAL); } } diff --git a/usr/src/uts/common/io/ptm.c b/usr/src/uts/common/io/ptm.c index bd4dc10511..7910b58cc8 100644 --- a/usr/src/uts/common/io/ptm.c +++ b/usr/src/uts/common/io/ptm.c @@ -449,6 +449,18 @@ ptmclose(queue_t *rqp, int flag, cred_t *credp) return (0); } +static boolean_t +ptmptsopencb(ptmptsopencb_arg_t arg) +{ + struct pt_ttys *ptmp = (struct pt_ttys *)arg; + boolean_t rval; + + PT_ENTER_READ(ptmp); + rval = (ptmp->pt_nullmsg != NULL); + PT_EXIT_READ(ptmp); + return (rval); +} + /* * The wput procedure will only handle ioctl and flush messages. */ @@ -572,6 +584,41 @@ ptmwput(queue_t *qp, mblk_t *mp) miocack(qp, mp, 0, 0); break; } + case PTMPTSOPENCB: + { + mblk_t *dp; /* ioctl reply data */ + ptmptsopencb_t *ppocb; + + /* only allow the kernel to invoke this ioctl */ + if (iocp->ioc_cr != kcred) { + miocnak(qp, mp, 0, EINVAL); + break; + } + + /* we don't support transparent ioctls */ + ASSERT(iocp->ioc_count != TRANSPARENT); + if (iocp->ioc_count == TRANSPARENT) { + miocnak(qp, mp, 0, EINVAL); + break; + } + + /* allocate a response message */ + dp = allocb(sizeof (ptmptsopencb_t), BPRI_MED); + if (dp == NULL) { + miocnak(qp, mp, 0, EAGAIN); + break; + } + + /* initialize the ioctl results */ + ppocb = (ptmptsopencb_t *)dp->b_rptr; + ppocb->ppocb_func = ptmptsopencb; + ppocb->ppocb_arg = (ptmptsopencb_arg_t)ptmp; + + /* send the reply data */ + mioc2ack(mp, dp, sizeof (ptmptsopencb_t), 0); + qreply(qp, mp); + break; + } } break; @@ -643,6 +690,13 @@ ptmwsrv(queue_t *qp) ASSERT(qp->q_ptr); ptmp = (struct pt_ttys *)qp->q_ptr; + + if ((mp = getq(qp)) == NULL) { + /* If there are no messages there's nothing to do. */ + DBG(("leaving ptmwsrv (no messages)\n")); + return; + } + PT_ENTER_READ(ptmp); if ((ptmp->pt_state & PTLOCK) || (ptmp->pts_rdq == NULL)) { DBG(("in master write srv proc but no slave\n")); @@ -652,12 +706,12 @@ ptmwsrv(queue_t *qp) * the user process waiting for ACK/NAK from * the ioctl invocation */ - while ((mp = getq(qp)) != NULL) { + do { if (mp->b_datap->db_type == M_IOCTL) miocnak(qp, mp, 0, EINVAL); else freemsg(mp); - } + } while ((mp = getq(qp)) != NULL); flushq(qp, FLUSHALL); mp = mexchange(NULL, NULL, 2, M_ERROR, -1); @@ -672,7 +726,7 @@ ptmwsrv(queue_t *qp) /* * while there are messages on this write queue... */ - while ((mp = getq(qp)) != NULL) { + do { /* * if don't have control message and cannot put * msg. on slave's read queue, put it back on @@ -689,7 +743,7 @@ ptmwsrv(queue_t *qp) */ DBG(("send message to slave\n")); putnext(ptmp->pts_rdq, mp); - } + } while ((mp = getq(qp)) != NULL); DBG(("leaving ptmwsrv\n")); PT_EXIT_READ(ptmp); } |