changeset 3442:770844b0f91a

6445040 add_drv/update_drv/rem_drv should use advisory record locking 6467524 Add a check to /dev/pts code to test for realvp 6509851 change name of PT_OWNER ioctl to OWNERPT
author vikram
date Thu, 18 Jan 2007 13:37:08 -0800
parents 00abce5a0b16
children e0e00ef6cee8
files usr/src/cmd/modload/drvsubr.c usr/src/cmd/modload/errmsg.h usr/src/cmd/truss/codes.c usr/src/lib/brand/lx/lx_brand/common/ioctl.c usr/src/lib/libc/port/gen/pt.c usr/src/uts/common/fs/dev/sdev_ptsops.c usr/src/uts/common/io/ptm.c usr/src/uts/common/sys/ptms.h
diffstat 8 files changed, 74 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/modload/drvsubr.c	Thu Jan 18 08:49:43 2007 -0800
+++ b/usr/src/cmd/modload/drvsubr.c	Thu Jan 18 13:37:08 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -45,6 +45,7 @@
 
 static char *add_rem_lock;	/* lock file */
 static char *tmphold;		/* temperary file for updating */
+static int  add_rem_lock_fd = -1;
 
 static int get_cached_n_to_m_file(char *filename, char ***cache);
 static int get_name_to_major_entry(int *major_no, char *driver_name,
@@ -648,39 +649,36 @@
 	return (ptr);
 }
 
