mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
platform/ptrace: make some operations arch specific
Make the patchSignalInfo/cpuid faulting/initial thread seccomp rules operations architecture dependent. Signed-off-by: Haibo Xu <haibo.xu@arm.com> Change-Id: Iaf692dbe3700d2e01168ec2f1b4beeda9136fd62
This commit is contained in:
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user