[9/9] seccomp: test, seccomp_filter_threads -- Use multiple threads

Submitted by Cyrill Gorcunov on April 26, 2018, 8:14 p.m.

Details

Message ID 20180426201443.2163-10-gorcunov@gmail.com
State New
Series "Per-thread seccomp support, v3"
Headers show

Commit Message

Cyrill Gorcunov April 26, 2018, 8:14 p.m.
Andrew proposed the test which actually triggered the issue
in current seccomp series, put it into a regular basis.

Suggested-by: Andrey Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
 test/zdtm/static/seccomp_filter_threads.c | 94 ++++++++++++++++++++++++++-----
 1 file changed, 79 insertions(+), 15 deletions(-)

Patch hide | download patch | download mbox

diff --git a/test/zdtm/static/seccomp_filter_threads.c b/test/zdtm/static/seccomp_filter_threads.c
index a0e0b6472d1a..1db4c9fbcc93 100644
--- a/test/zdtm/static/seccomp_filter_threads.c
+++ b/test/zdtm/static/seccomp_filter_threads.c
@@ -9,6 +9,7 @@ 
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <sys/syscall.h>
+#include <sys/mman.h>
 
 #ifdef __NR_seccomp
 # include <linux/seccomp.h>
@@ -18,6 +19,7 @@ 
 #endif
 
 #include "zdtmtst.h"
+#include "lock.h"
 
 #ifndef SECCOMP_SET_MODE_FILTER
 #define SECCOMP_SET_MODE_FILTER 1
@@ -30,9 +32,12 @@ 
 const char *test_doc	= "Check threads to carry different seccomps";
 const char *test_author	= "Cyrill Gorcunov <gorcunov@openvz.org>";
 
+static long sys_gettid(void) { return syscall(__NR_gettid); }
+
 #ifdef __NR_seccomp
 
-static task_waiter_t tw;
+static futex_t *wait_rdy;
+static futex_t *wait_run;
 
 int get_seccomp_mode(pid_t pid)
 {
@@ -82,27 +87,76 @@  int filter_syscall(int syscall_nr, unsigned int flags)
 	return 0;
 }
 
+void tigger_ptrace(void) { ptrace(PTRACE_TRACEME); }
+void trigger_prctl(void) { prctl(PR_SET_PDEATHSIG, 9, 0, 0, 0); }
+void trigger_mincore(void) { mincore(NULL, 0, NULL); }
+
+#define gen_param(__syscall_nr, __trigger)		\
+{							\
+	.syscall_name	= # __syscall_nr,		\
+	.syscall_nr	= __syscall_nr,			\
+	.trigger	= __trigger,			\
+}
+
+struct {
+	char		*syscall_name;
+	unsigned int	syscall_nr;
+	void		(*trigger)(void);
+} pthread_seccomp_params[] = {
+	gen_param(__NR_ptrace, tigger_ptrace),
+	gen_param(__NR_prctl, trigger_prctl),
+	gen_param(__NR_mincore, trigger_mincore),
+};
+
+#define WAITER_VALS_OFFSET (ARRAY_SIZE(pthread_seccomp_params) * 2)
+
 void *thread_main(void *arg)
 {
-	if (filter_syscall(__NR_ptrace, 0) < 0)
+	size_t nr = (long) arg;
+
+	if (filter_syscall(pthread_seccomp_params[nr].syscall_nr, 0) < 0)
 		pthread_exit((void *)1);
 
-	test_msg("__NR_ptrace filtered inside a sole thread\n");
+	test_msg("%s filtered inside a sole thread %lu\n",
+		 pthread_seccomp_params[nr].syscall_name,
+		 sys_gettid());
+
+	futex_inc_and_wake(wait_rdy);
+	futex_wait_while_lt(wait_run, 1);
+
+	test_msg("Triggering %zu %s thread %lu\n",
+		 nr, pthread_seccomp_params[nr].syscall_name,
+		 sys_gettid());
 
-	task_waiter_complete(&tw, 1);
-	task_waiter_wait4(&tw, 2);
+	pthread_seccomp_params[nr].trigger();
 
-	ptrace(PTRACE_TRACEME);
+	test_msg("Abnormal exit %zu thread %lu\n", nr, sys_gettid());
 	pthread_exit((void *)1);
 }
 
 int main(int argc, char ** argv)
 {
 	int ret, mode, status;
+	size_t i;
 	pid_t pid;
 
 	test_init(argc, argv);
-	task_waiter_init(&tw);
+
+	wait_rdy = mmap(NULL, sizeof(*wait_rdy), PROT_READ | PROT_WRITE,
+			MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+	wait_run = mmap(NULL, sizeof(*wait_rdy), PROT_READ | PROT_WRITE,
+			MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+
+	if (wait_rdy == MAP_FAILED || wait_run == MAP_FAILED) {
+		pr_perror("mmap failed\n");
+		exit(1);
+	}
+
+	futex_init(wait_rdy);
+	futex_init(wait_run);
+
+	futex_set(wait_rdy, 0);
+	futex_set(wait_run, 0);
 
 	pid = fork();
 	if (pid < 0) {
@@ -110,27 +164,37 @@  int main(int argc, char ** argv)
 		return -1;
 	}
 
+
 	if (pid == 0) {
-		pthread_t thread;
+		pthread_t thread[ARRAY_SIZE(pthread_seccomp_params)];
 		void *p = NULL;
 
 		zdtm_seccomp = 1;
 
-		pthread_create(&thread, NULL, thread_main, NULL);
-		if (pthread_join(thread, &p) != 0) {
-			pr_perror("pthread_join");
-			exit(1);
+		for (i = 0; i < ARRAY_SIZE(pthread_seccomp_params); i++) {
+			if (pthread_create(&thread[i], NULL, thread_main, (void *)i)) {
+				pr_perror("pthread_create");
+				exit(1);
+			}
+		}
+
+		for (i = 0; i < ARRAY_SIZE(pthread_seccomp_params); i++) {
+			test_msg("Waiting thread %zu\n", i);
+			if (pthread_join(thread[i], &p) != 0) {
+				pr_perror("pthread_join");
+				exit(1);
+			}
 		}
 
-		syscall(__NR_exit, p);
+		syscall(__NR_exit, 0);
 	}
 
-	task_waiter_wait4(&tw, 1);
+	futex_wait_until(wait_rdy, ARRAY_SIZE(pthread_seccomp_params));
 
 	test_daemon();
 	test_waitsig();
 
-	task_waiter_complete(&tw, 2);
+	futex_inc_and_wake(wait_run);
 	mode = get_seccomp_mode(pid);
 
 	if (mode != SECCOMP_MODE_DISABLED) {