Module Name: src Committed By: kamil Date: Sun Feb 12 06:09:53 UTC 2017
Modified Files: src/lib/libc/sys: ptrace.2 src/sys/kern: sys_ptrace_common.c src/sys/sys: ptrace.h src/tests/kernel: t_ptrace_wait.c Log Message: Introduce new interface in ptrace(2) - PT_GET_SIGMASK and PT_SET_SIGMASK Add new interface to add ability to get/set signal mask of a tracee. It has been inspired by Linux PTRACE_GETSIGMASK and PTRACE_SETSIGMASK, but adapted for NetBSD API. This interface is used for checkpointing software to set/restore context of a process including signal mask like criu or just to track this property in reverse-execution software like Record and Replay Framework (rr). Add new ATF tests for this interface ==================================== getsigmask1: Verify that plain PT_SET_SIGMASK can be called getsigmask2: Verify that PT_SET_SIGMASK reports correct mask from tracee setsigmask1: Verify that plain PT_SET_SIGMASK can be called with empty mask setsigmask2: Verify that sigmask is preserved between PT_GET_SIGMASK and PT_SET_SIGMASK setsigmask3: Verify that sigmask is preserved between PT_GET_SIGMASK, process resumed and PT_SET_SIGMASK setsigmask4: Verify that new sigmask is visible in tracee Kernel ABI bump delayed as there are more interfaces to come in ptrace(2). Sponsored by <The NetBSD Foundation> To generate a diff of this commit: cvs rdiff -u -r1.58 -r1.59 src/lib/libc/sys/ptrace.2 cvs rdiff -u -r1.13 -r1.14 src/sys/kern/sys_ptrace_common.c cvs rdiff -u -r1.55 -r1.56 src/sys/sys/ptrace.h cvs rdiff -u -r1.69 -r1.70 src/tests/kernel/t_ptrace_wait.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/sys/ptrace.2 diff -u src/lib/libc/sys/ptrace.2:1.58 src/lib/libc/sys/ptrace.2:1.59 --- src/lib/libc/sys/ptrace.2:1.58 Fri Jan 27 12:52:39 2017 +++ src/lib/libc/sys/ptrace.2 Sun Feb 12 06:09:53 2017 @@ -1,7 +1,7 @@ -.\" $NetBSD: ptrace.2,v 1.58 2017/01/27 12:52:39 wiz Exp $ +.\" $NetBSD: ptrace.2,v 1.59 2017/02/12 06:09:53 kamil Exp $ .\" .\" This file is in the public domain. -.Dd January 25, 2016 +.Dd February 12, 2016 .Dt PTRACE 2 .Os .Sh NAME @@ -514,6 +514,31 @@ The .Fa data argument should be set to .Li sizeof(struct ptrace_siginfo) . +.It Dv PT_SET_SIGMASK +This request loads the traced process' signal mask from +.Dq Li "sigset_t" +(defined in +.In sys/sigtypes.h ) +pointed to by +.Fa addr . +The +.Fa data +argument contains the LWP ID of the thread whose registers are to +be written. +If zero is supplied, the first thread of the process is written. +.It Dv PT_GET_SIGMASK +This request is the converse of +.Dv PT_SET_SIGMASK ; +it reads the traced process' signal mask into +.Dq Li "sigset_t" +(defined in +.In sys/sigtypes.h ) +pointed to by +.Fa addr . +The +.Fa data +argument contains the LWP ID of the thread whose mask is to be read. +If zero is supplied, the first thread of the process is read. .El .Pp Additionally, the following requests exist but are Index: src/sys/kern/sys_ptrace_common.c diff -u src/sys/kern/sys_ptrace_common.c:1.13 src/sys/kern/sys_ptrace_common.c:1.14 --- src/sys/kern/sys_ptrace_common.c:1.13 Sat Feb 11 19:32:41 2017 +++ src/sys/kern/sys_ptrace_common.c Sun Feb 12 06:09:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sys_ptrace_common.c,v 1.13 2017/02/11 19:32:41 kamil Exp $ */ +/* $NetBSD: sys_ptrace_common.c,v 1.14 2017/02/12 06:09:52 kamil Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -118,7 +118,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.13 2017/02/11 19:32:41 kamil Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.14 2017/02/12 06:09:52 kamil Exp $"); #ifdef _KERNEL_OPT #include "opt_ptrace.h" @@ -212,6 +212,8 @@ ptrace_listener_cb(kauth_cred_t cred, ka case PT_GET_PROCESS_STATE: case PT_SET_SIGINFO: case PT_GET_SIGINFO: + case PT_SET_SIGMASK: + case PT_GET_SIGMASK: #ifdef __HAVE_PTRACE_MACHDEP PTRACE_MACHDEP_REQUEST_CASES #endif @@ -406,6 +408,8 @@ do_ptrace(struct ptrace_methods *ptm, st case PT_IO: case PT_SET_SIGINFO: case PT_GET_SIGINFO: + case PT_SET_SIGMASK: + case PT_GET_SIGMASK: #ifdef PT_GETREGS case PT_GETREGS: #endif @@ -1039,6 +1043,35 @@ do_ptrace(struct ptrace_methods *ptm, st break; + case PT_SET_SIGMASK: + write = 1; + + case PT_GET_SIGMASK: + /* write = 0 done above. */ + + tmp = data; + if (tmp != 0 && t->p_nlwps > 1) { + lwp_delref(lt); + mutex_enter(t->p_lock); + lt = lwp_find(t, tmp); + if (lt == NULL) { + mutex_exit(t->p_lock); + error = ESRCH; + break; + } + lwp_addref(lt); + mutex_exit(t->p_lock); + } + + if (!process_validregs(lt)) + error = EINVAL; + else if (write == 1) + error = copyin(addr, <->l_sigmask, sizeof(sigset_t)); + else + error = copyout(<->l_sigmask, addr, sizeof(sigset_t)); + + break; + #ifdef PT_SETREGS case PT_SETREGS: write = 1; Index: src/sys/sys/ptrace.h diff -u src/sys/sys/ptrace.h:1.55 src/sys/sys/ptrace.h:1.56 --- src/sys/sys/ptrace.h:1.55 Mon Jan 16 21:35:59 2017 +++ src/sys/sys/ptrace.h Sun Feb 12 06:09:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ptrace.h,v 1.55 2017/01/16 21:35:59 kamil Exp $ */ +/* $NetBSD: ptrace.h,v 1.56 2017/02/12 06:09:52 kamil Exp $ */ /*- * Copyright (c) 1984, 1993 @@ -55,6 +55,8 @@ #define PT_GET_PROCESS_STATE 18 /* get process state, defined below */ #define PT_SET_SIGINFO 19 /* set signal state, defined below */ #define PT_GET_SIGINFO 20 /* get signal state, defined below */ +#define PT_SET_SIGMASK 21 /* set signal mask */ +#define PT_GET_SIGMASK 22 /* get signal mask */ #define PT_FIRSTMACH 32 /* for machine-specific requests */ #include <machine/ptrace.h> /* machine-specific requests, if any */ @@ -80,7 +82,9 @@ /* 17 */ "PT_GET_EVENT_MASK", \ /* 18 */ "PT_GET_PROCESS_STATE", \ /* 19 */ "PT_SET_SIGINFO", \ -/* 20 */ "PT_GET_SIGINFO", +/* 20 */ "PT_GET_SIGINFO", \ +/* 20 */ "PT_GET_SIGMASK", \ +/* 20 */ "PT_GET_SIGMASK", /* PT_{G,S}EVENT_MASK */ typedef struct ptrace_event { Index: src/tests/kernel/t_ptrace_wait.c diff -u src/tests/kernel/t_ptrace_wait.c:1.69 src/tests/kernel/t_ptrace_wait.c:1.70 --- src/tests/kernel/t_ptrace_wait.c:1.69 Fri Jan 27 16:43:07 2017 +++ src/tests/kernel/t_ptrace_wait.c Sun Feb 12 06:09:52 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: t_ptrace_wait.c,v 1.69 2017/01/27 16:43:07 kamil Exp $ */ +/* $NetBSD: t_ptrace_wait.c,v 1.70 2017/02/12 06:09:52 kamil Exp $ */ /*- * Copyright (c) 2016 The NetBSD Foundation, Inc. @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: t_ptrace_wait.c,v 1.69 2017/01/27 16:43:07 kamil Exp $"); +__RCSID("$NetBSD: t_ptrace_wait.c,v 1.70 2017/02/12 06:09:52 kamil Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -6583,6 +6583,370 @@ ATF_TC_BODY(signal10, tc) TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); } +ATF_TC(getsigmask1); +ATF_TC_HEAD(getsigmask1, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that plain PT_SET_SIGMASK can be called"); +} + +ATF_TC_BODY(getsigmask1, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t mask; + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_GET_SIGMASK\n"); + ATF_REQUIRE(ptrace(PT_GET_SIGMASK, child, &mask, 0) != -1); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(getsigmask2); +ATF_TC_HEAD(getsigmask2, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that PT_SET_SIGMASK reports correct mask from tracee"); +} + +ATF_TC_BODY(getsigmask2, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + const int sigmasked = SIGTRAP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t mask; + sigset_t expected_mask; + ATF_REQUIRE(sigemptyset(&mask) == 0); + ATF_REQUIRE(sigemptyset(&expected_mask) == 0); + ATF_REQUIRE(sigaddset(&expected_mask, sigmasked) == 0); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + sigaddset(&mask, sigmasked); + sigprocmask(SIG_BLOCK, &mask, NULL); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_GET_SIGMASK\n"); + ATF_REQUIRE(ptrace(PT_GET_SIGMASK, child, &mask, 0) != -1); + + ATF_REQUIRE(memcmp(&mask, &expected_mask, sizeof(sigset_t)) == 0); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(setsigmask1); +ATF_TC_HEAD(setsigmask1, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that plain PT_SET_SIGMASK can be called with empty mask"); +} + +ATF_TC_BODY(setsigmask1, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t mask; + ATF_REQUIRE(sigemptyset(&mask) == 0); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_SET_SIGMASK for empty mask\n"); + ATF_REQUIRE(ptrace(PT_SET_SIGMASK, child, &mask, 0) != -1); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(setsigmask2); +ATF_TC_HEAD(setsigmask2, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that sigmask is preserved between PT_GET_SIGMASK and " + "PT_SET_SIGMASK"); +} + +ATF_TC_BODY(setsigmask2, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t new_mask; + sigset_t mask; + ATF_REQUIRE(sigemptyset(&new_mask) == 0); + ATF_REQUIRE(sigemptyset(&mask) == 0); + ATF_REQUIRE(sigaddset(&mask, SIGINT) == 0); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_SET_SIGMASK for new mask with SIGINT\n"); + ATF_REQUIRE(ptrace(PT_SET_SIGMASK, child, &mask, 0) != -1); + + printf("Before calling PT_GET_SIGMASK to store it in new_mask\n"); + ATF_REQUIRE(ptrace(PT_GET_SIGMASK, child, &new_mask, 0) != -1); + + ATF_REQUIRE(memcmp(&mask, &new_mask, sizeof(sigset_t)) == 0); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(setsigmask3); +ATF_TC_HEAD(setsigmask3, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that sigmask is preserved between PT_GET_SIGMASK, process " + "resumed and PT_SET_SIGMASK"); +} + +ATF_TC_BODY(setsigmask3, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t new_mask; + sigset_t mask; + ATF_REQUIRE(sigemptyset(&new_mask) == 0); + ATF_REQUIRE(sigemptyset(&mask) == 0); + ATF_REQUIRE(sigaddset(&mask, SIGINT) == 0); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_SET_SIGMASK for new mask with SIGINT\n"); + ATF_REQUIRE(ptrace(PT_SET_SIGMASK, child, &mask, 0) != -1); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_GET_SIGMASK to store it in new_mask\n"); + ATF_REQUIRE(ptrace(PT_GET_SIGMASK, child, &new_mask, 0) != -1); + + ATF_REQUIRE(memcmp(&mask, &new_mask, sizeof(sigset_t)) == 0); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + +ATF_TC(setsigmask4); +ATF_TC_HEAD(setsigmask4, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Verify that new sigmask is visible in tracee"); +} + +ATF_TC_BODY(setsigmask4, tc) +{ + const int exitval = 5; + const int sigval = SIGSTOP; + pid_t child, wpid; +#if defined(TWAIT_HAVE_STATUS) + int status; +#endif + sigset_t mask; + sigset_t expected_mask; + ATF_REQUIRE(sigemptyset(&mask) == 0); + ATF_REQUIRE(sigemptyset(&expected_mask) == 0); + ATF_REQUIRE(sigaddset(&expected_mask, SIGINT) == 0); + + printf("Before forking process PID=%d\n", getpid()); + ATF_REQUIRE((child = fork()) != -1); + if (child == 0) { + printf("Before calling PT_TRACE_ME from child %d\n", getpid()); + FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); + + printf("Before raising %s from child\n", strsignal(sigval)); + FORKEE_ASSERT(raise(sigval) == 0); + + sigprocmask(0, NULL, &mask); + + FORKEE_ASSERT + (memcmp(&mask, &expected_mask, sizeof(sigset_t)) == 0); + + printf("Before exiting of the child process\n"); + _exit(exitval); + } + printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_stopped(status, sigval); + + printf("Before calling PT_SET_SIGMASK for new mask with SIGINT\n"); + ATF_REQUIRE(ptrace(PT_SET_SIGMASK, child, &expected_mask, 0) != -1); + + printf("Before resuming the child process where it left off and " + "without signal to be sent\n"); + ATF_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); + + validate_status_exited(status, exitval); + + printf("Before calling %s() for the child\n", TWAIT_FNAME); + TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); +} + ATF_TP_ADD_TCS(tp) { setvbuf(stdout, NULL, _IONBF, 0); @@ -6696,5 +7060,13 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, signal9); ATF_TP_ADD_TC(tp, signal10); + ATF_TP_ADD_TC(tp, getsigmask1); + ATF_TP_ADD_TC(tp, getsigmask2); + + ATF_TP_ADD_TC(tp, setsigmask1); + ATF_TP_ADD_TC(tp, setsigmask2); + ATF_TP_ADD_TC(tp, setsigmask3); + ATF_TP_ADD_TC(tp, setsigmask4); + return atf_no_error(); }