[1/2] test: Test for partially mprotect()-ed sysv shmem segment

Submitted by Pavel Emelianov on May 19, 2016, 10:06 a.m.

Details

Message ID 573D900A.4060101@virtuozzo.com
State Accepted
Series "Support mprotected sysv shmems"
Commit 0a1ea36f88eaa575f02fbfdfd8f678f569a87a12
Headers show

Commit Message

Pavel Emelianov May 19, 2016, 10:06 a.m.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
---
 test/zdtm/.gitignore         |   1 +
 test/zdtm/static/Makefile    |   1 +
 test/zdtm/static/shm-mp.c    | 116 +++++++++++++++++++++++++++++++++++++++++++
 test/zdtm/static/shm-mp.desc |   1 +
 4 files changed, 119 insertions(+)
 create mode 100644 test/zdtm/static/shm-mp.c
 create mode 100644 test/zdtm/static/shm-mp.desc

Patch hide | download patch | download mbox

diff --git a/test/zdtm/.gitignore b/test/zdtm/.gitignore
index 2e2ac2b..4c2b2de 100644
--- a/test/zdtm/.gitignore
+++ b/test/zdtm/.gitignore
@@ -131,6 +131,7 @@ 
 /static/session02
 /static/session03
 /static/shm
+/static/shm-mp
 /static/sigaltstack
 /static/signalfd00
 /static/sigpending
diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 36b9252..e07725b 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -45,6 +45,7 @@  TST_NOFILE	=				\
 		inotify_system			\
 		inotify_system_nodel		\
 		shm				\
+		shm-mp				\
 		ptrace_sig			\
 		pipe00				\
 		pipe01				\
diff --git a/test/zdtm/static/shm-mp.c b/test/zdtm/static/shm-mp.c
new file mode 100644
index 0000000..b297d76
--- /dev/null
+++ b/test/zdtm/static/shm-mp.c
@@ -0,0 +1,116 @@ 
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <signal.h>
+#include <setjmp.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc="Tests mprotected SYSVIPC shmems";
+const char *test_author="Pavel Emelyanov <xemul@openvz.org>";
+
+static sigjmp_buf segv_ret;		/* we need sig*jmp stuff, otherwise SIGSEGV will reset our handler */
+static void segfault(int signo)
+{
+	siglongjmp(segv_ret, 1);
+}
+
+static int check_prot(char *ptr, char val, int prot)
+{
+	if (signal(SIGSEGV, segfault) == SIG_ERR) {
+		fail("setting SIGSEGV handler failed: %m\n");
+		return -1;
+	}
+
+	if (!sigsetjmp(segv_ret, 1)) {
+		if (*ptr != val) {
+			fail("read value doesn't match what I wrote");
+			return -1;
+		}
+		if (!(prot & PROT_READ)) {
+			fail("PROT_READ bypassed\n");
+			return -1;
+		}
+	} else		/* we come here on return from SIGSEGV handler */
+		if (prot & PROT_READ) {
+			fail("PROT_READ rejected\n");
+			return -1;
+		}
+
+	if (!sigsetjmp(segv_ret, 1)) {
+		*ptr = val;
+		if (!(prot & PROT_WRITE)) {
+			fail("PROT_WRITE bypassed\n");
+			return -1;
+		}
+	} else		/* we come here on return from SIGSEGV handler */
+		if (prot & PROT_WRITE) {
+			fail("PROT_WRITE rejected\n");
+			return -1;
+		}
+
+	if (signal(SIGSEGV, SIG_DFL) == SIG_ERR) {
+		fail("restoring SIGSEGV handler failed: %m\n");
+		return -1;
+	}
+
+	return 0;
+}
+int main(int argc, char **argv)
+{
+	key_t key;
+	int id, f = 0;
+	char *mem;
+
+	test_init(argc, argv);
+
+	key = ftok(argv[0], 812135646);
+	if (key == -1) {
+		pr_perror("Can't make key");
+		goto out;
+	}
+
+	id = shmget(key, 2 * 4096, 0777 | IPC_CREAT | IPC_EXCL);
+	if (id == -1) {
+		pr_perror("Can't make seg");
+		goto out;
+	}
+
+	mem = shmat(id, NULL, 0);
+	if (mem == (void *)-1) {
+		pr_perror("Can't shmat");
+		goto out_rm;
+	}
+
+	mem[0] = 'R';
+	mem[4096] = 'W';
+
+	if (mprotect(mem, 4096, PROT_READ)) {
+		pr_perror("Can't mprotect shmem");
+		goto out_dt;
+	}
+
+	test_daemon();
+	test_waitsig();
+
+	if (check_prot(mem, 'R', PROT_READ))
+		f++;
+	if (check_prot(mem + 4096, 'W', PROT_READ | PROT_WRITE))
+		f++;
+
+
+	if (!f)
+		pass();
+	else
+		fail("Some checks failed");
+
+out_dt:
+	shmdt(mem);
+out_rm:
+	shmctl(id, IPC_RMID, NULL);
+out:
+	return 0;
+}
diff --git a/test/zdtm/static/shm-mp.desc b/test/zdtm/static/shm-mp.desc
new file mode 100644
index 0000000..6c4afe5
--- /dev/null
+++ b/test/zdtm/static/shm-mp.desc
@@ -0,0 +1 @@ 
+{'flavor': 'ns uns'}