From: Eugene Syromyatnikov Date: Mon, 15 Jan 2018 20:49:14 +0000 (+0100) Subject: syscall.c: add ability to set personality based on GETREGSET iov size X-Git-Tag: v4.21~133 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=64fd0ce626accf9c269bd3afb8206cdccbae9a6f;p=strace syscall.c: add ability to set personality based on GETREGSET iov size Some architectures (aarch64, s390x) use only PTRACE_GETREGSET interface and use its size to detect current personality. Let's generalise this approach and also avoid subtle errors when we get register but forget to update personality, at least for those architectures. Note that in order to employ this behaviour, architecture has to use PTRACE_GETREGSET exclusively (no HAVE_GETREGS_OLD) and should declare appropriate ARCH_PERSONALITY_*_IOV_SIZE macros. * syscall.c (get_regs) [ptrace_getregset_or_getregs && !HAVE_GETREGS_OLD]: Call update_personality based on the value returned in the iov_len field by PTRACE_GETREGSET. Warn once if the returned iov_len is unknown. --- diff --git a/syscall.c b/syscall.c index 444bfa1e..1a45b977 100644 --- a/syscall.c +++ b/syscall.c @@ -1154,7 +1154,37 @@ get_regs(struct tcb *const tcp) return get_regs_error = getregs_old(tcp); # else /* !HAVE_GETREGS_OLD */ /* Assume that PTRACE_GETREGSET/PTRACE_GETREGS works. */ - return get_regs_error = ptrace_getregset_or_getregs(tcp->pid); + get_regs_error = ptrace_getregset_or_getregs(tcp->pid); + +# if defined ARCH_PERSONALITY_0_IOV_SIZE + if (get_regs_error) + return get_regs_error; + + switch (ARCH_IOVEC_FOR_GETREGSET.iov_len) { + case ARCH_PERSONALITY_0_IOV_SIZE: + update_personality(tcp, 0); + break; + case ARCH_PERSONALITY_1_IOV_SIZE: + update_personality(tcp, 1); + break; + default: { + static bool printed = false; + + if (!printed) { + error_msg("Unsupported regset size returned by " + "PTRACE_GETREGSET: %zu", + ARCH_IOVEC_FOR_GETREGSET.iov_len); + + printed = true; + } + + update_personality(tcp, 0); + } + } +# endif /* ARCH_PERSONALITY_0_IOV_SIZE */ + + return get_regs_error; + # endif /* !HAVE_GETREGS_OLD */ #else /* !ptrace_getregset_or_getregs */