[op] Move SignalStack to abi/linux package.

Updates #214

PiperOrigin-RevId: 378594929
This commit is contained in:
Ayush Ranjan
2021-06-10 01:00:24 -07:00
committed by gVisor bot
parent 8d87a9418a
commit a51fcf22eb
13 changed files with 62 additions and 156 deletions
+1
View File
@@ -79,6 +79,7 @@ go_library(
"//pkg/abi",
"//pkg/bits",
"//pkg/context",
"//pkg/hostarch",
"//pkg/marshal",
"//pkg/marshal/primitive",
],
+35 -1
View File
@@ -16,6 +16,7 @@ package linux
import (
"gvisor.dev/gvisor/pkg/bits"
"gvisor.dev/gvisor/pkg/hostarch"
)
const (
@@ -165,7 +166,7 @@ const (
SIG_IGN = 1
)
// Signal action flags for rt_sigaction(2), from uapi/asm-generic/signal.h
// Signal action flags for rt_sigaction(2), from uapi/asm-generic/signal.h.
const (
SA_NOCLDSTOP = 0x00000001
SA_NOCLDWAIT = 0x00000002
@@ -179,6 +180,12 @@ const (
SA_ONESHOT = SA_RESETHAND
)
// Signal stack flags for signalstack(2), from include/uapi/linux/signal.h.
const (
SS_ONSTACK = 1
SS_DISABLE = 2
)
// Signal info types.
const (
SI_MASK = 0xffff0000
@@ -242,6 +249,33 @@ type SigAction struct {
// LINT.ThenChange(../../safecopy/safecopy_unsafe.go)
// SignalStack represents information about a user stack, and is equivalent to
// stack_t.
//
// +marshal
// +stateify savable
type SignalStack struct {
Addr uint64
Flags uint32
_ uint32
Size uint64
}
// Contains checks if the stack pointer is within this stack.
func (s *SignalStack) Contains(sp hostarch.Addr) bool {
return hostarch.Addr(s.Addr) < sp && sp <= hostarch.Addr(s.Addr+s.Size)
}
// Top returns the stack's top address.
func (s *SignalStack) Top() hostarch.Addr {
return hostarch.Addr(s.Addr + s.Size)
}
// IsEnabled returns true iff this signal stack is marked as enabled.
func (s *SignalStack) IsEnabled() bool {
return s.Flags&SS_DISABLE == 0
}
// Possible values for Sigevent.Notify, aka struct sigevent::sigev_notify.
const (
SIGEV_SIGNAL = 0
-1
View File
@@ -18,7 +18,6 @@ go_library(
"signal_amd64.go",
"signal_arm64.go",
"signal_info.go",
"signal_stack.go",
"stack.go",
"stack_unsafe.go",
"syscalls_amd64.go",
+2 -6
View File
@@ -134,10 +134,6 @@ type Context interface {
// RegisterMap returns a map of all registers.
RegisterMap() (map[string]uintptr, error)
// NewSignalStack returns a new object that is equivalent to stack_t in the
// guest architecture.
NewSignalStack() NativeSignalStack
// SignalSetup modifies the context in preparation for handling the
// given signal.
//
@@ -153,7 +149,7 @@ type Context interface {
// stack is not going to be used).
//
// sigset is the signal mask before entering the signal handler.
SignalSetup(st *Stack, act *linux.SigAction, info *SignalInfo, alt *SignalStack, sigset linux.SignalSet) error
SignalSetup(st *Stack, act *linux.SigAction, info *SignalInfo, alt *linux.SignalStack, sigset linux.SignalSet) error
// SignalRestore restores context after returning from a signal
// handler.
@@ -163,7 +159,7 @@ type Context interface {
// rt is true if SignalRestore is being entered from rt_sigreturn and
// false if SignalRestore is being entered from sigreturn.
// SignalRestore returns the thread's new signal mask.
SignalRestore(st *Stack, rt bool) (linux.SignalSet, SignalStack, error)
SignalRestore(st *Stack, rt bool) (linux.SignalSet, linux.SignalStack, error)
// CPUIDEmulate emulates a CPUID instruction according to current register state.
CPUIDEmulate(l log.Logger)
-22
View File
@@ -19,28 +19,6 @@ import (
"gvisor.dev/gvisor/pkg/hostarch"
)
// SignalStack represents information about a user stack, and is equivalent to
// stack_t.
//
// +marshal
// +stateify savable
type SignalStack struct {
Addr uint64
Flags uint32
_ uint32
Size uint64
}
// SerializeFrom implements NativeSignalStack.SerializeFrom.
func (s *SignalStack) SerializeFrom(other *SignalStack) {
*s = *other
}
// DeserializeTo implements NativeSignalStack.DeserializeTo.
func (s *SignalStack) DeserializeTo(other *SignalStack) {
*other = *s
}
// SignalInfo represents information about a signal being delivered, and is
// equivalent to struct siginfo in linux kernel(linux/include/uapi/asm-generic/siginfo.h).
//
+5 -10
View File
@@ -76,16 +76,11 @@ const (
type UContext64 struct {
Flags uint64
Link uint64
Stack SignalStack
Stack linux.SignalStack
MContext SignalContext64
Sigset linux.SignalSet
}
// NewSignalStack implements Context.NewSignalStack.
func (c *context64) NewSignalStack() NativeSignalStack {
return &SignalStack{}
}
// From Linux 'arch/x86/include/uapi/asm/sigcontext.h' the following is the
// size of the magic cookie at the end of the xsave frame.
//
@@ -105,7 +100,7 @@ func (c *context64) fpuFrameSize() (size int, useXsave bool) {
// SignalSetup implements Context.SignalSetup. (Compare to Linux's
// arch/x86/kernel/signal.c:__setup_rt_frame().)
func (c *context64) SignalSetup(st *Stack, act *linux.SigAction, info *SignalInfo, alt *SignalStack, sigset linux.SignalSet) error {
func (c *context64) SignalSetup(st *Stack, act *linux.SigAction, info *SignalInfo, alt *linux.SignalStack, sigset linux.SignalSet) error {
sp := st.Bottom
// "The 128-byte area beyond the location pointed to by %rsp is considered
@@ -232,15 +227,15 @@ func (c *context64) SignalSetup(st *Stack, act *linux.SigAction, info *SignalInf
// SignalRestore implements Context.SignalRestore. (Compare to Linux's
// arch/x86/kernel/signal.c:sys_rt_sigreturn().)
func (c *context64) SignalRestore(st *Stack, rt bool) (linux.SignalSet, SignalStack, error) {
func (c *context64) SignalRestore(st *Stack, rt bool) (linux.SignalSet, linux.SignalStack, error) {
// Copy out the stack frame.
var uc UContext64
if _, err := uc.CopyIn(st, StackBottomMagic); err != nil {
return 0, SignalStack{}, err
return 0, linux.SignalStack{}, err
}
var info SignalInfo
if _, err := info.CopyIn(st, StackBottomMagic); err != nil {
return 0, SignalStack{}, err
return 0, linux.SignalStack{}, err
}
// Restore registers.
+5 -10
View File
@@ -61,7 +61,7 @@ type FpsimdContext struct {
type UContext64 struct {
Flags uint64
Link uint64
Stack SignalStack
Stack linux.SignalStack
Sigset linux.SignalSet
// glibc uses a 1024-bit sigset_t
_pad [120]byte // (1024 - 64) / 8 = 120
@@ -71,13 +71,8 @@ type UContext64 struct {
MContext SignalContext64
}
// NewSignalStack implements Context.NewSignalStack.
func (c *context64) NewSignalStack() NativeSignalStack {
return &SignalStack{}
}
// SignalSetup implements Context.SignalSetup.
func (c *context64) SignalSetup(st *Stack, act *linux.SigAction, info *SignalInfo, alt *SignalStack, sigset linux.SignalSet) error {
func (c *context64) SignalSetup(st *Stack, act *linux.SigAction, info *SignalInfo, alt *linux.SignalStack, sigset linux.SignalSet) error {
sp := st.Bottom
// Construct the UContext64 now since we need its size.
@@ -142,15 +137,15 @@ func (c *context64) SignalSetup(st *Stack, act *linux.SigAction, info *SignalInf
}
// SignalRestore implements Context.SignalRestore.
func (c *context64) SignalRestore(st *Stack, rt bool) (linux.SignalSet, SignalStack, error) {
func (c *context64) SignalRestore(st *Stack, rt bool) (linux.SignalSet, linux.SignalStack, error) {
// Copy out the stack frame.
var uc UContext64
if _, err := uc.CopyIn(st, StackBottomMagic); err != nil {
return 0, SignalStack{}, err
return 0, linux.SignalStack{}, err
}
var info SignalInfo
if _, err := info.CopyIn(st, StackBottomMagic); err != nil {
return 0, SignalStack{}, err
return 0, linux.SignalStack{}, err
}
// Restore registers.
-68
View File
@@ -1,68 +0,0 @@
// Copyright 2018 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 386 amd64 arm64
package arch
import (
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
)
const (
// SignalStackFlagOnStack is possible set on return from getaltstack,
// in order to indicate that the thread is currently on the alt stack.
SignalStackFlagOnStack = 1
// SignalStackFlagDisable is a flag to indicate the stack is disabled.
SignalStackFlagDisable = 2
)
// IsEnabled returns true iff this signal stack is marked as enabled.
func (s SignalStack) IsEnabled() bool {
return s.Flags&SignalStackFlagDisable == 0
}
// Top returns the stack's top address.
func (s SignalStack) Top() hostarch.Addr {
return hostarch.Addr(s.Addr + s.Size)
}
// SetOnStack marks this signal stack as in use.
//
// Note that there is no corresponding ClearOnStack, and that this should only
// be called on copies that are serialized to userspace.
func (s *SignalStack) SetOnStack() {
s.Flags |= SignalStackFlagOnStack
}
// Contains checks if the stack pointer is within this stack.
func (s *SignalStack) Contains(sp hostarch.Addr) bool {
return hostarch.Addr(s.Addr) < sp && sp <= hostarch.Addr(s.Addr+s.Size)
}
// 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)
// DeserializeTo copies the data in this object into the host SignalStack
// s.
DeserializeTo(s *SignalStack)
}
+1 -1
View File
@@ -151,7 +151,7 @@ type Task struct {
// which the SA_ONSTACK flag is set.
//
// signalStack is exclusive to the task goroutine.
signalStack arch.SignalStack
signalStack linux.SignalStack
// signalQueue is a set of registered waiters for signal-related events.
//
+1 -2
View File
@@ -66,7 +66,6 @@ package kernel
import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/fs"
"gvisor.dev/gvisor/pkg/sentry/mm"
"gvisor.dev/gvisor/pkg/sentry/vfs"
@@ -181,7 +180,7 @@ func (r *runSyscallAfterExecStop) execute(t *Task) taskRunState {
t.tg.signalHandlers = t.tg.signalHandlers.CopyForExec()
t.endStopCond.L = &t.tg.signalHandlers.mu
// "Any alternate signal stack is not preserved (sigaltstack(2))." - execve(2)
t.signalStack = arch.SignalStack{Flags: arch.SignalStackFlagDisable}
t.signalStack = linux.SignalStack{Flags: linux.SS_DISABLE}
// "The termination signal is reset to SIGCHLD (see clone(2))."
t.tg.terminationSignal = linux.SIGCHLD
// execed indicates that the process can no longer join a process group
+9 -30
View File
@@ -249,7 +249,7 @@ func (t *Task) deliverSignalToHandler(info *arch.SignalInfo, act linux.SigAction
// handler expects to see in its ucontext (even if it's not in use).
alt := t.signalStack
if act.Flags&linux.SA_ONSTACK != 0 && alt.IsEnabled() {
alt.SetOnStack()
alt.Flags |= linux.SS_ONSTACK
if !alt.Contains(sp) {
sp = hostarch.Addr(alt.Top())
}
@@ -641,17 +641,17 @@ func (t *Task) SetSavedSignalMask(mask linux.SignalSet) {
}
// SignalStack returns the task-private signal stack.
func (t *Task) SignalStack() arch.SignalStack {
func (t *Task) SignalStack() linux.SignalStack {
t.p.PullFullState(t.MemoryManager().AddressSpace(), t.Arch())
alt := t.signalStack
if t.onSignalStack(alt) {
alt.Flags |= arch.SignalStackFlagOnStack
alt.Flags |= linux.SS_ONSTACK
}
return alt
}
// onSignalStack returns true if the task is executing on the given signal stack.
func (t *Task) onSignalStack(alt arch.SignalStack) bool {
func (t *Task) onSignalStack(alt linux.SignalStack) bool {
sp := hostarch.Addr(t.Arch().Stack())
return alt.Contains(sp)
}
@@ -661,20 +661,20 @@ func (t *Task) onSignalStack(alt arch.SignalStack) bool {
// This value may not be changed if the task is currently executing on the
// signal stack, i.e. if t.onSignalStack returns true. In this case, this
// function will return false. Otherwise, true is returned.
func (t *Task) SetSignalStack(alt arch.SignalStack) bool {
func (t *Task) SetSignalStack(alt linux.SignalStack) bool {
// Check that we're not executing on the stack.
if t.onSignalStack(t.signalStack) {
return false
}
if alt.Flags&arch.SignalStackFlagDisable != 0 {
if alt.Flags&linux.SS_DISABLE != 0 {
// Don't record anything beyond the flags.
t.signalStack = arch.SignalStack{
Flags: arch.SignalStackFlagDisable,
t.signalStack = linux.SignalStack{
Flags: linux.SS_DISABLE,
}
} else {
// Mask out irrelevant parts: only disable matters.
alt.Flags &= arch.SignalStackFlagDisable
alt.Flags &= linux.SS_DISABLE
t.signalStack = alt
}
return true
@@ -718,27 +718,6 @@ func (tg *ThreadGroup) SetSigAction(sig linux.Signal, actptr *linux.SigAction) (
return oldact, nil
}
// CopyOutSignalStack converts the given SignalStack into an
// architecture-specific type and then copies it out to task memory.
func (t *Task) CopyOutSignalStack(addr hostarch.Addr, s *arch.SignalStack) error {
n := t.Arch().NewSignalStack()
n.SerializeFrom(s)
_, err := n.CopyOut(t, addr)
return err
}
// CopyInSignalStack copies an architecture-specific stack_t from task memory
// and then converts it into a SignalStack.
func (t *Task) CopyInSignalStack(addr hostarch.Addr) (arch.SignalStack, error) {
n := t.Arch().NewSignalStack()
var s arch.SignalStack
if _, err := n.CopyIn(t, addr); err != nil {
return s, err
}
n.DeserializeTo(&s)
return s, nil
}
// groupStop is a TaskStop placed on tasks that have received a stop signal
// (SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU). (The term "group-stop" originates from
// the ptrace man page.)
+1 -2
View File
@@ -18,7 +18,6 @@ import (
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/inet"
"gvisor.dev/gvisor/pkg/sentry/kernel/auth"
"gvisor.dev/gvisor/pkg/sentry/kernel/futex"
@@ -131,7 +130,7 @@ func (ts *TaskSet) newTask(cfg *TaskConfig) (*Task, error) {
runState: (*runApp)(nil),
interruptChan: make(chan struct{}, 1),
signalMask: cfg.SignalMask,
signalStack: arch.SignalStack{Flags: arch.SignalStackFlagDisable},
signalStack: linux.SignalStack{Flags: linux.SS_DISABLE},
image: *image,
fsContext: cfg.FSContext,
fdTable: cfg.FDTable,
+2 -3
View File
@@ -325,13 +325,12 @@ func Sigaltstack(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
alt := t.SignalStack()
if oldaddr != 0 {
if err := t.CopyOutSignalStack(oldaddr, &alt); err != nil {
if _, err := alt.CopyOut(t, oldaddr); err != nil {
return 0, nil, err
}
}
if setaddr != 0 {
alt, err := t.CopyInSignalStack(setaddr)
if err != nil {
if _, err := alt.CopyIn(t, setaddr); err != nil {
return 0, nil, err
}
// The signal stack cannot be changed if the task is currently