diff options
| author | Ryan Zezeski <rpz@joyent.com> | 2016-12-29 08:20:14 -0800 |
|---|---|---|
| committer | Robert Mustacchi <rm@joyent.com> | 2017-02-01 09:28:35 -0800 |
| commit | defc4c8acfa01dba1ef3c13ca0cafccfcede51c0 (patch) | |
| tree | 9cd62c9e49328972d9275c66099c128dabfa3f77 | |
| parent | 80e10fd0d22bbf0d18bfdae035e06f44c68ae8e6 (diff) | |
| download | illumos-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.mf | 2 | ||||
| -rw-r--r-- | usr/src/test/os-tests/runfiles/default.run | 5 | ||||
| -rw-r--r-- | usr/src/test/os-tests/tests/Makefile | 2 | ||||
| -rw-r--r-- | usr/src/test/os-tests/tests/sdevfs/Makefile | 47 | ||||
| -rw-r--r-- | usr/src/test/os-tests/tests/sdevfs/sdevfs_eisdir.c | 73 | ||||
| -rw-r--r-- | usr/src/uts/common/fs/dev/sdev_vnops.c | 32 |
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); |
