summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io')
-rw-r--r--usr/src/uts/common/io/gentty.c114
-rw-r--r--usr/src/uts/common/io/l_strplumb.c27
-rw-r--r--usr/src/uts/common/io/ptm.c62
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);
}