diff options
Diffstat (limited to 'pkg/sentry/arch')
-rw-r--r-- | pkg/sentry/arch/arch.go | 3 | ||||
-rw-r--r-- | pkg/sentry/arch/arch_aarch64.go | 9 | ||||
-rw-r--r-- | pkg/sentry/arch/arch_arm64.go | 13 | ||||
-rw-r--r-- | pkg/sentry/arch/arch_state_x86.go | 2 | ||||
-rw-r--r-- | pkg/sentry/arch/arch_x86.go | 2 | ||||
-rw-r--r-- | pkg/sentry/arch/arch_x86_impl.go | 2 | ||||
-rw-r--r-- | pkg/sentry/arch/signal_arm64.go | 30 | ||||
-rw-r--r-- | pkg/sentry/arch/signal_stack.go | 2 | ||||
-rw-r--r-- | pkg/sentry/arch/stack.go | 3 | ||||
-rw-r--r-- | pkg/sentry/arch/syscalls_amd64.go | 7 | ||||
-rw-r--r-- | pkg/sentry/arch/syscalls_arm64.go | 23 |
11 files changed, 75 insertions, 21 deletions
diff --git a/pkg/sentry/arch/arch.go b/pkg/sentry/arch/arch.go index 1d11cc472..a903d031c 100644 --- a/pkg/sentry/arch/arch.go +++ b/pkg/sentry/arch/arch.go @@ -88,6 +88,9 @@ type Context interface { // SyscallNo returns the syscall number. SyscallNo() uintptr + // SyscallSaveOrig save orignal register value. + SyscallSaveOrig() + // SyscallArgs returns the syscall arguments in an array. SyscallArgs() SyscallArguments diff --git a/pkg/sentry/arch/arch_aarch64.go b/pkg/sentry/arch/arch_aarch64.go index 5053393c1..c29e1b841 100644 --- a/pkg/sentry/arch/arch_aarch64.go +++ b/pkg/sentry/arch/arch_aarch64.go @@ -95,8 +95,14 @@ type State struct { // Our floating point state. aarch64FPState `state:"wait"` + // TLS pointer + TPValue uint64 + // FeatureSet is a pointer to the currently active feature set. FeatureSet *cpuid.FeatureSet + + // OrigR0 stores the value of register R0. + OrigR0 uint64 } // Proto returns a protobuf representation of the system registers in State. @@ -145,7 +151,9 @@ func (s *State) Fork() State { return State{ Regs: s.Regs, aarch64FPState: s.aarch64FPState.fork(), + TPValue: s.TPValue, FeatureSet: s.FeatureSet, + OrigR0: s.OrigR0, } } @@ -255,6 +263,7 @@ func (s *State) PtraceSetFPRegs(src io.Reader) (int, error) { const ( _NT_PRSTATUS = 1 _NT_PRFPREG = 2 + _NT_ARM_TLS = 0x401 ) // PtraceGetRegSet implements Context.PtraceGetRegSet. diff --git a/pkg/sentry/arch/arch_arm64.go b/pkg/sentry/arch/arch_arm64.go index 885115ae2..db99c5acb 100644 --- a/pkg/sentry/arch/arch_arm64.go +++ b/pkg/sentry/arch/arch_arm64.go @@ -140,16 +140,17 @@ func (c *context64) SetStack(value uintptr) { // TLS returns the current TLS pointer. func (c *context64) TLS() uintptr { - // TODO(gvisor.dev/issue/1238): TLS is not supported. - // MRS_TPIDR_EL0 - return 0 + return uintptr(c.TPValue) } // SetTLS sets the current TLS pointer. Returns false if value is invalid. func (c *context64) SetTLS(value uintptr) bool { - // TODO(gvisor.dev/issue/1238): TLS is not supported. - // MSR_TPIDR_EL0 - return false + if value >= uintptr(maxAddr64) { + return false + } + + c.TPValue = uint64(value) + return true } // SetOldRSeqInterruptedIP implements Context.SetOldRSeqInterruptedIP. diff --git a/pkg/sentry/arch/arch_state_x86.go b/pkg/sentry/arch/arch_state_x86.go index e35c9214a..aa31169e0 100644 --- a/pkg/sentry/arch/arch_state_x86.go +++ b/pkg/sentry/arch/arch_state_x86.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build amd64 i386 +// +build amd64 386 package arch diff --git a/pkg/sentry/arch/arch_x86.go b/pkg/sentry/arch/arch_x86.go index 88b40a9d1..7fc4c0473 100644 --- a/pkg/sentry/arch/arch_x86.go +++ b/pkg/sentry/arch/arch_x86.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build amd64 i386 +// +build amd64 386 package arch diff --git a/pkg/sentry/arch/arch_x86_impl.go b/pkg/sentry/arch/arch_x86_impl.go index 04ac283c6..3edf40764 100644 --- a/pkg/sentry/arch/arch_x86_impl.go +++ b/pkg/sentry/arch/arch_x86_impl.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build amd64 i386 +// +build amd64 386 package arch diff --git a/pkg/sentry/arch/signal_arm64.go b/pkg/sentry/arch/signal_arm64.go index 0c1db4b13..1cb1adf8c 100644 --- a/pkg/sentry/arch/signal_arm64.go +++ b/pkg/sentry/arch/signal_arm64.go @@ -98,9 +98,12 @@ func (c *context64) SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt if ucSize < 0 { panic("can't get size of UContext64") } - // st.Arch.Width() is for the restorer address. sizeof(siginfo) == 128. - frameSize := int(st.Arch.Width()) + ucSize + 128 - frameBottom := (sp-usermem.Addr(frameSize)) & ^usermem.Addr(15) - 8 + + // frameSize = ucSize + sizeof(siginfo). + // sizeof(siginfo) == 128. + // R30 stores the restorer address. + frameSize := ucSize + 128 + frameBottom := (sp - usermem.Addr(frameSize)) & ^usermem.Addr(15) sp = frameBottom + usermem.Addr(frameSize) st.Bottom = sp @@ -130,12 +133,27 @@ func (c *context64) SignalSetup(st *Stack, act *SignalAct, info *SignalInfo, alt c.Regs.Regs[0] = uint64(info.Signo) c.Regs.Regs[1] = uint64(infoAddr) c.Regs.Regs[2] = uint64(ucAddr) - + c.Regs.Regs[30] = uint64(act.Restorer) return nil } // SignalRestore implements Context.SignalRestore. -// Only used on intel. func (c *context64) SignalRestore(st *Stack, rt bool) (linux.SignalSet, SignalStack, error) { - return 0, SignalStack{}, nil + // Copy out the stack frame. + var uc UContext64 + if _, err := st.Pop(&uc); err != nil { + return 0, SignalStack{}, err + } + var info SignalInfo + if _, err := st.Pop(&info); err != nil { + return 0, SignalStack{}, err + } + + // Restore registers. + c.Regs.Regs = uc.MContext.Regs + c.Regs.Pc = uc.MContext.Pc + c.Regs.Sp = uc.MContext.Sp + c.Regs.Pstate = uc.MContext.Pstate + + return uc.Sigset, uc.Stack, nil } diff --git a/pkg/sentry/arch/signal_stack.go b/pkg/sentry/arch/signal_stack.go index 1a6056171..e58f055c7 100644 --- a/pkg/sentry/arch/signal_stack.go +++ b/pkg/sentry/arch/signal_stack.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build i386 amd64 arm64 +// +build 386 amd64 arm64 package arch diff --git a/pkg/sentry/arch/stack.go b/pkg/sentry/arch/stack.go index 09bceabc9..1108fa0bd 100644 --- a/pkg/sentry/arch/stack.go +++ b/pkg/sentry/arch/stack.go @@ -97,7 +97,6 @@ func (s *Stack) Push(vals ...interface{}) (usermem.Addr, error) { if c < 0 { return 0, fmt.Errorf("bad binary.Size for %T", v) } - // TODO(b/38173783): Use a real context.Context. n, err := usermem.CopyObjectOut(context.Background(), s.IO, s.Bottom-usermem.Addr(c), norm, usermem.IOOpts{}) if err != nil || c != n { return 0, err @@ -121,11 +120,9 @@ func (s *Stack) Pop(vals ...interface{}) (usermem.Addr, error) { var err error if isVaddr { value := s.Arch.Native(uintptr(0)) - // TODO(b/38173783): Use a real context.Context. n, err = usermem.CopyObjectIn(context.Background(), s.IO, s.Bottom, value, usermem.IOOpts{}) *vaddr = usermem.Addr(s.Arch.Value(value)) } else { - // TODO(b/38173783): Use a real context.Context. n, err = usermem.CopyObjectIn(context.Background(), s.IO, s.Bottom, v, usermem.IOOpts{}) } if err != nil { diff --git a/pkg/sentry/arch/syscalls_amd64.go b/pkg/sentry/arch/syscalls_amd64.go index 8b4f23007..3859f41ee 100644 --- a/pkg/sentry/arch/syscalls_amd64.go +++ b/pkg/sentry/arch/syscalls_amd64.go @@ -18,6 +18,13 @@ package arch const restartSyscallNr = uintptr(219) +// SyscallSaveOrig save the value of the register which is clobbered in +// syscall handler(doSyscall()). +// +// Noop on x86. +func (c *context64) SyscallSaveOrig() { +} + // SyscallNo returns the syscall number according to the 64-bit convention. func (c *context64) SyscallNo() uintptr { return uintptr(c.Regs.Orig_rax) diff --git a/pkg/sentry/arch/syscalls_arm64.go b/pkg/sentry/arch/syscalls_arm64.go index 00d5ef461..92d062513 100644 --- a/pkg/sentry/arch/syscalls_arm64.go +++ b/pkg/sentry/arch/syscalls_arm64.go @@ -18,6 +18,17 @@ package arch const restartSyscallNr = uintptr(128) +// SyscallSaveOrig save the value of the register R0 which is clobbered in +// syscall handler(doSyscall()). +// +// In linux, at the entry of the syscall handler(el0_svc_common()), value of R0 +// is saved to the pt_regs.orig_x0 in kernel code. But currently, the orig_x0 +// was not accessible to the user space application, so we have to do the same +// operation in the sentry code to save the R0 value into the App context. +func (c *context64) SyscallSaveOrig() { + c.OrigR0 = c.Regs.Regs[0] +} + // SyscallNo returns the syscall number according to the 64-bit convention. func (c *context64) SyscallNo() uintptr { return uintptr(c.Regs.Regs[8]) @@ -40,7 +51,7 @@ func (c *context64) SyscallNo() uintptr { // R30: the link register. func (c *context64) SyscallArgs() SyscallArguments { return SyscallArguments{ - SyscallArgument{Value: uintptr(c.Regs.Regs[0])}, + SyscallArgument{Value: uintptr(c.OrigR0)}, SyscallArgument{Value: uintptr(c.Regs.Regs[1])}, SyscallArgument{Value: uintptr(c.Regs.Regs[2])}, SyscallArgument{Value: uintptr(c.Regs.Regs[3])}, @@ -50,13 +61,21 @@ func (c *context64) SyscallArgs() SyscallArguments { } // RestartSyscall implements Context.RestartSyscall. +// Prepare for system call restart, OrigR0 will be restored to R0. +// Please see the linux code as reference: +// arch/arm64/kernel/signal.c:do_signal() func (c *context64) RestartSyscall() { c.Regs.Pc -= SyscallWidth - c.Regs.Regs[8] = uint64(restartSyscallNr) + // R0 will be backed up into OrigR0 when entering doSyscall(). + // Please see the linux code as reference: + // arch/arm64/kernel/syscall.c:el0_svc_common(). + // Here we restore it back. + c.Regs.Regs[0] = uint64(c.OrigR0) } // RestartSyscallWithRestartBlock implements Context.RestartSyscallWithRestartBlock. func (c *context64) RestartSyscallWithRestartBlock() { c.Regs.Pc -= SyscallWidth + c.Regs.Regs[0] = uint64(c.OrigR0) c.Regs.Regs[8] = uint64(restartSyscallNr) } |