diff options
author | Martin Natano <natano@cvs.openbsd.org> | 2018-12-23 11:23:22 +0000 |
---|---|---|
committer | Martin Natano <natano@cvs.openbsd.org> | 2018-12-23 11:23:22 +0000 |
commit | 45e71ecf45d9e41795d9450a5a927dadd365cde8 (patch) | |
tree | 0e2927f47ee5c2b87013937cb2e2a82f93127f67 /regress | |
parent | 835d168825c3ee4be213bcbdb6932afc9c90d080 (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/Makefile | 4 | ||||
-rw-r--r-- | regress/sys/mfs_noperm/Makefile | 34 | ||||
-rw-r--r-- | regress/sys/mfs_noperm/README | 3 | ||||
-rw-r--r-- | regress/sys/mfs_noperm/nopermtest.c | 150 |
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); +} |