summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorvikram <none@none>2007-01-18 13:37:08 -0800
committervikram <none@none>2007-01-18 13:37:08 -0800
commit49e92448e558772c002444c0d92e7a31d529d046 (patch)
tree7b94e27cf3cd12b5392a5d30c228f4c10e66be53 /usr/src
parentc7ce59f142277983e66b3701901be4f1c31e57c8 (diff)
downloadillumos-joyent-49e92448e558772c002444c0d92e7a31d529d046.tar.gz
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
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/modload/drvsubr.c63
-rw-r--r--usr/src/cmd/modload/errmsg.h8
-rw-r--r--usr/src/cmd/truss/codes.c3
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/ioctl.c6
-rw-r--r--usr/src/lib/libc/port/gen/pt.c4
-rw-r--r--usr/src/uts/common/fs/dev/sdev_ptsops.c24
-rw-r--r--usr/src/uts/common/io/ptm.c4
-rw-r--r--usr/src/uts/common/sys/ptms.h4
8 files changed, 74 insertions, 42 deletions
diff --git a/usr/src/cmd/modload/drvsubr.c b/usr/src/cmd/modload/drvsubr.c
index 00c4a03786..f1fb38add3 100644
--- a/usr/src/cmd/modload/drvsubr.c
+++ b/usr/src/cmd/modload/drvsubr.c
@@ -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 @@ get_entry(
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 @@ cleanup_moddir(void)
void
exit_unlock(void)
{
- struct stat buf;
+ struct flock unlock;
- if (stat(add_rem_lock, &buf) == NOERR) {
- if (unlink(add_rem_lock) == -1) {
- (void) fprintf(stderr, gettext(ERR_REM_LOCK),
- add_rem_lock);
- }
+ if (add_rem_lock_fd < 0)
+ return;
+
+ 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;
}
}
diff --git a/usr/src/cmd/modload/errmsg.h b/usr/src/cmd/modload/errmsg.h
index bc41755678..6412f4d24b 100644
--- a/usr/src/cmd/modload/errmsg.h
+++ b/usr/src/cmd/modload/errmsg.h
@@ -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 @@ extern "C" {
#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 @@ extern "C" {
"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"
diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c
index fe5a173211..b27be91c7b 100644
--- a/usr/src/cmd/truss/codes.c
+++ b/usr/src/cmd/truss/codes.c
@@ -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 @@ const struct ioc {
{ (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"},
diff --git a/usr/src/lib/brand/lx/lx_brand/common/ioctl.c b/usr/src/lib/brand/lx/lx_brand/common/ioctl.c
index b6a6b79ad1..f9b2668700 100644
--- a/usr/src/lib/brand/lx/lx_brand/common/ioctl.c
+++ b/usr/src/lib/brand/lx/lx_brand/common/ioctl.c
@@ -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 @@ ict_gptn(int fd, struct stat *stat, int cmd, char *cmd_str, intptr_t arg)
* 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. */
diff --git a/usr/src/lib/libc/port/gen/pt.c b/usr/src/lib/libc/port/gen/pt.c
index 86bcd319c3..1272c947eb 100644
--- a/usr/src/lib/libc/port/gen/pt.c
+++ b/usr/src/lib/libc/port/gen/pt.c
@@ -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 @@ grantpt(int fd)
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;
diff --git a/usr/src/uts/common/fs/dev/sdev_ptsops.c b/usr/src/uts/common/fs/dev/sdev_ptsops.c
index 9ab5cf8881..50ed639ddb 100644
--- a/usr/src/uts/common/fs/dev/sdev_ptsops.c
+++ b/usr/src/uts/common/fs/dev/sdev_ptsops.c
@@ -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 @@ devpts_prunedir(struct sdev_node *ddv)
* 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 @@ devpts_lookup(struct vnode *dvp, char *nm, struct vnode **vpp,
{
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 @@ devpts_lookup(struct vnode *dvp, char *nm, struct vnode **vpp,
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_setattr(struct vnode *vp, struct vattr *vap, int flags,
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
diff --git a/usr/src/uts/common/io/ptm.c b/usr/src/uts/common/io/ptm.c
index 7910b58cc8..aaa4886069 100644
--- a/usr/src/uts/common/io/ptm.c
+++ b/usr/src/uts/common/io/ptm.c
@@ -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 @@ ptmwput(queue_t *qp, mblk_t *mp)
miocack(qp, mp, 0, 0);
break;
}
- case PT_OWNER:
+ case OWNERPT:
{
pt_own_t *ptop;
int error;
diff --git a/usr/src/uts/common/sys/ptms.h b/usr/src/uts/common/sys/ptms.h
index 120503539b..458022ebc8 100644
--- a/usr/src/uts/common/sys/ptms.h
+++ b/usr/src/uts/common/sys/ptms.h
@@ -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 @@ typedef struct pt_own {
#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
/*