summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Syromyatnikov <evgsyr@gmail.com>2022-08-03 14:56:53 +0200
committerEugene Syromyatnikov <evgsyr@gmail.com>2022-08-09 10:34:31 +0200
commit8ad09429b7d27e85c0fdc1e043ed16ab10746240 (patch)
treee267439b86494bf1fba720739d87f098691a5596
parent8495c8b757c5ff66500fe09326a5ee1fc1aea26c (diff)
downloadstrace-8ad09429b7d27e85c0fdc1e043ed16ab10746240.tar.gz
printsiginfo: print si_lower/si_upper for SEGV_BNDERR signals
* configure.ac (AC_CHECK_MEMBERS): Add siginfo_t.si_lower and siginfo_t.si_upper checks. * src/printsiginfo.c (print_si_info): [!SEGV_STACKFLOW && HAVE_SIGINFO_T_SI_LOWER] <case SIGSEGV>: Print si_lower and si_upper fields if si_code is SEGV_BNDERR. * tests/ptrace.c: Add checks.
-rw-r--r--configure.ac4
-rw-r--r--src/printsiginfo.c16
-rw-r--r--tests/ptrace.c99
3 files changed, 107 insertions, 12 deletions
diff --git a/configure.ac b/configure.ac
index 30dab8eea..4dd35adad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -425,7 +425,9 @@ AC_CHECK_MEMBERS(m4_normalize([
siginfo_t.si_timerid,
siginfo_t.si_overrun,
siginfo_t.si_pkey,
- siginfo_t.si_addr_lsb
+ siginfo_t.si_addr_lsb,
+ siginfo_t.si_lower,
+ siginfo_t.si_upper
]),,, [#include <signal.h>])
AC_CHECK_HEADERS(m4_normalize([
diff --git a/src/printsiginfo.c b/src/printsiginfo.c
index c49bf0163..f9990d219 100644
--- a/src/printsiginfo.c
+++ b/src/printsiginfo.c
@@ -179,14 +179,26 @@ print_si_info(struct tcb *tcp, const siginfo_t *sip)
case SIGSEGV:
tprint_struct_next();
PRINT_FIELD_PTR(*sip, si_addr);
-#ifdef HAVE_SIGINFO_T_SI_PKEY
+#if (!defined(SEGV_STACKFLOW) && defined(HAVE_SIGINFO_T_SI_LOWER)) \
+ || (!defined(__SEGV_PSTKOVF) && defined(HAVE_SIGINFO_T_SI_PKEY))
switch (sip->si_code) {
+# if !defined(SEGV_STACKFLOW) && defined(HAVE_SIGINFO_T_SI_LOWER)
+ case SEGV_BNDERR:
+ tprint_struct_next();
+ PRINT_FIELD_PTR(*sip, si_lower);
+ tprint_struct_next();
+ PRINT_FIELD_PTR(*sip, si_upper);
+ break;
+# endif /* !SEGV_STACKFLOW && HAVE_SIGINFO_T_SI_LOWER */
+# if !defined(__SEGV_PSTKOVF) && defined(HAVE_SIGINFO_T_SI_PKEY)
case SEGV_PKUERR:
tprint_struct_next();
PRINT_FIELD_U(*sip, si_pkey);
break;
+# endif /* !__SEGV_PSTKOVF && HAVE_SIGINFO_T_SI_PKEY */
}
-#endif
+#endif /* !SEGV_STACKFLOW && HAVE_SIGINFO_T_SI_LOWER
+ * || !__SEGV_PSTKOVF && HAVE_SIGINFO_T_SI_PKEY */
break;
case SIGPOLL:
switch (sip->si_code) {
diff --git a/tests/ptrace.c b/tests/ptrace.c
index c22403ec9..c60cdea97 100644
--- a/tests/ptrace.c
+++ b/tests/ptrace.c
@@ -33,6 +33,12 @@
#undef XLAT_MACROS_ONLY
#include "xlat/audit_arch.h"
+#if SIZEOF_LONG > 4
+# define UP64BIT(a_) a_
+#else
+# define UP64BIT(a_)
+#endif
+
struct valstraux {
int val;
const char *str;
@@ -1890,21 +1896,96 @@ main(void)
XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
XLAT_ARGS(SIGPROF), sip->si_code, sip->si_errno, errstr);
-#if defined HAVE_SIGINFO_T_SI_PKEY && defined SEGV_PKUERR
+ /* SIGSEGV */
+ struct valstraux segv_codes[] = {
+ { ARG_XLAT_KNOWN(0x1, "SEGV_MAPERR") },
+ { ARG_XLAT_KNOWN(0x2, "SEGV_ACCERR") },
+#ifdef SEGV_STACKFLOW
+ { ARG_XLAT_KNOWN(0x3, "SEGV_STACKFLOW") },
+#else
+ { ARG_XLAT_KNOWN(0x3, "SEGV_BNDERR"), ""
+# ifdef HAVE_SIGINFO_T_SI_LOWER
+ ", si_lower=NULL, si_upper=NULL"
+ },
+ { ARG_XLAT_KNOWN(0x3, "SEGV_BNDERR"),
+ ", si_lower=NULL"
+ ", si_upper=0x" UP64BIT("deadc0de") "beadfeed" },
+ { ARG_XLAT_KNOWN(0x3, "SEGV_BNDERR"),
+ ", si_lower=0x" UP64BIT("facecafe") "befeeded"
+ ", si_upper=NULL" },
+ { ARG_XLAT_KNOWN(0x3, "SEGV_BNDERR"),
+ ", si_lower=0x" UP64BIT("beefface") "cafedead"
+ ", si_upper=0x" UP64BIT("badc0ded") "dadfaced",
+#endif /* HAVE_SIGINFO_T_SI_LOWER */
+ },
+#endif /* SEGV_STACKFLOW */
+#ifdef __SEGV_PSTKOVF
+ { ARG_XLAT_KNOWN(0x4, "__SEGV_PSTKOVF") },
+#else
+ { ARG_XLAT_KNOWN(0x4, "SEGV_PKUERR"), ""
+# ifdef HAVE_SIGINFO_T_SI_PKEY
+ ", si_pkey=0"
+ },
+ { ARG_XLAT_KNOWN(0x4, "SEGV_PKUERR"), ", si_pkey=1234567890" },
+ { ARG_XLAT_KNOWN(0x4, "SEGV_PKUERR"), ", si_pkey=3141592653"
+# endif /* HAVE_SIGINFO_T_SI_PKEY */
+ },
+#endif /* __SEGV_PSTKOVF */
+ { ARG_XLAT_KNOWN(0x5, "SEGV_ACCADI") },
+ { ARG_XLAT_KNOWN(0x6, "SEGV_ADIDERR") },
+ { ARG_XLAT_KNOWN(0x7, "SEGV_ADIPERR") },
+ { ARG_XLAT_KNOWN(0x8, "SEGV_MTEAERR") },
+ { ARG_XLAT_KNOWN(0x9, "SEGV_MTESERR") },
+ { ARG_STR(0xa) },
+ { ARG_STR(0x499602d2) },
+ };
+ uint32_t segv_pkey_vecs[] = { 0, 1234567890, 3141592653U };
+ struct {
+ void *lower;
+ void *upper;
+ } segv_bnd_vecs[] = {
+ { 0, 0 },
+ { 0, (void *) (uintptr_t) 0xdeadc0debeadfeedULL },
+ { (void *) (uintptr_t) 0xfacecafebefeededULL, 0 },
+ { (void *) (uintptr_t) 0xbeeffacecafedeadULL,
+ (void *) (uintptr_t) 0xbadc0deddadfacedULL },
+ };
+ size_t segv_pkey_pos = 0;
+ size_t segv_bnd_pos = 0;
+
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);
+ for (size_t i = 0; i < ARRAY_SIZE(segv_codes); i++) {
+ sip->si_code = segv_codes[i].val;
+
+ switch (sip->si_code) {
+ case 3: /* SEGV_BNDERR */
+#ifdef HAVE_SIGINFO_T_SI_LOWER
+ sip->si_lower = segv_bnd_vecs[segv_bnd_pos].lower;
+ sip->si_upper = segv_bnd_vecs[segv_bnd_pos].upper;
+#endif
+ segv_bnd_pos = (segv_bnd_pos + 1)
+ % ARRAY_SIZE(segv_bnd_vecs);
+ break;
+ case 4: /* SEGV_PKUERR */
+#ifdef HAVE_SIGINFO_T_SI_PKEY
+ sip->si_pkey = segv_pkey_vecs[segv_pkey_pos];
#endif
+ segv_pkey_pos = (segv_pkey_pos + 1)
+ % ARRAY_SIZE(segv_pkey_vecs);
+ break;
+ };
+
+ do_ptrace(PTRACE_SETSIGINFO, pid, bad_request, (uintptr_t) sip);
+ printf("ptrace(" XLAT_FMT ", %d, %#lx, {si_signo=" XLAT_FMT_U
+ ", si_code=%s, si_addr=%p%s}) = %s\n",
+ XLAT_ARGS(PTRACE_SETSIGINFO), pid, bad_request,
+ XLAT_ARGS(SIGSEGV), segv_codes[i].str,
+ sip->si_addr, segv_codes[i].aux ?: "", errstr);
+ }
#ifdef HAVE_SIGINFO_T_SI_SYSCALL
memset(sip, -1, sizeof(*sip));