mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
[op] Move SignalStack to abi/linux package.
Updates #214 PiperOrigin-RevId: 378594929
This commit is contained in:
@@ -79,6 +79,7 @@ go_library(
|
||||
"//pkg/abi",
|
||||
"//pkg/bits",
|
||||
"//pkg/context",
|
||||
"//pkg/hostarch",
|
||||
"//pkg/marshal",
|
||||
"//pkg/marshal/primitive",
|
||||
],
|
||||
|
||||
+35
-1
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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).
|
||||
//
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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.
|
||||
//
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user