summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Zezeski <rpz@joyent.com>2016-12-29 08:20:14 -0800
committerRobert Mustacchi <rm@joyent.com>2017-02-01 09:28:35 -0800
commitdefc4c8acfa01dba1ef3c13ca0cafccfcede51c0 (patch)
tree9cd62c9e49328972d9275c66099c128dabfa3f77
parent80e10fd0d22bbf0d18bfdae035e06f44c68ae8e6 (diff)
downloadillumos-joyent-defc4c8acfa01dba1ef3c13ca0cafccfcede51c0.tar.gz
7719 sdev_create() doesn't enforce EISDIR in non-GZ
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> Reviewed by: Andy Stormont <astormont@racktopsystems.com> Reviewed by: Dan McDonald <danmcd@omniti.com> Approved by: Dan McDonald <danmcd@omniti.com>
-rw-r--r--usr/src/pkg/manifests/system-test-ostest.mf2
-rw-r--r--usr/src/test/os-tests/runfiles/default.run5
-rw-r--r--usr/src/test/os-tests/tests/Makefile2
-rw-r--r--usr/src/test/os-tests/tests/sdevfs/Makefile47
-rw-r--r--usr/src/test/os-tests/tests/sdevfs/sdevfs_eisdir.c73
-rw-r--r--usr/src/uts/common/fs/dev/sdev_vnops.c32
6 files changed, 158 insertions, 3 deletions
diff --git a/usr/src/pkg/manifests/system-test-ostest.mf b/usr/src/pkg/manifests/system-test-ostest.mf
index 4f037a7749..c4c6d98836 100644
--- a/usr/src/pkg/manifests/system-test-ostest.mf
+++ b/usr/src/pkg/manifests/system-test-ostest.mf
@@ -26,6 +26,7 @@ dir path=opt/os-tests/bin
dir path=opt/os-tests/runfiles
dir path=opt/os-tests/tests
dir path=opt/os-tests/tests/file-locking
+dir path=opt/os-tests/tests/sdevfs
dir path=opt/os-tests/tests/secflags
dir path=opt/os-tests/tests/sigqueue
file path=opt/os-tests/README mode=0444
@@ -37,6 +38,7 @@ file path=opt/os-tests/tests/file-locking/acquire-lock.64 mode=0555
file path=opt/os-tests/tests/file-locking/runtests.32 mode=0555
file path=opt/os-tests/tests/file-locking/runtests.64 mode=0555
file path=opt/os-tests/tests/poll_test mode=0555
+file path=opt/os-tests/tests/sdevfs/sdevfs_eisdir mode=0555
file path=opt/os-tests/tests/secflags/addrs-32 mode=0555
file path=opt/os-tests/tests/secflags/addrs-64 mode=0555
file path=opt/os-tests/tests/secflags/secflags_aslr mode=0555
diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run
index 8f36276de4..8b7e82f916 100644
--- a/usr/src/test/os-tests/runfiles/default.run
+++ b/usr/src/test/os-tests/runfiles/default.run
@@ -11,6 +11,7 @@
#
# Copyright (c) 2012 by Delphix. All rights reserved.
+# Copyright 2016 Joyent, Inc.
#
[DEFAULT]
@@ -43,5 +44,9 @@ tests = ['secflags_aslr',
[/opt/os-tests/tests/sigqueue]
tests = ['sigqueue_queue_size']
+[/opt/os-tests/tests/sdevfs]
+user = root
+tests = ['sdevfs_eisdir']
+
[/opt/os-tests/tests/file-locking]
tests = ['runtests.32', 'runtests.64']
diff --git a/usr/src/test/os-tests/tests/Makefile b/usr/src/test/os-tests/tests/Makefile
index 42219ce8fb..6b6e0f9fce 100644
--- a/usr/src/test/os-tests/tests/Makefile
+++ b/usr/src/test/os-tests/tests/Makefile
@@ -13,6 +13,6 @@
# Copyright (c) 2012 by Delphix. All rights reserved.
#
-SUBDIRS = poll secflags sigqueue spoof-ras file-locking
+SUBDIRS = poll secflags sigqueue spoof-ras sdevfs file-locking
include $(SRC)/test/Makefile.com
diff --git a/usr/src/test/os-tests/tests/sdevfs/Makefile b/usr/src/test/os-tests/tests/sdevfs/Makefile
new file mode 100644
index 0000000000..4d72e332b7
--- /dev/null
+++ b/usr/src/test/os-tests/tests/sdevfs/Makefile
@@ -0,0 +1,47 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2016 Joyent, Inc.
+#
+
+include $(SRC)/Makefile.master
+
+ROOTOPTPKG = $(ROOT)/opt/os-tests
+TESTDIR = $(ROOTOPTPKG)/tests/sdevfs
+
+PROGS = sdevfs_eisdir
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/test/Makefile.com
+
+CMDS = $(PROGS:%=$(TESTDIR)/%)
+$(CMDS) := FILEMODE = 0555
+
+all: $(PROGS)
+
+install: all $(CMDS)
+
+lint:
+
+clobber: clean
+ -$(RM) $(PROGS)
+
+clean:
+ -$(RM) *.o
+
+$(CMDS): $(TESTDIR) $(PROGS)
+
+$(TESTDIR):
+ $(INS.dir)
+
+$(TESTDIR)/%: %
+ $(INS.file)
diff --git a/usr/src/test/os-tests/tests/sdevfs/sdevfs_eisdir.c b/usr/src/test/os-tests/tests/sdevfs/sdevfs_eisdir.c
new file mode 100644
index 0000000000..a1cc386ce7
--- /dev/null
+++ b/usr/src/test/os-tests/tests/sdevfs/sdevfs_eisdir.c
@@ -0,0 +1,73 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2016 Joyent, Inc.
+ */
+
+/*
+ * open(2) should return EISDIR when asking for write access on a dir.
+ * This test should return the same results in both GZ and NGZ contexts.
+ */
+#include <stdio.h>
+#include <strings.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/debug.h>
+#include <sys/statvfs.h>
+
+#define SD_TEST_DIR "/dev/zvol"
+
+int
+main(int argc, char *argv[])
+{
+ struct stat st;
+ struct statvfs vfs;
+ int ret;
+
+ if (stat(SD_TEST_DIR, &st) != 0) {
+ fprintf(stderr, "test failed: failed to stat %s\n",
+ SD_TEST_DIR);
+ return (1);
+ }
+
+ if ((st.st_mode & S_IFMT) != S_IFDIR) {
+ fprintf(stderr, "test failed: %s is not a dir\n", SD_TEST_DIR);
+ return (1);
+ }
+
+ if (statvfs(SD_TEST_DIR, &vfs) != 0) {
+ fprintf(stderr, "test failed: failed to stat vfs for %s: %s\n",
+ SD_TEST_DIR, strerror(errno));
+ return (1);
+ }
+
+ if (strncmp("dev", vfs.f_basetype, FSTYPSZ) != 0) {
+ fprintf(stderr, "test failed: asked to run on non-dev\n");
+ return (1);
+ }
+
+ ret = open(SD_TEST_DIR, O_RDWR, 0);
+ VERIFY3S(ret, ==, -1);
+ VERIFY3S(errno, ==, EISDIR);
+
+ /*
+ * It's important to test both O_RDWR and O_RDWR | O_CREAT
+ * because of the different code paths taken in sdev.
+ */
+ ret = open(SD_TEST_DIR, O_RDWR | O_CREAT, 0);
+ VERIFY3S(ret, ==, -1);
+ VERIFY3S(errno, ==, EISDIR);
+
+ return (0);
+}
diff --git a/usr/src/uts/common/fs/dev/sdev_vnops.c b/usr/src/uts/common/fs/dev/sdev_vnops.c
index 59a3c9f17a..79ebd8b2e5 100644
--- a/usr/src/uts/common/fs/dev/sdev_vnops.c
+++ b/usr/src/uts/common/fs/dev/sdev_vnops.c
@@ -660,10 +660,38 @@ sdev_create(struct vnode *dvp, char *nm, struct vattr *vap, vcexcl_t excl,
return (ENOENT);
}
- /* non-global do not allow pure node creation */
+ /*
+ * Nodes cannot be created in NGZ context.
+ */
if (!SDEV_IS_GLOBAL(parent)) {
rw_exit(&parent->sdev_dotdot->sdev_contents);
- return (prof_lookup(dvp, nm, vpp, cred));
+ error = prof_lookup(dvp, nm, vpp, cred);
+
+ /*
+ * In this case, we can't create a vnode but we can
+ * open an existing one. However, we still want to
+ * enforce the open(2) error semantics as if this was
+ * a regular sdev_create() in GZ context. Since we
+ * know the vnode already exists (error == 0) we a)
+ * return EEXIST if exclusive access was requested, or
+ * b) return EISDIR if write access was requested on a
+ * directory. Otherwise, we return the value from
+ * prof_lookup() as is.
+ */
+ if (error == 0) {
+ if (excl == EXCL) {
+ error = EEXIST;
+ } else if (((*vpp)->v_type == VDIR) &&
+ (mode & VWRITE)) {
+ error = EISDIR;
+ }
+
+ if (error != 0)
+ VN_RELE(*vpp);
+ }
+
+
+ return (error);
}
rw_exit(&parent->sdev_dotdot->sdev_contents);