[CRIU] [PATCH 7/7] seccomp: test -- Add seccomp_filter_threads

Andrey Vagin avagin at virtuozzo.com
Thu Apr 26 00:19:47 MSK 2018


Pls, take a look at the attached test. criu restore hangs up on it.


[root at fc24 criu]# python test/zdtm.py run -t zdtm/static/seccomp_filter_threads  --iter 0 -f h
Checking feature seccomp_filters
=== Run 1/1 ================ zdtm/static/seccomp_filter_threads

================= Run zdtm/static/seccomp_filter_threads in h ==================
Start test
Test is SUID
./seccomp_filter_threads --pidfile=seccomp_filter_threads.pid --outfile=seccomp_filter_threads.out
Send the 15 signal to  48
Wait for zdtm/static/seccomp_filter_threads(48) to die for 0.100000
Removing dump/zdtm/static/seccomp_filter_threads/48
================= Test zdtm/static/seccomp_filter_threads PASS =================



ot at fc24 criu]# python test/zdtm.py run -t zdtm/static/seccomp_filter_threads  --iter 1
Checking feature seccomp_filters
=== Run 1/1 ================ zdtm/static/seccomp_filter_threads

================= Run zdtm/static/seccomp_filter_threads in h ==================
Start test
Test is SUID
./seccomp_filter_threads --pidfile=seccomp_filter_threads.pid --outfile=seccomp_filter_threads.out
Run criu dump
Run criu restore
^Z
[1]+  Stopped                 python test/zdtm.py run -t zdtm/static/seccomp_filter_threads --iter 1


13141 ?        Ss     0:00  \_ sshd: root [priv]
13143 ?        S      0:00      \_ sshd: root at pts/3
13144 pts/3    Ss     0:00          \_ -bash
13427 pts/3    T      0:00              \_ python test/zdtm.py run -t zdtm/static/seccomp_filter_threads --iter 1
13439 pts/3    T      0:00              |   \_ ./zdtm_ct zdtm.py
13440 pts/3    S      0:00              |       \_ python2 zdtm.py
13442 pts/3    T      0:00              |           \_ python2 zdtm.py
13492 pts/3    S      0:00              |               \_ ../criu/criu restore --no-default-config -o restore.log -D dump/zdtm/static/seccomp_filter_threads/48/1 -v4 --pidfile /root/git/mai
13493 ?        Ss     0:00              |                   \_ ../criu/criu restore --no-default-config -o restore.log -D dump/zdtm/static/seccomp_filter_threads/48/1 -v4 --pidfile /root/git
13494 ?        Sl     0:00              |                       \_ ./seccomp_filter_threads --pidfile=seccomp_filter_threads.pid --outfile=seccomp_filter_threads.out


[root at fc24 criu]# gdb -p 13493 
(gdb) bt
#0  0x00007f3864104b99 in syscall () from target:/lib64/libc.so.6
#1  0x0000000000440cbd in sys_futex (addr2=0x0, val3=0, timeout=0x7ffd0af54810, val1=<optimized out>, op=0, addr1=0x7f386547300c) at include/common/lock.h:25
#2  __restore_wait_inprogress_tasks (participants=1) at criu/cr-restore.c:181
#3  0x0000000000443164 in sigreturn_restore (pid=32568, pid at entry=48, task_args=task_args at entry=0x7f3865472000, alen=alen at entry=4096, core=0xa58, core at entry=0x16885b0)
    at criu/cr-restore.c:3528
#4  0x0000000000445131 in restore_one_alive_task (core=0x16885b0, pid=<optimized out>) at criu/cr-restore.c:1062
#5  restore_one_task (core=0x16885b0, pid=<optimized out>) at criu/cr-restore.c:1349
#6  restore_task_with_children (_arg=<optimized out>) at criu/cr-restore.c:1978
#7  0x00007f386410a16f in clone () from target:/lib64/libc.so.6


