summaryrefslogtreecommitdiff
path: root/regress
diff options
context:
space:
mode:
authorMartin Natano <natano@cvs.openbsd.org>2018-12-23 11:23:22 +0000
committerMartin Natano <natano@cvs.openbsd.org>2018-12-23 11:23:22 +0000
commit45e71ecf45d9e41795d9450a5a927dadd365cde8 (patch)
tree0e2927f47ee5c2b87013937cb2e2a82f93127f67 /regress
parent835d168825c3ee4be213bcbdb6932afc9c90d080 (diff)
Add regress suite for the noperm mfs mount flag. Protection of the root vnode
should be effective now. Let's make sure it stays that way.
Diffstat (limited to 'regress')
-rw-r--r--regress/sys/Makefile4
-rw-r--r--regress/sys/mfs_noperm/Makefile34
-rw-r--r--regress/sys/mfs_noperm/README3
-rw-r--r--regress/sys/mfs_noperm/nopermtest.c150
4 files changed, 189 insertions, 2 deletions
diff --git a/regress/sys/Makefile b/regress/sys/Makefile
index a43b917d757..2586d2ef6b8 100644
--- a/regress/sys/Makefile
+++ b/regress/sys/Makefile
@@ -1,7 +1,7 @@
-# $OpenBSD: Makefile,v 1.25 2017/05/29 11:59:32 sf Exp $
+# $OpenBSD: Makefile,v 1.26 2018/12/23 11:23:21 natano Exp $
# $NetBSD: Makefile,v 1.4 1995/04/20 22:41:08 cgd Exp $
-SUBDIR= copy crypto dev ddb ffs fifofs fileops kern \
+SUBDIR= copy crypto dev ddb ffs fifofs fileops kern mfs_noperm \
net netinet netinet6 nfs ptrace sys uvm
.if exists(arch/${MACHINE}/Makefile)
SUBDIR+= arch/${MACHINE}
diff --git a/regress/sys/mfs_noperm/Makefile b/regress/sys/mfs_noperm/Makefile
new file mode 100644
index 00000000000..35f634a48eb
--- /dev/null
+++ b/regress/sys/mfs_noperm/Makefile
@@ -0,0 +1,34 @@
+# $OpenBSD: Makefile,v 1.1 2018/12/23 11:23:21 natano Exp $
+
+PROG= nopermtest
+CDIAGFLAGS= -Wall
+#CDIAGFLAGS+= -Werror
+CDIAGFLAGS+= -Wpointer-arith
+CDIAGFLAGS+= -Wno-uninitialized
+CDIAGFLAGS+= -Wstrict-prototypes
+CDIAGFLAGS+= -Wmissing-prototypes
+CDIAGFLAGS+= -Wunused
+CDIAGFLAGS+= -Wsign-compare
+CDIAGFLAGS+= -Wshadow
+
+REGRESS_SETUP_ONCE= mount
+REGRESS_CLEANUP= umount
+REGRESS_TARGETS= run-regress-locked run-regress-unlocked
+
+mount:
+ mount_mfs -s1M -o noperm swap /mnt
+
+umount:
+ umount -f /mnt
+
+run-regress-locked: ${PROG}
+ chown root:wheel /mnt
+ chmod 700 /mnt
+ su build -c './${PROG} /mnt locked'
+
+run-regress-unlocked: ${PROG}
+ chown build /mnt
+ chmod 700 /mnt
+ su build -c './${PROG} /mnt unlocked'
+
+.include <bsd.regress.mk>
diff --git a/regress/sys/mfs_noperm/README b/regress/sys/mfs_noperm/README
new file mode 100644
index 00000000000..972a332c057
--- /dev/null
+++ b/regress/sys/mfs_noperm/README
@@ -0,0 +1,3 @@
+ $OpenBSD: README,v 1.1 2018/12/23 11:23:21 natano Exp $
+
+These tests must be run as root, /mnt must be clean.
diff --git a/regress/sys/mfs_noperm/nopermtest.c b/regress/sys/mfs_noperm/nopermtest.c
new file mode 100644
index 00000000000..a35e3697395
--- /dev/null
+++ b/regress/sys/mfs_noperm/nopermtest.c
@@ -0,0 +1,150 @@
+/* $OpenBSD: nopermtest.c,v 1.1 2018/12/23 11:23:21 natano Exp $ */
+
+/*
+ * Copyright (c) 2018 Martin Natano <natano@natano.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define EXPECT_OK(expr) do { \
+ int r = (expr); \
+ if (r == -1) { \
+ fprintf(stderr, "FAIL:%d: %s -> r=%d errno=%d(%s)\n", \
+ __LINE__, #expr, r, errno, strerror(errno)); \
+ nfail++; \
+ } \
+} while (0)
+
+#define EXPECT_ERRNO(expr, expected_errno) do { \
+ int r = (expr); \
+ if (r != -1 || errno != expected_errno) { \
+ fprintf(stderr, "FAIL:%d: %s -> r=%d errno=%d(%s)\n", \
+ __LINE__, #expr, r, errno, strerror(errno)); \
+ nfail++; \
+ } \
+} while (0)
+
+static void check_locked(const char *);
+static void check_unlocked(const char *);
+static void check_unlocked_vroot(void);
+static void check_unlocked_subdir(void);
+
+__dead static void usage(void);
+
+static int nfail;
+
+int
+main(int argc, char **argv)
+{
+ const char *mnt, *stage;
+ const char *errstr;
+
+ if (argc != 3)
+ usage();
+
+ mnt = argv[1];
+ stage = argv[2];
+
+ if (strcmp(stage, "locked") == 0)
+ check_locked(mnt);
+ else if (strcmp(stage, "unlocked") == 0)
+ check_unlocked(mnt);
+ else
+ usage();
+
+ return (nfail > 0);
+}
+
+static void
+check_locked(const char *mnt)
+{
+ char path[PATH_MAX];
+
+ EXPECT_OK(access(mnt, F_OK));
+ EXPECT_ERRNO(access(mnt, R_OK), EACCES);
+ EXPECT_ERRNO(access(mnt, W_OK), EACCES);
+ EXPECT_ERRNO(access(mnt, X_OK), EACCES);
+
+ (void)snprintf(path, PATH_MAX, "%s/stdin", mnt);
+ EXPECT_ERRNO(mknod(path, S_IFCHR | 0700, makedev(22, 0)), EACCES);
+
+ EXPECT_ERRNO(chown(mnt, getuid(), -1), EPERM);
+ EXPECT_ERRNO(chmod(mnt, 0700), EPERM);
+ EXPECT_ERRNO(chflags(mnt, SF_ARCHIVED), EPERM);
+ EXPECT_ERRNO(utimes(mnt, NULL), EACCES);
+}
+
+static void
+check_unlocked(const char *mnt)
+{
+ if (chdir(mnt) == -1)
+ err(1, "chdir");
+
+ check_unlocked_vroot();
+ check_unlocked_subdir();
+}
+
+static void
+check_unlocked_vroot(void)
+{
+ int fd;
+
+ EXPECT_OK(access(".", R_OK | W_OK | X_OK));
+
+ EXPECT_ERRNO(mknod("stdin", S_IFCHR | 0700, makedev(22, 0)), EPERM);
+
+ EXPECT_ERRNO(chown(".", 0, -1), EPERM);
+ EXPECT_OK(chmod(".", 0700));
+ EXPECT_ERRNO(chflags(".", SF_ARCHIVED), EPERM);
+ EXPECT_OK(utimes(".", NULL));
+}
+
+static void
+check_unlocked_subdir(void)
+{
+ if (mkdir("sub", 0000) == -1)
+ err(1, "mkdir");
+
+ EXPECT_OK(access("sub", R_OK | W_OK | X_OK));
+
+ EXPECT_OK(mknod("sub/stdin", S_IFCHR | 0700, makedev(22, 0)));
+
+ EXPECT_OK(chown("sub", 0, -1));
+ EXPECT_OK(chmod("sub", 0000));
+ EXPECT_OK(chflags("sub", SF_ARCHIVED));
+ EXPECT_OK(utimes("sub", NULL));
+
+ EXPECT_OK(chmod("sub", S_ISVTX | 0700));
+ EXPECT_OK(chown("sub/stdin", 0, -1));
+ EXPECT_OK(rename("sub/stdin", "sub/stdin2"));
+ EXPECT_OK(unlink("sub/stdin2"));
+}
+
+__dead static void
+usage(void)
+{
+ (void)fprintf(stderr, "usage: %s mnt stage\n", getprogname());
+ exit(1);
+}