summaryrefslogtreecommitdiff
path: root/regress/sys/uvm/minherit_zero
diff options
context:
space:
mode:
authorMatthew Dempsky <matthew@cvs.openbsd.org>2014-06-13 07:17:55 +0000
committerMatthew Dempsky <matthew@cvs.openbsd.org>2014-06-13 07:17:55 +0000
commit51fc384bcf4757d13d5947ff3bdda531fc6d2c2b (patch)
tree1ec96c5bec7406661a0d93e28952a33b3d6ac52e /regress/sys/uvm/minherit_zero
parent85eeb1e3a9b977aa3728a40ff49136c90b39d210 (diff)
Add regress test for MAP_INHERIT_ZERO.
Diffstat (limited to 'regress/sys/uvm/minherit_zero')
-rw-r--r--regress/sys/uvm/minherit_zero/Makefile5
-rw-r--r--regress/sys/uvm/minherit_zero/minherit_zero.c130
2 files changed, 135 insertions, 0 deletions
diff --git a/regress/sys/uvm/minherit_zero/Makefile b/regress/sys/uvm/minherit_zero/Makefile
new file mode 100644
index 00000000000..9e054db9f59
--- /dev/null
+++ b/regress/sys/uvm/minherit_zero/Makefile
@@ -0,0 +1,5 @@
+# $OpenBSD: Makefile,v 1.1 2014/06/13 07:17:54 matthew Exp $
+
+PROG= minherit_zero
+
+.include <bsd.regress.mk>
diff --git a/regress/sys/uvm/minherit_zero/minherit_zero.c b/regress/sys/uvm/minherit_zero/minherit_zero.c
new file mode 100644
index 00000000000..e7bfa23f7c1
--- /dev/null
+++ b/regress/sys/uvm/minherit_zero/minherit_zero.c
@@ -0,0 +1,130 @@
+/* $OpenBSD: minherit_zero.c,v 1.1 2014/06/13 07:17:54 matthew Exp $ */
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * 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/mman.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <string.h>
+#include <unistd.h>
+
+#define CHECK(x) assert((x))
+#define CHECK_EQ(a, b) assert((a) == (b))
+#define CHECK_NE(a, b) assert((a) != (b))
+#define CHECK_GE(a, b) assert((a) >= (b))
+
+static int
+ismemset(const void *s, int c, size_t n)
+{
+ const unsigned char *p = s;
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ if (p[i] != c)
+ return (0);
+ return (1);
+}
+
+static void
+wait_for_clean_exit(pid_t pid)
+{
+ int status;
+ CHECK_EQ(pid, waitpid(pid, &status, 0));
+ CHECK(WIFEXITED(status));
+ CHECK_EQ(0, WEXITSTATUS(status));
+}
+
+enum {
+ NPAGES = 4,
+
+ PARENT_BYTE = 42,
+ CHILD_BYTE = 53,
+ GRANDCHILD_BYTE = 65
+};
+
+/*
+ * We map some memory, configure it's inheritance for MAP_INHERIT_ZERO,
+ * then check that when we fork child or grandchild processes, that they
+ * receive new zero'd out memory mappings. Additionally, we sanity check
+ * that after the child (or grandchild) process exits, that the parent's
+ * memory is still in tact.
+ */
+static void
+dotest(int fd, size_t len, int flags)
+{
+ void *p;
+ pid_t pid;
+
+ p = mmap(NULL, len, PROT_READ|PROT_WRITE, flags, fd, 0);
+ CHECK_NE(MAP_FAILED, p);
+
+ CHECK_EQ(0, minherit(p, len, MAP_INHERIT_ZERO));
+
+ memset(p, PARENT_BYTE, len);
+
+ pid = fork();
+ CHECK_GE(pid, 0);
+ if (pid == 0) {
+ CHECK(ismemset(p, 0, len));
+ memset(p, CHILD_BYTE, len);
+
+ pid = fork();
+ CHECK_GE(pid, 0);
+ if (pid == 0) {
+ CHECK(ismemset(p, 0, len));
+ memset(p, GRANDCHILD_BYTE, len);
+ _exit(0);
+ }
+
+ wait_for_clean_exit(pid);
+ CHECK(ismemset(p, CHILD_BYTE, len));
+ memset(p, 0, len);
+ _exit(0);
+ }
+
+ wait_for_clean_exit(pid);
+ CHECK(ismemset(p, PARENT_BYTE, len));
+ memset(p, 0, len);
+
+ CHECK_EQ(0, munmap(p, len));
+}
+
+int
+main()
+{
+ long pagesize;
+ size_t len;
+
+ pagesize = sysconf(_SC_PAGESIZE);
+ CHECK_GE(pagesize, 1);
+ len = NPAGES * pagesize;
+
+ /* First run test with private anonymous memory. */
+ dotest(-1, len, MAP_ANON|MAP_PRIVATE);
+
+ /* Test again with shared anonymous memory. */
+ dotest(-1, len, MAP_ANON|MAP_SHARED);
+
+ /* Finally, test with private file mapping. */
+ int fd = open(_PATH_BSHELL, O_RDONLY);
+ CHECK_GE(fd, 0);
+ dotest(fd, len, MAP_FILE|MAP_PRIVATE);
+ CHECK_EQ(0, close(fd));
+
+ return (0);
+}