Allow to return an error from PullFullState.

PiperOrigin-RevId: 504415294
This commit is contained in:
Andrei Vagin
2023-01-24 17:15:17 -08:00
committed by gVisor bot
parent 8604e1c200
commit aeabb78527
7 changed files with 49 additions and 27 deletions
+6 -1
View File
@@ -65,7 +65,12 @@ func (t *Task) Clone(args *linux.CloneArgs) (ThreadID, *SyscallControl, error) {
// Pull task registers and FPU state, a cloned task will inherit the
// state of the current task.
t.p.PullFullState(t.MemoryManager().AddressSpace(), t.Arch())
if err := t.p.PullFullState(t.MemoryManager().AddressSpace(), t.Arch()); err != nil {
t.Warningf("Unable to pull a full state: %v", err)
t.forceSignal(linux.SIGILL, true /* unconditional */)
t.SendSignal(SignalInfoPriv(linux.SIGILL))
return 0, nil, linuxerr.EFAULT
}
// "If CLONE_NEWUSER is specified along with other CLONE_NEW* flags in a
// single clone(2) or unshare(2) call, the user namespace is guaranteed to
+4 -1
View File
@@ -247,7 +247,10 @@ func (app *runApp) execute(t *Task) taskRunState {
t.Arch().ClearSingleStep()
}
if t.hasTracer() {
t.p.PullFullState(t.MemoryManager().AddressSpace(), t.Arch())
if e := t.p.PullFullState(t.MemoryManager().AddressSpace(), t.Arch()); e != nil {
t.Warningf("Unable to pull a full state: %v", e)
err = e
}
}
switch err {
+34 -2
View File
@@ -644,8 +644,9 @@ func (t *Task) SetSavedSignalMask(mask linux.SignalSet) {
}
// SignalStack returns the task-private signal stack.
//
// By precondition, a full state has to be pulled.
func (t *Task) SignalStack() linux.SignalStack {
t.p.PullFullState(t.MemoryManager().AddressSpace(), t.Arch())
alt := t.signalStack
if t.onSignalStack(alt) {
alt.Flags |= linux.SS_ONSTACK
@@ -653,6 +654,34 @@ func (t *Task) SignalStack() linux.SignalStack {
return alt
}
// SigaltStack implements the sigaltstack syscall.
func (t *Task) SigaltStack(setaddr hostarch.Addr, oldaddr hostarch.Addr) (*SyscallControl, error) {
if err := t.p.PullFullState(t.MemoryManager().AddressSpace(), t.Arch()); err != nil {
t.PrepareGroupExit(linux.WaitStatusTerminationSignal(linux.SIGILL))
return CtrlDoExit, linuxerr.EFAULT
}
alt := t.SignalStack()
if oldaddr != 0 {
if _, err := alt.CopyOut(t, oldaddr); err != nil {
return nil, err
}
}
if setaddr != 0 {
if _, err := alt.CopyIn(t, setaddr); err != nil {
return nil, err
}
// The signal stack cannot be changed if the task is currently
// on the stack. This is enforced at the lowest level because
// these semantics apply to changing the signal stack via a
// ucontext during a signal handler.
if !t.SetSignalStack(alt) {
return nil, linuxerr.EPERM
}
}
return nil, nil
}
// onSignalStack returns true if the task is executing on the given signal stack.
func (t *Task) onSignalStack(alt linux.SignalStack) bool {
sp := hostarch.Addr(t.Arch().Stack())
@@ -1018,7 +1047,10 @@ func (*runInterrupt) execute(t *Task) taskRunState {
// Are there signals pending?
if info := t.dequeueSignalLocked(linux.SignalSet(t.signalMask.RacyLoad())); info != nil {
t.p.PullFullState(t.MemoryManager().AddressSpace(), t.Arch())
if err := t.p.PullFullState(t.MemoryManager().AddressSpace(), t.Arch()); err != nil {
t.PrepareGroupExit(linux.WaitStatusTerminationSignal(linux.SIGILL))
return (*runExit)(nil)
}
if linux.SignalSetOf(linux.Signal(info.Signo))&StopSignals != 0 {
// Indicate that we've dequeued a stop signal before unlocking the
+1 -1
View File
@@ -125,7 +125,7 @@ func (c *context) Release() {}
func (c *context) FullStateChanged() {}
// PullFullState implements platform.Context.PullFullState.
func (c *context) PullFullState(as platform.AddressSpace, ac *arch.Context64) {}
func (c *context) PullFullState(as platform.AddressSpace, ac *arch.Context64) error { return nil }
// PrepareSleep implements platform.Context.platform.Context.
func (*context) PrepareSleep() {}
+1 -1
View File
@@ -221,7 +221,7 @@ type Context interface {
// PullFullState() to load all registers and FPU state.
//
// Preconditions: The caller must be running on the task goroutine.
PullFullState(as AddressSpace, ac *arch.Context64)
PullFullState(as AddressSpace, ac *arch.Context64) error
// FullStateChanged() indicates that a thread state has been changed by
// the Sentry. This happens in case of the rt_sigreturn, execve, etc.
+1 -1
View File
@@ -197,7 +197,7 @@ func (c *context) Release() {}
func (c *context) FullStateChanged() {}
// PullFullState implements platform.Context.PullFullState.
func (c *context) PullFullState(as platform.AddressSpace, ac *arch.Context64) {}
func (c *context) PullFullState(as platform.AddressSpace, ac *arch.Context64) error { return nil }
// PrepareSleep implements platform.Context.platform.PrepareSleep.
func (*context) PrepareSleep() {}
+2 -20
View File
@@ -323,26 +323,8 @@ func Sigaltstack(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.S
setaddr := args[0].Pointer()
oldaddr := args[1].Pointer()
alt := t.SignalStack()
if oldaddr != 0 {
if _, err := alt.CopyOut(t, oldaddr); err != nil {
return 0, nil, err
}
}
if setaddr != 0 {
if _, err := alt.CopyIn(t, setaddr); err != nil {
return 0, nil, err
}
// The signal stack cannot be changed if the task is currently
// on the stack. This is enforced at the lowest level because
// these semantics apply to changing the signal stack via a
// ucontext during a signal handler.
if !t.SetSignalStack(alt) {
return 0, nil, linuxerr.EPERM
}
}
return 0, nil, nil
ctrl, err := t.SigaltStack(setaddr, oldaddr)
return 0, ctrl, err
}
// Pause implements linux syscall pause(2).