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