diff options
author | Andrei Vagin <avagin@google.com> | 2021-01-19 15:31:49 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-01-19 15:34:02 -0800 |
commit | 48ea2c34d1d3dead7727d9e2760b587c7609b14b (patch) | |
tree | 7b8e2c8bc3a2a1a8da7f780800e4d2aae674b943 /pkg/sentry/platform/ptrace/subprocess.go | |
parent | be17b94446b2f96c2a3d531fe20271537c77c8aa (diff) |
platform/ptrace: workaround a kernel ptrace issue on ARM64
On ARM64, when ptrace stops on a system call, it uses the x7 register to
indicate whether the stop has been signalled from syscall entry or syscall
exit. This means that we can't get a value of this register and we can't change
it. More details are in the comment for tracehook_report_syscall in
arch/arm64/kernel/ptrace.c.
This happens only if we stop on a system call, so let's queue a signal, resume
a stub thread and catch it on a signal handling.
Fixes: #5238
PiperOrigin-RevId: 352668695
Diffstat (limited to 'pkg/sentry/platform/ptrace/subprocess.go')
-rw-r--r-- | pkg/sentry/platform/ptrace/subprocess.go | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/pkg/sentry/platform/ptrace/subprocess.go b/pkg/sentry/platform/ptrace/subprocess.go index aacd7ce70..17fb0a0d8 100644 --- a/pkg/sentry/platform/ptrace/subprocess.go +++ b/pkg/sentry/platform/ptrace/subprocess.go @@ -550,6 +550,12 @@ func (s *subprocess) switchToApp(c *context, ac arch.Context) bool { // Wait for the syscall-enter stop. sig := t.wait(stopped) + if sig == syscall.SIGSTOP { + // SIGSTOP was delivered to another thread in the same thread + // group, which initiated another group stop. Just ignore it. + continue + } + // Refresh all registers. if err := t.getRegs(regs); err != nil { panic(fmt.Sprintf("ptrace get regs failed: %v", err)) @@ -566,13 +572,11 @@ func (s *subprocess) switchToApp(c *context, ac arch.Context) bool { // Is it a system call? if sig == (syscallEvent | syscall.SIGTRAP) { + s.arm64SyscallWorkaround(t, regs) + // Ensure registers are sane. updateSyscallRegs(regs) return true - } else if sig == syscall.SIGSTOP { - // SIGSTOP was delivered to another thread in the same thread - // group, which initiated another group stop. Just ignore it. - continue } // Grab signal information. |