aboutsummaryrefslogtreecommitdiffstats
path: root/tests/zfs-tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/zfs-tests')
-rw-r--r--tests/zfs-tests/tests/functional/suid/Makefile.am1
-rw-r--r--tests/zfs-tests/tests/functional/suid/suid_write_to_file.c150
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_zil_replay.ksh99
7 files changed, 179 insertions, 79 deletions
diff --git a/tests/zfs-tests/tests/functional/suid/Makefile.am b/tests/zfs-tests/tests/functional/suid/Makefile.am
index 594d2b77c..0145c1205 100644
--- a/tests/zfs-tests/tests/functional/suid/Makefile.am
+++ b/tests/zfs-tests/tests/functional/suid/Makefile.am
@@ -7,6 +7,7 @@ dist_pkgdata_SCRIPTS = \
suid_write_to_sgid.ksh \
suid_write_to_suid_sgid.ksh \
suid_write_to_none.ksh \
+ suid_write_zil_replay.ksh \
cleanup.ksh \
setup.ksh
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_file.c b/tests/zfs-tests/tests/functional/suid/suid_write_to_file.c
index 571dc553b..f3febb903 100644
--- a/tests/zfs-tests/tests/functional/suid/suid_write_to_file.c
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_file.c
@@ -29,86 +29,16 @@
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
-
-static void
-test_stat_mode(mode_t extra)
-{
- struct stat st;
- int i, fd;
- char fpath[1024];
- char *penv[] = {"TESTDIR", "TESTFILE0"};
- char buf[] = "test";
- mode_t res;
- mode_t mode = 0777 | extra;
-
- /*
- * Get the environment variable values.
- */
- for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
- if ((penv[i] = getenv(penv[i])) == NULL) {
- fprintf(stderr, "getenv(penv[%d])\n", i);
- exit(1);
- }
- }
-
- umask(0);
- if (stat(penv[0], &st) == -1 && mkdir(penv[0], mode) == -1) {
- perror("mkdir");
- exit(2);
- }
-
- snprintf(fpath, sizeof (fpath), "%s/%s", penv[0], penv[1]);
- unlink(fpath);
- if (stat(fpath, &st) == 0) {
- fprintf(stderr, "%s exists\n", fpath);
- exit(3);
- }
-
- fd = creat(fpath, mode);
- if (fd == -1) {
- perror("creat");
- exit(4);
- }
- close(fd);
-
- if (setuid(65534) == -1) {
- perror("setuid");
- exit(5);
- }
-
- fd = open(fpath, O_RDWR);
- if (fd == -1) {
- perror("open");
- exit(6);
- }
-
- if (write(fd, buf, sizeof (buf)) == -1) {
- perror("write");
- exit(7);
- }
- close(fd);
-
- if (stat(fpath, &st) == -1) {
- perror("stat");
- exit(8);
- }
- unlink(fpath);
-
- /* Verify SUID/SGID are dropped */
- res = st.st_mode & (0777 | S_ISUID | S_ISGID);
- if (res != (mode & 0777)) {
- fprintf(stderr, "stat(2) %o\n", res);
- exit(9);
- }
-}
+#include <stdbool.h>
int
main(int argc, char *argv[])
{
- const char *name;
+ const char *name, *phase;
mode_t extra;
+ struct stat st;
- if (argc < 2) {
+ if (argc < 3) {
fprintf(stderr, "Invalid argc\n");
exit(1);
}
@@ -127,7 +57,77 @@ main(int argc, char *argv[])
exit(1);
}
- test_stat_mode(extra);
+ const char *testdir = getenv("TESTDIR");
+ if (!testdir) {
+ fprintf(stderr, "getenv(TESTDIR)\n");
+ exit(1);
+ }
+
+ umask(0);
+ if (stat(testdir, &st) == -1 && mkdir(testdir, 0777) == -1) {
+ perror("mkdir");
+ exit(2);
+ }
+
+ char fpath[1024];
+ snprintf(fpath, sizeof (fpath), "%s/%s", testdir, name);
+
+
+ phase = argv[2];
+ if (strcmp(phase, "PRECRASH") == 0) {
+
+ /* clean up last run */
+ unlink(fpath);
+ if (stat(fpath, &st) == 0) {
+ fprintf(stderr, "%s exists\n", fpath);
+ exit(3);
+ }
+
+ int fd;
+
+ fd = creat(fpath, 0777 | extra);
+ if (fd == -1) {
+ perror("creat");
+ exit(4);
+ }
+ close(fd);
+
+ if (setuid(65534) == -1) {
+ perror("setuid");
+ exit(5);
+ }
+
+ fd = open(fpath, O_RDWR);
+ if (fd == -1) {
+ perror("open");
+ exit(6);
+ }
+
+ const char buf[] = "test";
+ if (write(fd, buf, sizeof (buf)) == -1) {
+ perror("write");
+ exit(7);
+ }
+ close(fd);
+
+ } else if (strcmp(phase, "REPLAY") == 0) {
+ /* created in PRECRASH run */
+ } else {
+ fprintf(stderr, "Invalid phase %s\n", phase);
+ exit(1);
+ }
+
+ if (stat(fpath, &st) == -1) {
+ perror("stat");
+ exit(8);
+ }
+
+ /* Verify SUID/SGID are dropped */
+ mode_t res = st.st_mode & (0777 | S_ISUID | S_ISGID);
+ if (res != 0777) {
+ fprintf(stderr, "stat(2) %o\n", res);
+ exit(9);
+ }
return (0);
}
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh
index dd0197861..470350f96 100755
--- a/tests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh
@@ -47,6 +47,6 @@ function cleanup
log_onexit cleanup
log_note "Verify write(2) to regular file by non-owner"
-log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "NONE"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "NONE" "PRECRASH"
log_pass "Verify write(2) to regular file by non-owner passed"
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh
index 49ae2bd1b..3c95a4026 100755
--- a/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh
@@ -47,6 +47,6 @@ function cleanup
log_onexit cleanup
log_note "Verify write(2) to SGID file by non-owner"
-log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SGID"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SGID" "PRECRASH"
log_pass "Verify write(2) to SGID file by non-owner passed"
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh
index 3983aad2e..4183cbeef 100755
--- a/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh
@@ -47,6 +47,6 @@ function cleanup
log_onexit cleanup
log_note "Verify write(2) to SUID file by non-owner"
-log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID" "PRECRASH"
log_pass "Verify write(2) to SUID file by non-owner passed"
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh
index a058c7e7d..f7a08a55f 100755
--- a/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh
@@ -47,6 +47,6 @@ function cleanup
log_onexit cleanup
log_note "Verify write(2) to SUID/SGID file by non-owner"
-log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID_SGID"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID_SGID" "PRECRASH"
log_pass "Verify write(2) to SUID/SGID file by non-owner passed"
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_zil_replay.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_zil_replay.ksh
new file mode 100755
index 000000000..81f431f6b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_zil_replay.ksh
@@ -0,0 +1,99 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# 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.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+verify_runnable "global"
+
+function cleanup_fs
+{
+ cleanup
+}
+
+log_assert "Verify ZIL replay results in correct SUID/SGID bits for unprivileged write to SUID/SGID files"
+log_onexit cleanup_fs
+log_must setup
+
+#
+# 1. Create a file system (TESTFS)
+#
+log_must zpool destroy "$TESTPOOL"
+log_must zpool create $TESTPOOL $VDEV log mirror $LDEV
+log_must zfs set compression=on $TESTPOOL
+log_must zfs create -o mountpoint="$TESTDIR" $TESTPOOL/$TESTFS
+
+# Make all the writes from suid_write_to_file.c sync
+log_must zfs set sync=always "$TESTPOOL/$TESTFS"
+
+#
+# This dd command works around an issue where ZIL records aren't created
+# after freezing the pool unless a ZIL header already exists. Create a file
+# synchronously to force ZFS to write one out.
+#
+log_must dd if=/dev/zero of=$TESTDIR/sync \
+ conv=fdatasync,fsync bs=1 count=1
+
+#
+# 2. Freeze TESTFS
+#
+log_must zpool freeze $TESTPOOL
+
+#
+# 3. Unprivileged write to a setuid file
+#
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "NONE" "PRECRASH"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID" "PRECRASH"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SGID" "PRECRASH"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID_SGID" "PRECRASH"
+
+#
+# 4. Unmount filesystem and export the pool
+#
+# At this stage TESTFS is empty again and frozen, the intent log contains
+# a complete set of deltas to replay.
+#
+log_must zfs unmount $TESTPOOL/$TESTFS
+
+log_note "List transactions to replay:"
+log_must zdb -iv $TESTPOOL/$TESTFS
+
+log_must zpool export $TESTPOOL
+
+#
+# 5. Remount TESTFS <which replays the intent log>
+#
+# Import the pool to unfreeze it and claim log blocks. It has to be
+# `zpool import -f` because we can't write a frozen pool's labels!
+#
+log_must zpool import -f -d $VDIR $TESTPOOL
+
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "NONE" "REPLAY"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID" "REPLAY"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SGID" "REPLAY"
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID_SGID" "REPLAY"
+
+log_pass