From 3c67754663f424f2ebbc0ff2a4c80e30618d5355 Mon Sep 17 00:00:00 2001 From: Rahat Mahmood Date: Sat, 25 Apr 2020 23:54:56 -0700 Subject: Enable automated marshalling for signals and the arch package. PiperOrigin-RevId: 308472331 --- pkg/sentry/arch/BUILD | 4 ++-- pkg/sentry/arch/arch_aarch64.go | 26 +++++++++++++--------- pkg/sentry/arch/arch_amd64.go | 13 ++++++----- pkg/sentry/arch/arch_arm64.go | 2 ++ pkg/sentry/arch/arch_state_aarch64.go | 38 ------------------------------- pkg/sentry/arch/arch_state_x86.go | 42 ----------------------------------- pkg/sentry/arch/arch_x86.go | 25 ++++++++++++--------- pkg/sentry/arch/arch_x86_impl.go | 4 +--- pkg/sentry/arch/signal.go | 3 +++ pkg/sentry/arch/signal_act.go | 4 ++++ pkg/sentry/arch/signal_stack.go | 3 +++ 11 files changed, 53 insertions(+), 111 deletions(-) delete mode 100644 pkg/sentry/arch/arch_state_aarch64.go (limited to 'pkg/sentry/arch') diff --git a/pkg/sentry/arch/BUILD b/pkg/sentry/arch/BUILD index e27f21e5e..901e0f320 100644 --- a/pkg/sentry/arch/BUILD +++ b/pkg/sentry/arch/BUILD @@ -11,7 +11,6 @@ go_library( "arch_amd64.go", "arch_amd64.s", "arch_arm64.go", - "arch_state_aarch64.go", "arch_state_x86.go", "arch_x86.go", "arch_x86_impl.go", @@ -26,11 +25,11 @@ go_library( "syscalls_amd64.go", "syscalls_arm64.go", ], + marshal = True, visibility = ["//:sandbox"], deps = [ ":registers_go_proto", "//pkg/abi/linux", - "//pkg/binary", "//pkg/context", "//pkg/cpuid", "//pkg/log", @@ -38,6 +37,7 @@ go_library( "//pkg/sync", "//pkg/syserror", "//pkg/usermem", + "//tools/go_marshal/marshal", ], ) diff --git a/pkg/sentry/arch/arch_aarch64.go b/pkg/sentry/arch/arch_aarch64.go index c29e1b841..529980267 100644 --- a/pkg/sentry/arch/arch_aarch64.go +++ b/pkg/sentry/arch/arch_aarch64.go @@ -17,18 +17,20 @@ package arch import ( + "encoding/binary" "fmt" "io" - "syscall" - "gvisor.dev/gvisor/pkg/binary" + "gvisor.dev/gvisor/pkg/abi/linux" "gvisor.dev/gvisor/pkg/cpuid" "gvisor.dev/gvisor/pkg/log" rpb "gvisor.dev/gvisor/pkg/sentry/arch/registers_go_proto" "gvisor.dev/gvisor/pkg/syserror" - "gvisor.dev/gvisor/pkg/usermem" ) +// Registers represents the CPU registers for this architecture. +type Registers = linux.PtraceRegs + const ( // SyscallWidth is the width of insturctions. SyscallWidth = 4 @@ -90,7 +92,7 @@ func NewFloatingPointData() *FloatingPointData { // file ensures it's only built on aarch64). type State struct { // The system registers. - Regs syscall.PtraceRegs `state:".(syscallPtraceRegs)"` + Regs Registers // Our floating point state. aarch64FPState `state:"wait"` @@ -226,25 +228,27 @@ func (s *State) RegisterMap() (map[string]uintptr, error) { // PtraceGetRegs implements Context.PtraceGetRegs. func (s *State) PtraceGetRegs(dst io.Writer) (int, error) { - return dst.Write(binary.Marshal(nil, usermem.ByteOrder, s.ptraceGetRegs())) + regs := s.ptraceGetRegs() + n, err := regs.WriteTo(dst) + return int(n), err } -func (s *State) ptraceGetRegs() syscall.PtraceRegs { +func (s *State) ptraceGetRegs() Registers { return s.Regs } -var ptraceRegsSize = int(binary.Size(syscall.PtraceRegs{})) +var registersSize = (*Registers)(nil).SizeBytes() // PtraceSetRegs implements Context.PtraceSetRegs. func (s *State) PtraceSetRegs(src io.Reader) (int, error) { - var regs syscall.PtraceRegs - buf := make([]byte, ptraceRegsSize) + var regs Registers + buf := make([]byte, registersSize) if _, err := io.ReadFull(src, buf); err != nil { return 0, err } - binary.Unmarshal(buf, usermem.ByteOrder, ®s) + regs.UnmarshalUnsafe(buf) s.Regs = regs - return ptraceRegsSize, nil + return registersSize, nil } // PtraceGetFPRegs implements Context.PtraceGetFPRegs. diff --git a/pkg/sentry/arch/arch_amd64.go b/pkg/sentry/arch/arch_amd64.go index 85d6acc0f..3b3a0a272 100644 --- a/pkg/sentry/arch/arch_amd64.go +++ b/pkg/sentry/arch/arch_amd64.go @@ -22,7 +22,6 @@ import ( "math/rand" "syscall" - "gvisor.dev/gvisor/pkg/binary" "gvisor.dev/gvisor/pkg/cpuid" "gvisor.dev/gvisor/pkg/sentry/limits" "gvisor.dev/gvisor/pkg/usermem" @@ -301,8 +300,10 @@ func (c *context64) PtracePeekUser(addr uintptr) (interface{}, error) { // PTRACE_PEEKUSER and PTRACE_POKEUSER are only effective on regs and // u_debugreg, returning 0 or silently no-oping for other fields // respectively. - if addr < uintptr(ptraceRegsSize) { - buf := binary.Marshal(nil, usermem.ByteOrder, c.ptraceGetRegs()) + if addr < uintptr(registersSize) { + regs := c.ptraceGetRegs() + buf := make([]byte, regs.SizeBytes()) + regs.MarshalUnsafe(buf) return c.Native(uintptr(usermem.ByteOrder.Uint64(buf[addr:]))), nil } // Note: x86 debug registers are missing. @@ -314,8 +315,10 @@ func (c *context64) PtracePokeUser(addr, data uintptr) error { if addr&7 != 0 || addr >= userStructSize { return syscall.EIO } - if addr < uintptr(ptraceRegsSize) { - buf := binary.Marshal(nil, usermem.ByteOrder, c.ptraceGetRegs()) + if addr < uintptr(registersSize) { + regs := c.ptraceGetRegs() + buf := make([]byte, regs.SizeBytes()) + regs.MarshalUnsafe(buf) usermem.ByteOrder.PutUint64(buf[addr:], uint64(data)) _, err := c.PtraceSetRegs(bytes.NewBuffer(buf)) return err diff --git a/pkg/sentry/arch/arch_arm64.go b/pkg/sentry/arch/arch_arm64.go index db99c5acb..ada7ac7b8 100644 --- a/pkg/sentry/arch/arch_arm64.go +++ b/pkg/sentry/arch/arch_arm64.go @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build arm64 + package arch import ( diff --git a/pkg/sentry/arch/arch_state_aarch64.go b/pkg/sentry/arch/arch_state_aarch64.go deleted file mode 100644 index 0136a85ad..000000000 --- a/pkg/sentry/arch/arch_state_aarch64.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2020 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// +build arm64 - -package arch - -import ( - "syscall" -) - -type syscallPtraceRegs struct { - Regs [31]uint64 - Sp uint64 - Pc uint64 - Pstate uint64 -} - -// saveRegs is invoked by stateify. -func (s *State) saveRegs() syscallPtraceRegs { - return syscallPtraceRegs(s.Regs) -} - -// loadRegs is invoked by stateify. -func (s *State) loadRegs(r syscallPtraceRegs) { - s.Regs = syscall.PtraceRegs(r) -} diff --git a/pkg/sentry/arch/arch_state_x86.go b/pkg/sentry/arch/arch_state_x86.go index aa31169e0..19ce99d25 100644 --- a/pkg/sentry/arch/arch_state_x86.go +++ b/pkg/sentry/arch/arch_state_x86.go @@ -18,7 +18,6 @@ package arch import ( "fmt" - "syscall" "gvisor.dev/gvisor/pkg/cpuid" "gvisor.dev/gvisor/pkg/usermem" @@ -90,44 +89,3 @@ func (s *State) afterLoadFPState() { // Copy to the new, aligned location. copy(s.x86FPState, old) } - -// +stateify savable -type syscallPtraceRegs struct { - R15 uint64 - R14 uint64 - R13 uint64 - R12 uint64 - Rbp uint64 - Rbx uint64 - R11 uint64 - R10 uint64 - R9 uint64 - R8 uint64 - Rax uint64 - Rcx uint64 - Rdx uint64 - Rsi uint64 - Rdi uint64 - Orig_rax uint64 - Rip uint64 - Cs uint64 - Eflags uint64 - Rsp uint64 - Ss uint64 - Fs_base uint64 - Gs_base uint64 - Ds uint64 - Es uint64 - Fs uint64 - Gs uint64 -} - -// saveRegs is invoked by stateify. -func (s *State) saveRegs() syscallPtraceRegs { - return syscallPtraceRegs(s.Regs) -} - -// loadRegs is invoked by stateify. -func (s *State) loadRegs(r syscallPtraceRegs) { - s.Regs = syscall.PtraceRegs(r) -} diff --git a/pkg/sentry/arch/arch_x86.go b/pkg/sentry/arch/arch_x86.go index 7fc4c0473..dc458b37f 100644 --- a/pkg/sentry/arch/arch_x86.go +++ b/pkg/sentry/arch/arch_x86.go @@ -21,7 +21,7 @@ import ( "io" "syscall" - "gvisor.dev/gvisor/pkg/binary" + "gvisor.dev/gvisor/pkg/abi/linux" "gvisor.dev/gvisor/pkg/cpuid" "gvisor.dev/gvisor/pkg/log" rpb "gvisor.dev/gvisor/pkg/sentry/arch/registers_go_proto" @@ -30,6 +30,9 @@ import ( "gvisor.dev/gvisor/pkg/usermem" ) +// Registers represents the CPU registers for this architecture. +type Registers = linux.PtraceRegs + // System-related constants for x86. const ( // SyscallWidth is the width of syscall, sysenter, and int 80 insturctions. @@ -267,10 +270,12 @@ func (s *State) RegisterMap() (map[string]uintptr, error) { // PtraceGetRegs implements Context.PtraceGetRegs. func (s *State) PtraceGetRegs(dst io.Writer) (int, error) { - return dst.Write(binary.Marshal(nil, usermem.ByteOrder, s.ptraceGetRegs())) + regs := s.ptraceGetRegs() + n, err := regs.WriteTo(dst) + return int(n), err } -func (s *State) ptraceGetRegs() syscall.PtraceRegs { +func (s *State) ptraceGetRegs() Registers { regs := s.Regs // These may not be initialized. if regs.Cs == 0 || regs.Ss == 0 || regs.Eflags == 0 { @@ -306,16 +311,16 @@ func (s *State) ptraceGetRegs() syscall.PtraceRegs { return regs } -var ptraceRegsSize = int(binary.Size(syscall.PtraceRegs{})) +var registersSize = (*Registers)(nil).SizeBytes() // PtraceSetRegs implements Context.PtraceSetRegs. func (s *State) PtraceSetRegs(src io.Reader) (int, error) { - var regs syscall.PtraceRegs - buf := make([]byte, ptraceRegsSize) + var regs Registers + buf := make([]byte, registersSize) if _, err := io.ReadFull(src, buf); err != nil { return 0, err } - binary.Unmarshal(buf, usermem.ByteOrder, ®s) + regs.UnmarshalUnsafe(buf) // Truncate segment registers to 16 bits. regs.Cs = uint64(uint16(regs.Cs)) regs.Ds = uint64(uint16(regs.Ds)) @@ -369,7 +374,7 @@ func (s *State) PtraceSetRegs(src io.Reader) (int, error) { } regs.Eflags = (s.Regs.Eflags &^ eflagsPtraceMutable) | (regs.Eflags & eflagsPtraceMutable) s.Regs = regs - return ptraceRegsSize, nil + return registersSize, nil } // isUserSegmentSelector returns true if the given segment selector specifies a @@ -538,7 +543,7 @@ const ( func (s *State) PtraceGetRegSet(regset uintptr, dst io.Writer, maxlen int) (int, error) { switch regset { case _NT_PRSTATUS: - if maxlen < ptraceRegsSize { + if maxlen < registersSize { return 0, syserror.EFAULT } return s.PtraceGetRegs(dst) @@ -558,7 +563,7 @@ func (s *State) PtraceGetRegSet(regset uintptr, dst io.Writer, maxlen int) (int, func (s *State) PtraceSetRegSet(regset uintptr, src io.Reader, maxlen int) (int, error) { switch regset { case _NT_PRSTATUS: - if maxlen < ptraceRegsSize { + if maxlen < registersSize { return 0, syserror.EFAULT } return s.PtraceSetRegs(src) diff --git a/pkg/sentry/arch/arch_x86_impl.go b/pkg/sentry/arch/arch_x86_impl.go index 3edf40764..0c73fcbfb 100644 --- a/pkg/sentry/arch/arch_x86_impl.go +++ b/pkg/sentry/arch/arch_x86_impl.go @@ -17,8 +17,6 @@ package arch import ( - "syscall" - "gvisor.dev/gvisor/pkg/cpuid" ) @@ -28,7 +26,7 @@ import ( // +stateify savable type State struct { // The system registers. - Regs syscall.PtraceRegs `state:".(syscallPtraceRegs)"` + Regs Registers // Our floating point state. x86FPState `state:"wait"` diff --git a/pkg/sentry/arch/signal.go b/pkg/sentry/arch/signal.go index 8b03d0187..c9fb55d00 100644 --- a/pkg/sentry/arch/signal.go +++ b/pkg/sentry/arch/signal.go @@ -22,6 +22,7 @@ import ( // SignalAct represents the action that should be taken when a signal is // delivered, and is equivalent to struct sigaction. // +// +marshal // +stateify savable type SignalAct struct { Handler uint64 @@ -43,6 +44,7 @@ func (s *SignalAct) DeserializeTo(other *SignalAct) { // SignalStack represents information about a user stack, and is equivalent to // stack_t. // +// +marshal // +stateify savable type SignalStack struct { Addr uint64 @@ -64,6 +66,7 @@ func (s *SignalStack) DeserializeTo(other *SignalStack) { // SignalInfo represents information about a signal being delivered, and is // equivalent to struct siginfo in linux kernel(linux/include/uapi/asm-generic/siginfo.h). // +// +marshal // +stateify savable type SignalInfo struct { Signo int32 // Signal number diff --git a/pkg/sentry/arch/signal_act.go b/pkg/sentry/arch/signal_act.go index f9ca2e74e..32173aa20 100644 --- a/pkg/sentry/arch/signal_act.go +++ b/pkg/sentry/arch/signal_act.go @@ -14,6 +14,8 @@ package arch +import "gvisor.dev/gvisor/tools/go_marshal/marshal" + // Special values for SignalAct.Handler. const ( // SignalActDefault is SIG_DFL and specifies that the default behavior for @@ -71,6 +73,8 @@ func (s SignalAct) HasRestorer() bool { // NativeSignalAct is a type that is equivalent to struct sigaction in the // guest architecture. type NativeSignalAct interface { + marshal.Marshallable + // SerializeFrom copies the data in the host SignalAct s into this object. SerializeFrom(s *SignalAct) diff --git a/pkg/sentry/arch/signal_stack.go b/pkg/sentry/arch/signal_stack.go index e58f055c7..0fa738a1d 100644 --- a/pkg/sentry/arch/signal_stack.go +++ b/pkg/sentry/arch/signal_stack.go @@ -18,6 +18,7 @@ package arch import ( "gvisor.dev/gvisor/pkg/usermem" + "gvisor.dev/gvisor/tools/go_marshal/marshal" ) const ( @@ -55,6 +56,8 @@ func (s *SignalStack) Contains(sp usermem.Addr) bool { // NativeSignalStack is a type that is equivalent to stack_t in the guest // architecture. type NativeSignalStack interface { + marshal.Marshallable + // SerializeFrom copies the data in the host SignalStack s into this // object. SerializeFrom(s *SignalStack) -- cgit v1.2.3