diff --git a/NEWS b/NEWS index 6c8f859db7..d6d64f187f 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,7 @@ Noteworthy changes in release ?.?? (????-??-??) * Implemented decoding of IFLA_GRO_MAX_SIZE and TCA_ACT_IN_HW_COUNT netlink attributes. * Implemented decoding of PR_SET_VMA operation of prctl syscall. + * Implemented decoding of siginfo_t.si_pkey field. * Updated lists of FAN_*, IORING_*, IOSQE_*, KVM_*, MODULE_INIT_*, TCA_ACT_*, and *_MAGIC constants. diff --git a/configure.ac b/configure.ac index d17ba04a77..27faa1a814 100644 --- a/configure.ac +++ b/configure.ac @@ -423,7 +423,8 @@ AC_CHECK_MEMBERS([struct utsname.domainname],,, [#include ]) AC_CHECK_MEMBERS(m4_normalize([ siginfo_t.si_syscall, siginfo_t.si_timerid, - siginfo_t.si_overrun + siginfo_t.si_overrun, + siginfo_t.si_pkey ]),,, [#include ]) AC_CHECK_HEADERS(m4_normalize([ diff --git a/src/printsiginfo.c b/src/printsiginfo.c index fb21a061b3..4999a33890 100644 --- a/src/printsiginfo.c +++ b/src/printsiginfo.c @@ -161,10 +161,23 @@ print_si_info(struct tcb *tcp, const siginfo_t *sip) tprint_struct_next(); PRINT_FIELD_U(*sip, si_stime); break; - case SIGILL: case SIGFPE: - case SIGSEGV: case SIGBUS: + case SIGILL: + case SIGFPE: + case SIGBUS: + tprint_struct_next(); + PRINT_FIELD_PTR(*sip, si_addr); + break; + case SIGSEGV: tprint_struct_next(); PRINT_FIELD_PTR(*sip, si_addr); +#ifdef HAVE_SIGINFO_T_SI_PKEY + switch (sip->si_code) { + case SEGV_PKUERR: + tprint_struct_next(); + PRINT_FIELD_U(*sip, si_pkey); + break; + } +#endif break; case SIGPOLL: switch (sip->si_code) { diff --git a/tests/.gitignore b/tests/.gitignore index a636eceb36..5a2f2649d8 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -860,6 +860,8 @@ seccomp_get_action_avail seccomp_get_notif_sizes seccomp_get_notif_sizes-success secontext.am +segv_accerr +segv_pkuerr select select-P semop diff --git a/tests/Makefile.am b/tests/Makefile.am index 9623e672dc..22a494539e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -335,6 +335,8 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ seccomp-filter-v \ seccomp-strict \ seccomp_get_notif_sizes-success \ + segv_accerr \ + segv_pkuerr \ select-P \ set_ptracer_any \ set_sigblock \ diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 23b9bce1da..c11d129af2 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -840,6 +840,8 @@ seccomp-filter-v -v -e trace=seccomp seccomp_get_action_avail -e trace=seccomp seccomp_get_notif_sizes -etrace=seccomp -a42 seccomp_get_notif_sizes-success -einject=seccomp:retval=42 -etrace=seccomp -a42 +segv_accerr -qq --trace=none +segv_pkuerr -qq --trace=none select -a36 select-P -a36 -e trace=select -P /dev/full 9>>/dev/full semop -a32 diff --git a/tests/ptrace.c b/tests/ptrace.c index 0ecd3c7b75..5266f0c069 100644 --- a/tests/ptrace.c +++ b/tests/ptrace.c @@ -1854,6 +1854,22 @@ main(void) XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, XLAT_ARGS(SIGPROF), sip->si_code, sip->si_errno, errstr); +#ifdef HAVE_SIGINFO_T_SI_PKEY + memset(sip, -1, sizeof(*sip)); + sip->si_signo = SIGSEGV; + sip->si_code = SEGV_PKUERR; + sip->si_errno = 0; + sip->si_addr = (void *) (unsigned long) 0xfacefeeddeadbeefULL; + sip->si_pkey = 0xbadc0ded; + + do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip); + printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U + ", si_code=" XLAT_FMT ", si_addr=%p, si_pkey=%u}) = %s\n", + XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request, + XLAT_ARGS(SIGSEGV), XLAT_ARGS(SEGV_PKUERR), + sip->si_addr, sip->si_pkey, errstr); +#endif + #ifdef HAVE_SIGINFO_T_SI_SYSCALL memset(sip, -1, sizeof(*sip)); sip->si_signo = SIGSYS; diff --git a/tests/segv_accerr.c b/tests/segv_accerr.c new file mode 100644 index 0000000000..1b50470f25 --- /dev/null +++ b/tests/segv_accerr.c @@ -0,0 +1,53 @@ +/* + * Check decoding of SEGV_ACCERR. + * + * Copyright (c) 2022 Dmitry V. Levin + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include + +#ifdef SEGV_ACCERR + +# include +# include +# include +# include + +static void +handler(int sig) +{ + _exit(0); +} + +int +main(void) { + int *p = mmap(NULL, get_page_size(), PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (p == MAP_FAILED) + perror_msg_and_fail("mmap"); + + const struct sigaction act = { + .sa_handler = handler, + .sa_flags = SA_RESETHAND + }; + if (sigaction(SIGSEGV, &act, NULL)) + perror_msg_and_fail("sigaction"); + + printf("--- SIGSEGV {si_signo=SIGSEGV" + ", si_code=SEGV_ACCERR, si_addr=%p} ---\n", p); + fflush(stdout); + + __asm__ volatile("":: "r" (*p)); + + error_msg_and_skip("PROT_NONE page is readable"); +} + +#else + +SKIP_MAIN_UNDEFINED("SEGV_ACCERR") + +#endif diff --git a/tests/segv_pkuerr.c b/tests/segv_pkuerr.c new file mode 100644 index 0000000000..92b867e600 --- /dev/null +++ b/tests/segv_pkuerr.c @@ -0,0 +1,55 @@ +/* + * Check decoding of SEGV_PKUERR. + * + * Copyright (c) 2022 Dmitry V. Levin + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include + +#if defined HAVE_SIGINFO_T_SI_PKEY && defined SEGV_PKUERR + +# include +# include +# include +# include + +static void +handler(int sig, siginfo_t *info, void *ucontext) +{ + if (info->si_code != SEGV_PKUERR) + error_msg_and_skip("SIGSEGV: si_code = %d", info->si_code); + + printf("--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_PKUERR" + ", si_addr=%p, si_pkey=%u} ---\n", + info->si_addr, info->si_pkey); + exit(0); +} + +int +main(void) { + int *p = mmap(NULL, get_page_size(), PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (p == MAP_FAILED) + perror_msg_and_fail("mmap"); + + const struct sigaction act = { + .sa_sigaction = handler, + .sa_flags = SA_SIGINFO | SA_RESETHAND + }; + if (sigaction(SIGSEGV, &act, NULL)) + perror_msg_and_fail("sigaction"); + + __asm__ volatile("":: "r" (*p)); + + error_msg_and_skip("PROT_EXEC page is readable"); +} + +#else + +SKIP_MAIN_UNDEFINED("HAVE_SIGINFO_T_SI_PKEY && SEGV_PKUERR") + +#endif