PCuABI requires that the siginfo_t data delivered to the signal by syscalls rt_sigqueueinfo and rt_tgsigqueueinfo should pass the capability pointer tags in case of signal delivered to the same process. In case of different process, no tag details are propagated.
Appropriate tests are added to verify the above behavior.
Signed-off-by: Amit Daniel Kachhap amit.kachhap@arm.com --- tools/testing/selftests/arm64/morello/clone.c | 2 +- .../selftests/arm64/morello/freestanding.h | 19 ++++ .../selftests/arm64/morello/read_write.c | 2 +- .../testing/selftests/arm64/morello/signal.c | 107 ++++++++++++++++++ .../selftests/arm64/morello/signal_common.c | 10 ++ .../selftests/arm64/morello/signal_common.h | 2 + 6 files changed, 140 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/arm64/morello/clone.c b/tools/testing/selftests/arm64/morello/clone.c index 03ce8f34ff0e..8217840ba504 100644 --- a/tools/testing/selftests/arm64/morello/clone.c +++ b/tools/testing/selftests/arm64/morello/clone.c @@ -178,7 +178,7 @@ void wait_single(struct test_fixture *data) __TH_LOG_ERROR("wait_test: Failed to clone"); }
- result = syscall(__NR_waitid, P_PID, cpid, wait_si, WEXITED, wait_ru); + result = waitid(P_PID, cpid, wait_si, WEXITED, wait_ru);
ASSERT_EQ(result, 0) { __TH_LOG_ERROR("wait_test: Failed on wait"); diff --git a/tools/testing/selftests/arm64/morello/freestanding.h b/tools/testing/selftests/arm64/morello/freestanding.h index 2d1b701bd1d4..f8a0fdcbdec3 100644 --- a/tools/testing/selftests/arm64/morello/freestanding.h +++ b/tools/testing/selftests/arm64/morello/freestanding.h @@ -9,6 +9,8 @@ #include <stddef.h> #include <asm/unistd.h> #include <linux/posix_types.h> +#include <linux/resource.h> +#include <linux/signal.h> #include <cheriintrin.h>
/* this is provided by libc, so roll our own */ @@ -17,6 +19,8 @@ typedef __kernel_pid_t pid_t; typedef __kernel_mqd_t mqd_t; typedef __kernel_timer_t timer_t; typedef __kernel_clockid_t clockid_t; +typedef __kernel_uid_t uid_t; +typedef __kernel_mode_t mode_t;
struct __test_meta { int message; @@ -185,4 +189,19 @@ static inline int close(int fd) return syscall(__NR_close, fd); }
+static inline pid_t getpid(void) +{ + return syscall(__NR_getpid); +} + +static inline uid_t getuid(void) +{ + return syscall(__NR_getuid); +} + +static inline int waitid(int id_type, pid_t id, siginfo_t *info, int options, struct rusage *ru) +{ + return syscall(__NR_waitid, id_type, id, info, options, ru); +} + #endif diff --git a/tools/testing/selftests/arm64/morello/read_write.c b/tools/testing/selftests/arm64/morello/read_write.c index 3cb53e683a2e..a68b5efeb5ab 100644 --- a/tools/testing/selftests/arm64/morello/read_write.c +++ b/tools/testing/selftests/arm64/morello/read_write.c @@ -42,7 +42,7 @@ static int fd;
TEST(test_getpid) { - syscall(__NR_getpid, 0); + getpid(); }
TEST(test_write) diff --git a/tools/testing/selftests/arm64/morello/signal.c b/tools/testing/selftests/arm64/morello/signal.c index 7629b0877cb2..67e277cecc52 100644 --- a/tools/testing/selftests/arm64/morello/signal.c +++ b/tools/testing/selftests/arm64/morello/signal.c @@ -5,8 +5,10 @@
#include <stdbool.h>
+#include <linux/mman.h> #include <linux/signal.h> #include <linux/time.h> +#include <linux/wait.h> #include <asm/fcntl.h> #include <asm/sigcontext.h> #include <asm/siginfo.h> @@ -172,6 +174,49 @@ static void test_timer_create_signal(void) ASSERT_EQ(timer_delete(timerid), 0); }
+static void setup_siginfo_same_process(siginfo_t *siginfo) +{ + signal_status = false; + siginfo_params.ptr = &siginfo_params; + ASSERT_EQ(1, cheri_tag_get(siginfo_params.ptr)) { + __TH_LOG_ERROR("Check if application compiled in purecap"); + } + siginfo_params.cap = true; + siginfo_params.si_code = SI_QUEUE; + siginfo->si_signo = SIGUSR1; + siginfo->si_code = SI_QUEUE; + siginfo->si_pid = getpid(); + siginfo->si_uid = getuid(); + siginfo->si_ptr = siginfo_params.ptr; +} + +static int sigqueueinfo_child(__attribute__((__unused__)) void *data) +{ + struct sigaction sa; + + setup_sigusr1_handler(&sa, SIG_UNBLOCK); + /* wait for some time till the sigusr1 handler is called */ + wait(DELAY * 1000); + ASSERT_TRUE(signal_status); + return 0; +} + +static pid_t setup_siginfo_diff_process(siginfo_t *siginfo) +{ + pid_t cpid; + + setup_siginfo_same_process(siginfo); + siginfo_params.cap = false; + siginfo_params.ptr = cheri_tag_clear(siginfo_params.ptr); + siginfo->si_ptr = siginfo_params.ptr; + + cpid = __clone(sigqueueinfo_child, 0, SIGCHLD, NULL, NULL, NULL, NULL); + ASSERT_GT(cpid, 0) { + __TH_LOG_ERROR("Failed to clone"); + } + return cpid; +} + TEST(test_signal_basic) { struct sigaction sa; @@ -225,10 +270,72 @@ TEST(test_timer_create) ASSERT_TRUE(signal_status); }
+TEST(test_rt_sigqueueinfo) +{ + siginfo_t si, wait_si; + pid_t cpid; + struct sigaction sa; + int ret; + + setup_sigusr1_handler(&sa, SIG_UNBLOCK); + + TH_LOG("test_rt_sigqueueinfo: Signal to the same process"); + setup_siginfo_same_process(&si); + ret = rt_sigqueueinfo(si.si_pid, SIGUSR1, &si); + ASSERT_EQ(ret, 0) { + __TH_LOG_ERROR("rt_sigqueueinfo syscall failed"); + } + wait(DELAY * 1000); + ASSERT_TRUE(signal_status); + + TH_LOG("test_rt_sigqueueinfo: Signal to a different process"); + cpid = setup_siginfo_diff_process(&si); + ret = rt_sigqueueinfo(cpid, SIGUSR1, &si); + ASSERT_EQ(ret, 0) { + __TH_LOG_ERROR("rt_sigqueueinfo syscall failed"); + } + ret = waitid(P_PID, cpid, &wait_si, WEXITED, NULL); + ASSERT_EQ(ret, 0) { + __TH_LOG_ERROR("test_rt_sigqueueinfo: Failed on wait"); + } +} + +TEST(test_rt_tgsigqueueinfo) +{ + siginfo_t si, wait_si; + pid_t cpid; + struct sigaction sa; + int ret; + + setup_sigusr1_handler(&sa, SIG_UNBLOCK); + + TH_LOG("test_rt_tgsigqueueinfo: Signal to the same process"); + setup_siginfo_same_process(&si); + ret = rt_tgsigqueueinfo(si.si_pid, si.si_pid, SIGUSR1, &si); + ASSERT_EQ(ret, 0) { + __TH_LOG_ERROR("rt_tgsigqueueinfo syscall failed"); + } + wait(DELAY * 1000); + ASSERT_TRUE(signal_status); + + TH_LOG("test_rt_tgsigqueueinfo: Signal to a different process"); + cpid = setup_siginfo_diff_process(&si); + ret = rt_tgsigqueueinfo(cpid, cpid, SIGUSR1, &si); + ASSERT_EQ(ret, 0) { + __TH_LOG_ERROR("rt_tgsigqueueinfo syscall failed"); + } + ret = waitid(P_PID, cpid, &wait_si, WEXITED, NULL); + ASSERT_EQ(ret, 0) { + __TH_LOG_ERROR("test_rt_tgsigqueueinfo: Failed on wait"); + } +} + int main(void) { test_signal_basic(); test_mq_notify(); test_timer_create(); + test_rt_sigqueueinfo(); + test_rt_tgsigqueueinfo(); return 0; } diff --git a/tools/testing/selftests/arm64/morello/signal_common.c b/tools/testing/selftests/arm64/morello/signal_common.c index 1bfbee442f29..59bb7cca1b40 100644 --- a/tools/testing/selftests/arm64/morello/signal_common.c +++ b/tools/testing/selftests/arm64/morello/signal_common.c @@ -87,3 +87,13 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value { return syscall(__NR_timer_settime, timerid, flags, new_value, old_value); } + +int rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *uinfo) +{ + return syscall(__NR_rt_sigqueueinfo, tgid, sig, uinfo); +} + +int rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig, siginfo_t *uinfo) +{ + return syscall(__NR_rt_tgsigqueueinfo, tgid, tid, sig, uinfo); +} diff --git a/tools/testing/selftests/arm64/morello/signal_common.h b/tools/testing/selftests/arm64/morello/signal_common.h index 1fdd95a95d69..cf08a3995792 100644 --- a/tools/testing/selftests/arm64/morello/signal_common.h +++ b/tools/testing/selftests/arm64/morello/signal_common.h @@ -31,5 +31,7 @@ int timer_create(clockid_t clockid, struct sigevent *sevp, timer_t *timerid); int timer_delete(timer_t timerid); int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value, struct itimerspec *old_value); +int rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *uinfo); +int rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig, siginfo_t *uinfo);
#endif /* ! SIGNAL_COMMON_H */