1818package fpu
1919
2020import (
21+ "errors"
2122 "fmt"
2223 "io"
2324
@@ -60,12 +61,37 @@ const (
6061const (
6162 // XFEATURE_MASK_FPSSE is xsave features that are always enabled in
6263 // signal frame fpstate.
63- XFEATURE_MASK_FPSSE = 0x3
64+ XFEATURE_MASK_FPSSE = cpuid.XSAVEFeatureX87 | cpuid.XSAVEFeatureSSE
6465
6566 // FXSAVE_AREA_SIZE is the size of the FXSAVE area.
6667 FXSAVE_AREA_SIZE = 512
6768)
6869
70+ // LINT.IfChange
71+ const (
72+ // SupportedXFeatureStates contains all xfeatures supported right now.
73+ //
74+ // TODO(gvisor.dev/issues/9896): Implement AMX support.
75+ // TODO(gvisor.dev/issues/10087): Implement PKRU support.
76+ SupportedXFeatureStates = cpuid.XSAVEFeatureX87 |
77+ cpuid.XSAVEFeatureSSE |
78+ cpuid.XSAVEFeatureAVX |
79+ cpuid.XSAVEFeatureAVX512op |
80+ cpuid.XSAVEFeatureAVX512zmm0 |
81+ cpuid.XSAVEFeatureAVX512zmm16
82+
83+ // ignoredXFeatureStates contains those xfeatures that may be
84+ // present in a buffer but are safe to skip during restore.
85+ //
86+ // Intel MPX deprecated in the Linux kernel.
87+ // PKRU states could be leaked. This issue was fixed in the 6.6 kernel.
88+ ignoredXFeatureStates = cpuid.XSAVEFeatureBNDREGS |
89+ cpuid.XSAVEFeatureBNDCSR |
90+ cpuid.XSAVEFeaturePKRU
91+ )
92+
93+ // LINT.ThenChange(../../platform/systrap/sysmsg/sysmsg_offsets.h)
94+
6995// initX86FPState (defined in asm files) sets up initial state.
7096func initX86FPState(data *byte, useXsave bool)
7197
@@ -261,8 +287,13 @@ func (s *State) PtraceSetXstateRegs(src io.Reader, maxlen int, featureSet cpuid.
261287 return n, nil
262288}
263289
290+ // ErrUnsupportedStateCleared is reported if an userspace state contains any
291+ // unsupported features.
292+ var ErrUnsupportedStateCleared = errors.New("contains unsupported states")
293+
264294// SanitizeUser mutates s to ensure that restoring it is safe.
265- func (s *State) SanitizeUser(featureSet cpuid.FeatureSet) {
295+ func (s *State) SanitizeUser(featureSet cpuid.FeatureSet) error {
296+ var err error
266297 f := *s
267298
268299 // Force reserved bits in MXCSR to 0. This is consistent with Linux.
@@ -271,12 +302,17 @@ func (s *State) SanitizeUser(featureSet cpuid.FeatureSet) {
271302 if len(f) >= minXstateBytes {
272303 // Users can't enable *more* XCR0 bits than what we, and the CPU, support.
273304 xstateBV := hostarch.ByteOrder.Uint64(f[xstateBVOffset:])
274- xstateBV &= featureSet.ValidXCR0Mask()
305+ xcr0Mask := featureSet.ValidXCR0Mask() & (SupportedXFeatureStates | ignoredXFeatureStates)
306+ if xstateBV&xcr0Mask != xstateBV {
307+ err = ErrUnsupportedStateCleared
308+ }
309+ xstateBV &= featureSet.ValidXCR0Mask() & SupportedXFeatureStates
275310 hostarch.ByteOrder.PutUint64(f[xstateBVOffset:], xstateBV)
276311 // Force XCOMP_BV and reserved bytes in the XSAVE header to 0.
277312 reserved := f[xsaveHeaderZeroedOffset : xsaveHeaderZeroedOffset+xsaveHeaderZeroedBytes]
278313 clear(reserved)
279314 }
315+ return err
280316}
281317
282318var (
@@ -357,7 +393,7 @@ func (s *State) AfterLoad() {
357393 supportedBV := fxsaveBV
358394 hostFeatureSet := cpuid.HostFeatureSet()
359395 if hostFeatureSet.UseXsave() {
360- supportedBV = hostFeatureSet.ValidXCR0Mask()
396+ supportedBV = hostFeatureSet.ValidXCR0Mask() & SupportedXFeatureStates
361397 }
362398
363399 // What was in use?
@@ -367,7 +403,7 @@ func (s *State) AfterLoad() {
367403 }
368404
369405 // Supported features must be a superset of saved features.
370- if savedBV&^supportedBV != 0 {
406+ if savedBV&^( supportedBV|ignoredXFeatureStates) != 0 {
371407 panic(ErrLoadingState{supportedFeatures: supportedBV, savedFeatures: savedBV})
372408 }
373409
0 commit comments