snapshot: sagernet/gvisor v0.0.0-20260727.0-sing-box-mod.1 + SPEC 048 guard

Обновление снапшота с v0.0.0-20250811.0 на пин, которого требует
sing-box после мержа 235 коммитов (upstream d620bbbf2 "Update gvisor to
20260727.0"). Прежний снапшот был взят 2026-08-04 ровно с той версии,
на которой тогда стоял апстрим; разрыв возник 2026-08-05 вместе с его
бампом.

За год апстрим-gvisor изменил ~14 000 строк в 292 файлах. Значимое для
нас — сетевой стек: tcp/connect.go (PMTU-discovery + исправление
начального RTT/RTO: раньше задержка ACK внутри стека завышала стартовый
таймаут на несколько RTT), tcp/snd.go, tcp/rcv.go, stack/conntrack.go,
stack/packet_buffer.go. Всего 30 файлов в TCP и 37 в stack.

Баг SPEC 048 апстрим НЕ исправил — проверено по коду новой версии:
handleConnecting по-прежнему проверяет состояние endpoint'а, но не ep.h,
а performHandshake так же зануляет h и отпускает мьютекс до Close().
Поэтому guard перенесён (12 строк) вместе со своим тестом (45 строк).

Red/green проверен на новой базе: без guard'а тест падает с той же
nil-паникой, что в полевом крашдампе; с ним зелёный.
This commit is contained in:
Leadaxe 2026-08-05 14:53:31 +03:00
parent ffebe42860
commit 117243aa02
293 changed files with 16413 additions and 2842 deletions

View file

@ -233,9 +233,10 @@ func readHWCap(auxvFilepath string) (hwCap, error) {
for i := 0; i < l; i++ {
tag := binary.LittleEndian.Uint64(auxv[i*16:])
val := binary.LittleEndian.Uint64(auxv[i*16+8:])
if tag == _AT_HWCAP {
switch tag {
case _AT_HWCAP:
c.hwCap1 = val
} else if tag == _AT_HWCAP2 {
case _AT_HWCAP2:
c.hwCap2 = val
}
@ -249,7 +250,7 @@ func readHWCap(auxvFilepath string) (hwCap, error) {
func initHWCap() {
c, err := readHWCap("/proc/self/auxv")
if err != nil {
log.Warningf("cpuid HWCap not initialized: %w", err)
log.Warningf("cpuid HWCap not initialized: %v", err)
} else {
hostFeatureSet.hwCap = c
}

View file

@ -192,7 +192,24 @@ func (fs FeatureSet) VirtualAddressBits() uint32 {
//go:nosplit
func (fs FeatureSet) PhysicalAddressBits() uint32 {
ax, _, _, _ := fs.query(addressSizes)
return ax & 0xff
physBits := ax & 0xff
if !fs.AMD() {
return physBits
}
maxExtended, _, _, _ := fs.query(extendedFunctionInfo)
if maxExtended < uint32(amdMemoryEncryptionInfo) {
return physBits
}
memEncAX, memEncBX, _, _ := fs.query(amdMemoryEncryptionInfo)
if memEncAX&amdMemoryEncryptionFeatureMask == 0 {
return physBits
}
// AMD memory encryption reduces usable physical address width by the
// CPUID-reported amount. Match Linux's
// arch/x86/kernel/cpu/amd.c:early_detect_mem_encrypt().
return physBits - ((memEncBX >> amdPhysAddrReductionShift) & amdPhysAddrReductionMask)
}
// CacheType describes the type of a cache, as returned in eax[4:0] for eax=4.
@ -382,15 +399,16 @@ var (
)
const (
// XCR0AMXMask are the bits that enable xsave to operate on AMX TILECFG
// and TILEDATA.
//
// Note: TILECFG and TILEDATA are always either both enabled or both
// disabled.
// XCR0AmxCfgMask is the bits that enable xsave to operate on
// AMX TILECFG.
//
// See Intel® 64 and IA-32 Architectures Software Developers Manual Vol.1
// section 13.3 for details.
XCR0AMXMask = uint64((1 << 17) | (1 << 18))
XCR0AmxCfgMask = uint64(1 << 17)
// XCR0AmxDataMask is the bits that enable xsave to operate on
// AMX TILEDATA.
XCR0AmxDataMask = uint64(1 << 18)
)
// ExtendedStateSize returns the number of bytes needed to save the "extended
@ -415,13 +433,15 @@ func (fs FeatureSet) ExtendedStateSize() (size, align uint) {
// AMXExtendedStateSize returns the number of bytes within the "extended state"
// area that is used for AMX.
func (fs FeatureSet) AMXExtendedStateSize() uint {
total := uint(0)
if fs.UseXsave() {
xcr0 := xgetbv(0)
if (xcr0 & XCR0AMXMask) != 0 {
return uint(amxTileCfgSize + amxTileDataSize)
// TILECFG is not part of AMX extended state, only TILEDATA.
if (xcr0 & XCR0AmxDataMask) != 0 {
total += uint(amxTileDataSize)
}
}
return 0
return total
}
// ValidXCR0Mask returns the valid bits in control register XCR0.
@ -435,7 +455,7 @@ func (fs FeatureSet) ValidXCR0Mask() uint64 {
return 0
}
ax, _, _, dx := fs.query(xSaveInfo)
return (uint64(dx)<<32 | uint64(ax)) &^ XCR0AMXMask
return (uint64(dx)<<32 | uint64(ax)) &^ (XCR0AmxCfgMask | XCR0AmxDataMask)
}
// UseXsave returns the choice of fp state saving instruction.

View file

@ -27,8 +27,8 @@ func (fs *FeatureSet) beforeSave() {}
// +checklocksignore
func (fs *FeatureSet) StateSave(stateSinkObject state.Sink) {
fs.beforeSave()
var FunctionValue Static
FunctionValue = fs.saveFunction()
FunctionValue := fs.saveFunction()
_ = (Static)(FunctionValue)
stateSinkObject.SaveValue(0, FunctionValue)
stateSinkObject.Save(1, &fs.hwCap)
}

View file

@ -63,15 +63,25 @@ const xSaveInfoNumLeaves = 64 // Maximum number of xSaveInfo leaves.
// The "extended" functions.
const (
extendedStart cpuidFunction = 0x80000000
extendedFunctionInfo cpuidFunction = extendedStart + 0 // Returns highest available extended function in eax.
extendedFeatures = extendedStart + 1 // Returns some extended feature bits in edx and ecx.
processorBrandString2 = extendedStart + 2 // Processor Name String Identifier.
processorBrandString3 = extendedStart + 3 // Processor Name String Identifier.
processorBrandString4 = extendedStart + 4 // Processor Name String Identifier.
l1CacheAndTLBInfo = extendedStart + 5 // Returns L2 cache information.
l2CacheInfo = extendedStart + 6 // Returns L2 cache information.
addressSizes = extendedStart + 8 // Physical and virtual address sizes.
extendedStart cpuidFunction = 0x80000000
extendedFunctionInfo cpuidFunction = extendedStart + 0 // Returns highest available extended function in eax.
extendedFeatures = extendedStart + 1 // Returns some extended feature bits in edx and ecx.
processorBrandString2 = extendedStart + 2 // Processor Name String Identifier.
processorBrandString3 = extendedStart + 3 // Processor Name String Identifier.
processorBrandString4 = extendedStart + 4 // Processor Name String Identifier.
l1CacheAndTLBInfo = extendedStart + 5 // Returns L2 cache information.
l2CacheInfo = extendedStart + 6 // Returns L2 cache information.
addressSizes = extendedStart + 8 // Physical and virtual address sizes.
amdMemoryEncryptionInfo = extendedStart + 31 // AMD memory encryption information.
)
// AMD-defined memory encryption feature bits and fields.
const (
amdSecureMemoryEncryption = 1 << 0
amdSecureEncryptedVirtualization = 1 << 1
amdMemoryEncryptionFeatureMask = amdSecureMemoryEncryption | amdSecureEncryptedVirtualization
amdPhysAddrReductionShift = 6
amdPhysAddrReductionMask = 0x3f
)
var allowedBasicFunctions = [...]bool{
@ -84,14 +94,15 @@ var allowedBasicFunctions = [...]bool{
}
var allowedExtendedFunctions = [...]bool{
extendedFunctionInfo - extendedStart: true,
extendedFeatures - extendedStart: true,
addressSizes - extendedStart: true,
processorBrandString2 - extendedStart: true,
processorBrandString3 - extendedStart: true,
processorBrandString4 - extendedStart: true,
l1CacheAndTLBInfo - extendedStart: true,
l2CacheInfo - extendedStart: true,
extendedFunctionInfo - extendedStart: true,
extendedFeatures - extendedStart: true,
addressSizes - extendedStart: true,
processorBrandString2 - extendedStart: true,
processorBrandString3 - extendedStart: true,
processorBrandString4 - extendedStart: true,
l1CacheAndTLBInfo - extendedStart: true,
l2CacheInfo - extendedStart: true,
amdMemoryEncryptionInfo - extendedStart: true,
}
// Function executes a CPUID function.
@ -119,7 +130,7 @@ func (i *In) normalize() {
switch cpuidFunction(i.Eax) {
case vendorID, featureInfo, intelCacheDescriptors, extendedFunctionInfo, extendedFeatures:
i.Ecx = 0 // Ignore.
case processorBrandString2, processorBrandString3, processorBrandString4, l1CacheAndTLBInfo, l2CacheInfo:
case processorBrandString2, processorBrandString3, processorBrandString4, l1CacheAndTLBInfo, l2CacheInfo, amdMemoryEncryptionInfo:
i.Ecx = 0 // Ignore.
case intelDeterministicCacheParams, extendedFeatureInfo:
// Preserve i.Ecx.