[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