Merge pull request #1248 from xiaobo55x:ptrace

PiperOrigin-RevId: 285038987
This commit is contained in:
gVisor bot
2019-12-11 13:52:24 -08:00
3 changed files with 85 additions and 30 deletions
@@ -21,6 +21,8 @@ import (
"strings"
"syscall"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/seccomp"
"gvisor.dev/gvisor/pkg/sentry/arch"
)
@@ -143,3 +145,43 @@ func (t *thread) adjustInitRegsRip() {
func initChildProcessPPID(initregs *syscall.PtraceRegs, ppid int32) {
initregs.R15 = uint64(ppid)
}
// patchSignalInfo patches the signal info to account for hitting the seccomp
// filters from vsyscall emulation, specified below. We allow for SIGSYS as a
// synchronous trap, but patch the structure to appear like a SIGSEGV with the
// Rip as the faulting address.
//
// Note that this should only be called after verifying that the signalInfo has
// been generated by the kernel.
func patchSignalInfo(regs *syscall.PtraceRegs, signalInfo *arch.SignalInfo) {
if linux.Signal(signalInfo.Signo) == linux.SIGSYS {
signalInfo.Signo = int32(linux.SIGSEGV)
// Unwind the kernel emulation, if any has occurred. A SIGSYS is delivered
// with the si_call_addr field pointing to the current RIP. This field
// aligns with the si_addr field for a SIGSEGV, so we don't need to touch
// anything there. We do need to unwind emulation however, so we set the
// instruction pointer to the faulting value, and "unpop" the stack.
regs.Rip = signalInfo.Addr()
regs.Rsp -= 8
}
}
// enableCpuidFault enable cpuid-faulting; this may fail on older kernels or hardware,
// so we just disregard the result. Host CPUID will be enabled.
func enableCpuidFault() {
syscall.RawSyscall6(syscall.SYS_ARCH_PRCTL, linux.ARCH_SET_CPUID, 0, 0, 0, 0, 0)
}
// appendArchSeccompRules append architecture specific seccomp rules when creating BPF program.
// Ref attachedThread() for more detail.
func appendArchSeccompRules(rules []seccomp.RuleSet) []seccomp.RuleSet {
return append(rules, seccomp.RuleSet{
Rules: seccomp.SyscallRules{
syscall.SYS_ARCH_PRCTL: []seccomp.Rule{
{seccomp.AllowValue(linux.ARCH_SET_CPUID), seccomp.AllowValue(0)},
},
},
Action: linux.SECCOMP_RET_ALLOW,
})
}
+36 -1
View File
@@ -17,8 +17,12 @@
package ptrace
import (
"fmt"
"strings"
"syscall"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/seccomp"
"gvisor.dev/gvisor/pkg/sentry/arch"
)
@@ -37,7 +41,7 @@ const (
// resetSysemuRegs sets up emulation registers.
//
// This should be called prior to calling sysemu.
func (s *subprocess) resetSysemuRegs(regs *syscall.PtraceRegs) {
func (t *thread) resetSysemuRegs(regs *syscall.PtraceRegs) {
}
// createSyscallRegs sets up syscall registers.
@@ -124,3 +128,34 @@ func (t *thread) adjustInitRegsRip() {
func initChildProcessPPID(initregs *syscall.PtraceRegs, ppid int32) {
initregs.Regs[7] = uint64(ppid)
}
// patchSignalInfo patches the signal info to account for hitting the seccomp
// filters from vsyscall emulation, specified below. We allow for SIGSYS as a
// synchronous trap, but patch the structure to appear like a SIGSEGV with the
// Rip as the faulting address.
//
// Note that this should only be called after verifying that the signalInfo has
// been generated by the kernel.
func patchSignalInfo(regs *syscall.PtraceRegs, signalInfo *arch.SignalInfo) {
if linux.Signal(signalInfo.Signo) == linux.SIGSYS {
signalInfo.Signo = int32(linux.SIGSEGV)
// Unwind the kernel emulation, if any has occurred. A SIGSYS is delivered
// with the si_call_addr field pointing to the current RIP. This field
// aligns with the si_addr field for a SIGSEGV, so we don't need to touch
// anything there. We do need to unwind emulation however, so we set the
// instruction pointer to the faulting value, and "unpop" the stack.
regs.Pc = signalInfo.Addr()
regs.Sp -= 8
}
}
// Noop on arm64.
func enableCpuidFault() {
}
// appendArchSeccompRules append architecture specific seccomp rules when creating BPF program.
// Ref attachedThread() for more detail.
func appendArchSeccompRules(rules []seccomp.RuleSet) []seccomp.RuleSet {
return rules
}
+7 -29
View File
@@ -20,6 +20,7 @@ import (
"fmt"
"syscall"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/procid"
@@ -77,27 +78,6 @@ func probeSeccomp() bool {
}
}
// patchSignalInfo patches the signal info to account for hitting the seccomp
// filters from vsyscall emulation, specified below. We allow for SIGSYS as a
// synchronous trap, but patch the structure to appear like a SIGSEGV with the
// Rip as the faulting address.
//
// Note that this should only be called after verifying that the signalInfo has
// been generated by the kernel.
func patchSignalInfo(regs *syscall.PtraceRegs, signalInfo *arch.SignalInfo) {
if linux.Signal(signalInfo.Signo) == linux.SIGSYS {
signalInfo.Signo = int32(linux.SIGSEGV)
// Unwind the kernel emulation, if any has occurred. A SIGSYS is delivered
// with the si_call_addr field pointing to the current RIP. This field
// aligns with the si_addr field for a SIGSEGV, so we don't need to touch
// anything there. We do need to unwind emulation however, so we set the
// instruction pointer to the faulting value, and "unpop" the stack.
regs.Rip = signalInfo.Addr()
regs.Rsp -= 8
}
}
// createStub creates a fresh stub processes.
//
// Precondition: the runtime OS thread must be locked.
@@ -149,7 +129,7 @@ func attachedThread(flags uintptr, defaultAction linux.BPFAction) (*thread, erro
Rules: seccomp.SyscallRules{
syscall.SYS_GETTIMEOFDAY: {},
syscall.SYS_TIME: {},
309: {}, // SYS_GETCPU.
unix.SYS_GETCPU: {}, // SYS_GETCPU was not defined in package syscall on amd64.
},
Action: linux.SECCOMP_RET_TRAP,
Vsyscall: true,
@@ -173,10 +153,7 @@ func attachedThread(flags uintptr, defaultAction linux.BPFAction) (*thread, erro
// For the initial process creation.
syscall.SYS_WAIT4: {},
syscall.SYS_ARCH_PRCTL: []seccomp.Rule{
{seccomp.AllowValue(linux.ARCH_SET_CPUID), seccomp.AllowValue(0)},
},
syscall.SYS_EXIT: {},
syscall.SYS_EXIT: {},
// For the stub prctl dance (all).
syscall.SYS_PRCTL: []seccomp.Rule{
@@ -196,6 +173,8 @@ func attachedThread(flags uintptr, defaultAction linux.BPFAction) (*thread, erro
},
Action: linux.SECCOMP_RET_ALLOW,
})
rules = appendArchSeccompRules(rules)
}
instrs, err := seccomp.BuildProgram(rules, defaultAction)
if err != nil {
@@ -267,9 +246,8 @@ func attachedThread(flags uintptr, defaultAction linux.BPFAction) (*thread, erro
syscall.RawSyscall(syscall.SYS_EXIT, uintptr(errno), 0, 0)
}
// Enable cpuid-faulting; this may fail on older kernels or hardware,
// so we just disregard the result. Host CPUID will be enabled.
syscall.RawSyscall6(syscall.SYS_ARCH_PRCTL, linux.ARCH_SET_CPUID, 0, 0, 0, 0, 0)
// Enable cpuid-faulting.
enableCpuidFault()
// Call the stub; should not return.
stubCall(stubStart, ppid)