From 21981a2bdab3f768dedb0508561c145175b9095c Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Tue, 19 Jul 2022 18:09:53 -0700 Subject: [PATCH] kernel: don't allocate extra buffer to copy fpu state from user-memory We don't care about corrupting the current state, because sigreturn syscalls never report errors and they queue SIGSEGV in case of any problems. Here are results fro the signal_benchmark on the kvm platform: Before: BM_FaultSignalFixup/real_time 6127 ns 6087 ns 111708 After: BM_FaultSignalFixup/real_time 3661 ns 3654 ns 199755 PiperOrigin-RevId: 462021118 --- pkg/sentry/arch/signal_amd64.go | 6 ++---- pkg/sentry/kernel/task_signals.go | 4 ++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/sentry/arch/signal_amd64.go b/pkg/sentry/arch/signal_amd64.go index 9f5b398a2..b47faf6d9 100644 --- a/pkg/sentry/arch/signal_amd64.go +++ b/pkg/sentry/arch/signal_amd64.go @@ -304,12 +304,10 @@ func (c *Context64) SignalRestore(st *Stack, rt bool, featureSet cpuid.FeatureSe if uc.MContext.Fpstate == 0 { c.fpState.Reset() } else { - fpSize, _ := featureSet.ExtendedStateSize() - f := make([]byte, fpSize) - if _, err := st.IO.CopyIn(context.Background(), hostarch.Addr(uc.MContext.Fpstate), f, usermem.IOOpts{}); err != nil { + if _, err := st.IO.CopyIn(context.Background(), hostarch.Addr(uc.MContext.Fpstate), c.fpState, usermem.IOOpts{}); err != nil { + c.fpState.Reset() return 0, linux.SignalStack{}, err } - copy(c.fpState, f) c.fpState.SanitizeUser(featureSet) } diff --git a/pkg/sentry/kernel/task_signals.go b/pkg/sentry/kernel/task_signals.go index 33c000ac5..d63c9e98c 100644 --- a/pkg/sentry/kernel/task_signals.go +++ b/pkg/sentry/kernel/task_signals.go @@ -305,6 +305,10 @@ func (t *Task) SignalReturn(rt bool) (*SyscallControl, error) { st := t.Stack() sigset, alt, err := t.Arch().SignalRestore(st, rt, t.k.featureSet) if err != nil { + // sigreturn syscalls never return errors. + t.Debugf("failed to restore from a signal frame: %v", err) + t.forceSignal(linux.SIGSEGV, false /* unconditional */) + t.SendSignal(SignalInfoPriv(linux.SIGSEGV)) return nil, err }