-/*ARGSUSED0*/
-static void
-signal_rtn(int sig)
-{
-	exit_unlock();
-}
-
 void
 enter_lock(void)
 {
-	int fd;
-
-	/*
-	 * Setup handler to clean lock file in case user terminates
-	 * the command.
-	 */
-	(void) sigset(SIGINT, signal_rtn);
-	(void) sigset(SIGHUP, signal_rtn);
-	(void) sigset(SIGTERM, signal_rtn);
+	struct flock lock;
 
 	/*
 	 * attempt to create the lock file
 	 */
-	if ((fd = open(add_rem_lock, O_CREAT | O_EXCL | O_WRONLY,
-	    S_IRUSR | S_IWUSR)) == -1) {
-		if (errno == EEXIST) {
+	add_rem_lock_fd = open(add_rem_lock, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
+	if (add_rem_lock_fd < 0) {
+		(void) fprintf(stderr, gettext(ERR_CREAT_LOCK),
+		    add_rem_lock, strerror(errno));
+		exit(1);
+	}
+
+	lock.l_type = F_WRLCK;
+	lock.l_whence = SEEK_SET;
+	lock.l_start = 0;
+	lock.l_len = 0;
+
+	/* Try for the lock but don't wait. */
+	if (fcntl(add_rem_lock_fd, F_SETLK, &lock) == -1) {
+		if (errno == EACCES || errno == EAGAIN) {
 			(void) fprintf(stderr, gettext(ERR_PROG_IN_USE));
 		} else {
-			perror(gettext(ERR_LOCKFILE));
+			(void) fprintf(stderr, gettext(ERR_LOCK),
+			    add_rem_lock, strerror(errno));
 		}
 		exit(1);
 	}
-	(void) close(fd);
 }
 
 void
@@ -709,13 +707,22 @@
 void
 exit_unlock(void)
 {
-	struct stat buf;
+	struct flock unlock;
+
+	if (add_rem_lock_fd < 0)
+		return;
 
-	if (stat(add_rem_lock, &buf) == NOERR) {
-		if (unlink(add_rem_lock) == -1) {
-			(void) fprintf(stderr, gettext(ERR_REM_LOCK),
-			    add_rem_lock);
-		}
+	unlock.l_type = F_UNLCK;
+	unlock.l_whence = SEEK_SET;
+	unlock.l_start = 0;
+	unlock.l_len = 0;
+
+	if (fcntl(add_rem_lock_fd, F_SETLK, &unlock) == -1) {
+		(void) fprintf(stderr, gettext(ERR_UNLOCK),
+		    add_rem_lock, strerror(errno));
+	} else {
+		(void) close(add_rem_lock_fd);
+		add_rem_lock_fd = -1;
 	}
 }
 
--- a/usr/src/cmd/modload/errmsg.h	Thu Jan 18 08:49:43 2007 -0800
+++ b/usr/src/cmd/modload/errmsg.h	Thu Jan 18 13:37:08 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -59,7 +59,6 @@
 #define	ERR_ALIAS_IN_NAM_MAJ	"Alias (%s) already in use as driver name.\n"
 #define	ERR_ALIAS_IN_USE	"(%s) already in use as a driver or alias.\n"
 #define	ERR_CANT_ACCESS_FILE	"Cannot access file (%s).\n"
-#define	ERR_REM_LOCK		"Cannot remove lockfile (%s). Remove by hand.\n"
 #define	ERR_BAD_PATH	"Bad syntax for pathname : (%s)\n"
 #define	ERR_FORK_FAIL	"Fork failed; cannot exec : %s\n"
 #define	ERR_PROG_IN_USE	"add_drv/rem_drv currently busy; try later\n"
@@ -95,7 +94,10 @@
 "Warning: Major number (%d) inconsistent with /etc/name_to_major file.\n"
 #define	ERR_MAJ_TOOBIG	"Warning: Entry '%s %llu' in %s has a major number " \
 			"larger\nthan the maximum allowed value %u.\n"
-#define	ERR_LOCKFILE	"Failed to create lock file.\n"
+
+#define	ERR_CREAT_LOCK	"Failed to create lock file(%s): %s\n"
+#define	ERR_LOCK	"Failed to lock the lock file(%s): %s\n"
+#define	ERR_UNLOCK	"Failed to unlock the lock file(%s): %s\n"
 
 #define	ERR_LOCATION	\
 "Warning: %s-bit version of driver found at %s.\n"
--- a/usr/src/cmd/truss/codes.c	Thu Jan 18 08:49:43 2007 -0800
+++ b/usr/src/cmd/truss/codes.c	Thu Jan 18 13:37:08 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -818,6 +818,7 @@
 	{ (uint_t)UNLKPT,		"UNLKPT",		NULL},
 	{ (uint_t)PTSSTTY,		"PTSSTTY",		NULL},
 	{ (uint_t)ZONEPT,		"ZONEPT",		NULL},
+	{ (uint_t)OWNERPT,		"OWNERPT",		NULL},
 
 	/* aggr link aggregation pseudo driver ioctls */
 	{ (uint_t)LAIOC_CREATE,		"LAIOC_CREATE",		"laioc_create"},
--- a/usr/src/lib/brand/lx/lx_brand/common/ioctl.c	Thu Jan 18 08:49:43 2007 -0800
+++ b/usr/src/lib/brand/lx/lx_brand/common/ioctl.c	Thu Jan 18 13:37:08 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -1202,11 +1202,11 @@
 	 * it assumes the fd node that's passed to it is a ptm node,
 	 * and in our case it's an lx_ptm node.  It also relies on
 	 * naming services to get the current process group name.
-	 * Hence we have to invoke the PT_OWNER ioctl directly here.
+	 * Hence we have to invoke the OWNERPT ioctl directly here.
 	 */
 	pto.pto_ruid = getuid();
 	pto.pto_rgid = getgid();
-	if (ioctl_istr(fd, PT_OWNER, "PT_OWNER", &pto, sizeof (pto)) != 0)
+	if (ioctl_istr(fd, OWNERPT, "OWNERPT", &pto, sizeof (pto)) != 0)
 		return (-EACCES);
 
 	/* Copy out the data. */
--- a/usr/src/lib/libc/port/gen/pt.c	Thu Jan 18 08:49:43 2007 -0800
+++ b/usr/src/lib/libc/port/gen/pt.c	Thu Jan 18 13:37:08 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -156,7 +156,7 @@
 	else
 		pto.pto_rgid = getgid();
 
-	istr.ic_cmd = PT_OWNER;
+	istr.ic_cmd = OWNERPT;
 	istr.ic_len = sizeof (pt_own_t);
 	istr.ic_timout = 0;
 	istr.ic_dp = (char *)&pto;
--- a/usr/src/uts/common/fs/dev/sdev_ptsops.c	Thu Jan 18 08:49:43 2007 -0800
+++ b/usr/src/uts/common/fs/dev/sdev_ptsops.c	Thu Jan 18 13:37:08 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -274,6 +274,25 @@
  * Lookup for /dev/pts directory
  *	If the entry does not exist, the devpts_create_rvp() callback
  *	is invoked to create it. Nodes do not persist across reboot.
+ *
+ * There is a potential denial of service here via
+ * fattach on top of a /dev/pts node - any permission changes
+ * applied to the node, apply to the fattached file and not
+ * to the underlying pts node. As a result when the previous
+ * user fdetaches, the pts node is still owned by the previous
+ * owner. To prevent this we don't allow fattach() on top of a pts
+ * node. This is done by a modification in the namefs filesystem
+ * where we check if the underlying node has the /dev/pts vnodeops.
+ * We do this via VOP_REALVP() on the underlying specfs node.
+ * sdev_nodes currently don't have a realvp. If a realvp is ever
+ * created for sdev_nodes, then VOP_REALVP() will return the
+ * actual realvp (possibly a ufs vnode). This will defeat the check
+ * in namefs code which checks if VOP_REALVP() returns a devpts
+ * node. We add an ASSERT here in /dev/pts lookup() to check for
+ * this condition. If sdev_nodes ever get a VOP_REALVP() entry point,
+ * change the code in the namefs filesystem code (in nm_mount()) to
+ * access the realvp of the specfs node directly instead of using
+ * VOP_REALVP().
  */
 /*ARGSUSED3*/
 static int
@@ -282,6 +301,7 @@
 {
 	struct sdev_node *sdvp = VTOSDEV(dvp);
 	struct sdev_node *dv;
+	struct vnode *rvp = NULL;
 	int error;
 
 	error = devname_lookup_func(sdvp, nm, vpp, cred, devpts_create_rvp,
@@ -291,6 +311,7 @@
 		switch ((*vpp)->v_type) {
 		case VCHR:
 			dv = VTOSDEV(VTOS(*vpp)->s_realvp);
+			ASSERT(VOP_REALVP(SDEVTOV(dv), &rvp) == ENOSYS);
 			break;
 		case VDIR:
 			dv = VTOSDEV(*vpp);
@@ -379,6 +400,7 @@
 		    devpts_set_id, AT_UID|AT_GID));
 }
 
+
 /*
  * We override lookup and readdir to build entries based on the
  * in kernel pty table. Also override setattr/setsecattr to
--- a/usr/src/uts/common/io/ptm.c	Thu Jan 18 08:49:43 2007 -0800
+++ b/usr/src/uts/common/io/ptm.c	Thu Jan 18 13:37:08 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
@@ -560,7 +560,7 @@
 			miocack(qp, mp, 0, 0);
 			break;
 		}
-		case PT_OWNER:
+		case OWNERPT:
 		{
 			pt_own_t *ptop;
 			int error;
--- a/usr/src/uts/common/sys/ptms.h	Thu Jan 18 08:49:43 2007 -0800
+++ b/usr/src/uts/common/sys/ptms.h	Thu Jan 18 13:37:08 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
@@ -164,7 +164,7 @@
 #define	UNLKPT		(('P'<<8)|2)	/* unlock master/slave pair */
 #define	PTSSTTY		(('P'<<8)|3)	/* set tty flag */
 #define	ZONEPT		(('P'<<8)|4)	/* set zone of master/slave pair */
-#define	PT_OWNER	(('P'<<8)|5)	/* set owner/group for slave device */
+#define	OWNERPT		(('P'<<8)|5)	/* set owner/group for slave device */
 
 #ifdef _KERNEL
 /*