On Fri, Apr 06, 2018 at 10:17:08PM +0300, Cyrill Gorcunov wrote:
> From: Cyrill Gorcunov <gorcunov at openvz.org>
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
>  test/zdtm/static/Makefile                    |   2 +
>  test/zdtm/static/seccomp_filter_threads.c    | 161 +++++++++++++++++++++++++++
>  test/zdtm/static/seccomp_filter_threads.desc |   1 +
>  3 files changed, 164 insertions(+)
>  create mode 100644 test/zdtm/static/seccomp_filter_threads.c
>  create mode 100644 test/zdtm/static/seccomp_filter_threads.desc
> 
> diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
> index 202fa639f902..bd98d0be4f6b 100644
> --- a/test/zdtm/static/Makefile
> +++ b/test/zdtm/static/Makefile
> @@ -184,6 +184,7 @@ TST_NOFILE	:=				\
>  		seccomp_strict			\
>  		seccomp_filter			\
>  		seccomp_filter_tsync			\
> +		seccomp_filter_threads			\
>  		seccomp_filter_inheritance		\
>  		different_creds			\
>  		vsx				\
> @@ -466,6 +467,7 @@ different_creds:	LDLIBS += -pthread
>  sigpending:		LDLIBS += -pthread
>  sigaltstack:		LDLIBS += -pthread
>  seccomp_filter_tsync:	LDLIBS += -pthread
> +seccomp_filter_threads:	LDLIBS += -pthread
>  shm:			CFLAGS += -DNEW_IPC_NS
>  msgque:			CFLAGS += -DNEW_IPC_NS
>  sem:			CFLAGS += -DNEW_IPC_NS
> diff --git a/test/zdtm/static/seccomp_filter_threads.c b/test/zdtm/static/seccomp_filter_threads.c
> new file mode 100644
> index 000000000000..a0e0b6472d1a
> --- /dev/null
> +++ b/test/zdtm/static/seccomp_filter_threads.c
> @@ -0,0 +1,161 @@
> +#include <unistd.h>
> +#include <stdbool.h>
> +#include <signal.h>
> +#include <stddef.h>
> +#include <sys/prctl.h>
> +#include <sys/ptrace.h>
> +#include <stdlib.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <sys/wait.h>
> +#include <sys/syscall.h>
> +
> +#ifdef __NR_seccomp
> +# include <linux/seccomp.h>
> +# include <linux/filter.h>
> +# include <linux/limits.h>
> +# include <pthread.h>
> +#endif
> +
> +#include "zdtmtst.h"
> +
> +#ifndef SECCOMP_SET_MODE_FILTER
> +#define SECCOMP_SET_MODE_FILTER 1
> +#endif
> +
> +#ifndef SECCOMP_FILTER_FLAG_TSYNC
> +#define SECCOMP_FILTER_FLAG_TSYNC 1
> +#endif
> +
> +const char *test_doc	= "Check threads to carry different seccomps";
> +const char *test_author	= "Cyrill Gorcunov <gorcunov at openvz.org>";
> +
> +#ifdef __NR_seccomp
> +
> +static task_waiter_t tw;
> +
> +int get_seccomp_mode(pid_t pid)
> +{
> +	FILE *f;
> +	char buf[PATH_MAX];
> +
> +	sprintf(buf, "/proc/%d/status", pid);
> +	f = fopen(buf, "r+");
> +	if (!f) {
> +		pr_perror("fopen failed");
> +		return -1;
> +	}
> +
> +	while (NULL != fgets(buf, sizeof(buf), f)) {
> +		int mode;
> +
> +		if (sscanf(buf, "Seccomp:\t%d", &mode) != 1)
> +			continue;
> +
> +		fclose(f);
> +		return mode;
> +	}
> +	fclose(f);
> +
> +	return -1;
> +}
> +
> +int filter_syscall(int syscall_nr, unsigned int flags)
> +{
> +	struct sock_filter filter[] = {
> +		BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)),
> +		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, syscall_nr, 0, 1),
> +		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
> +		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
> +	};
> +
> +	struct sock_fprog bpf_prog = {
> +		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
> +		.filter = filter,
> +	};
> +
> +	if (syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, flags, &bpf_prog) < 0) {
> +		pr_perror("seccomp failed");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +void *thread_main(void *arg)
> +{
> +	if (filter_syscall(__NR_ptrace, 0) < 0)
> +		pthread_exit((void *)1);
> +
> +	test_msg("__NR_ptrace filtered inside a sole thread\n");
> +
> +	task_waiter_complete(&tw, 1);
> +	task_waiter_wait4(&tw, 2);
> +
> +	ptrace(PTRACE_TRACEME);
> +	pthread_exit((void *)1);
> +}
> +
> +int main(int argc, char ** argv)
> +{
> +	int ret, mode, status;
> +	pid_t pid;
> +
> +	test_init(argc, argv);
> +	task_waiter_init(&tw);
> +
> +	pid = fork();
> +	if (pid < 0) {
> +		pr_perror("fork");
> +		return -1;
> +	}
> +
> +	if (pid == 0) {
> +		pthread_t thread;
> +		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);
> +		}
> +
> +		syscall(__NR_exit, p);
> +	}
> +
> +	task_waiter_wait4(&tw, 1);
> +
> +	test_daemon();
> +	test_waitsig();
> +
> +	task_waiter_complete(&tw, 2);
> +	mode = get_seccomp_mode(pid);
> +
> +	if (mode != SECCOMP_MODE_DISABLED) {
> +		fail("seccomp mode mismatch %d\n", mode);
> +		return 1;
> +	}
> +
> +	ret = waitpid(pid, &status, 0);
> +	if (ret != pid) {
> +		fail("waitpid: %d != %d", ret, pid);
> +		exit(1);
> +	}
> +
> +	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
> +		fail("expected 0 exit, got %d\n", WEXITSTATUS(status));
> +		exit(1);
> +	}
> +
> +	pass();
> +	return 0;
> +}
> +
> +#else /* __NR_seccomp */
> +
> +#define TEST_SKIP_REASON "incompatible kernel (no seccomp)"
> +#include "skip-me.c"
> +
> +#endif /* __NR_seccomp */
> diff --git a/test/zdtm/static/seccomp_filter_threads.desc b/test/zdtm/static/seccomp_filter_threads.desc
> new file mode 100644
> index 000000000000..14dd96184987
> --- /dev/null
> +++ b/test/zdtm/static/seccomp_filter_threads.desc
> @@ -0,0 +1 @@
> +{'flags': 'suid', 'feature': 'seccomp_filters'}
> -- 
> 2.14.3
> 
-------------- next part --------------
diff --git a/test/zdtm/static/seccomp_filter_threads.c b/test/zdtm/static/seccomp_filter_threads.c
index a0e0b6472..277e9db56 100644
--- a/test/zdtm/static/seccomp_filter_threads.c
+++ b/test/zdtm/static/seccomp_filter_threads.c
@@ -84,21 +84,35 @@ int filter_syscall(int syscall_nr, unsigned int flags)
 
 void *thread_main(void *arg)
 {
-	if (filter_syscall(__NR_ptrace, 0) < 0)
-		pthread_exit((void *)1);
+	long n = (long) arg;
+
+	pr_err("%ld\n", n);
+	if (n == 0)  {
+		if (filter_syscall(__NR_ptrace, 0) < 0)
+			pthread_exit((void *)1);
+	} else {
+		if (filter_syscall(__NR_prctl, 0) < 0)
+			pthread_exit((void *)1);
+	}
 
 	test_msg("__NR_ptrace filtered inside a sole thread\n");
 
-	task_waiter_complete(&tw, 1);
-	task_waiter_wait4(&tw, 2);
+	task_waiter_complete(&tw, 1 + 1000 * n);
+	task_waiter_wait4(&tw, 2 + 1000 * n);
 
-	ptrace(PTRACE_TRACEME);
+	pr_err("%ld\n", n);
+	if (n == 0)
+		ptrace(PTRACE_TRACEME);
+	else
+		prctl(PR_SET_PDEATHSIG, 9, 0, 0, 0);
+	pr_err("%ld\n", n);
 	pthread_exit((void *)1);
 }
 
 int main(int argc, char ** argv)
 {
 	int ret, mode, status;
+	long i;
 	pid_t pid;
 
 	test_init(argc, argv);
@@ -111,26 +125,30 @@ int main(int argc, char ** argv)
 	}
 
 	if (pid == 0) {
-		pthread_t thread;
+		pthread_t thread[2];
 		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 < 2; i++)
+			pthread_create(&thread[i], NULL, thread_main, (void *)i);
+		for (i = 0; i < 2; 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);
+	for (i = 0; i < 2; i++)
+		task_waiter_wait4(&tw, 1 + 1000 * i);
 
 	test_daemon();
 	test_waitsig();
 
-	task_waiter_complete(&tw, 2);
+	for (i = 0; i < 2; i++)
+		task_waiter_complete(&tw, 2 + 1000 * i);
 	mode = get_seccomp_mode(pid);
 
 	if (mode != SECCOMP_MODE_DISABLED) {
@@ -144,6 +162,7 @@ int main(int argc, char ** argv)
 		exit(1);
 	}
 
+	pr_err("%d\n", status);
 	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
 		fail("expected 0 exit, got %d\n", WEXITSTATUS(status));
 		exit(1);


More information about the CRIU mailing list