summaryrefslogtreecommitdiff
path: root/regress/sys
diff options
context:
space:
mode:
Diffstat (limited to 'regress/sys')
-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);
+}