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:
parent
ffebe42860
commit
117243aa02
293 changed files with 16413 additions and 2842 deletions
82
pkg/ebpf/ebpf.go
Normal file
82
pkg/ebpf/ebpf.go
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// Copyright 2026 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package ebpf provides tools for working with extended Berkely Packet Filter (eBPF) programs.
|
||||
//
|
||||
// gVisor currently does not support running eBPF programs.
|
||||
package ebpf
|
||||
|
||||
import (
|
||||
"github.com/sagernet/gvisor/pkg/abi/linux"
|
||||
)
|
||||
|
||||
// BPFID is a sequential, globally-unique (though unloaded
|
||||
// programs' IDs are reused) ID for an eBPF program.
|
||||
type BPFID uint32
|
||||
|
||||
// UnverifiedProgram represents an eBPF program provided by userspace that has not
|
||||
// been validated.
|
||||
//
|
||||
// +stateify savable
|
||||
type UnverifiedProgram struct {
|
||||
// instructions is a list of eBPF instructions.
|
||||
//
|
||||
// Immutable.
|
||||
instructions []linux.EBPFInstruction
|
||||
}
|
||||
|
||||
// NewUnverifiedProgram creates an unverified eBPF program from a set of instructions.
|
||||
func NewUnverifiedProgram(instructions []linux.EBPFInstruction) UnverifiedProgram {
|
||||
return UnverifiedProgram{
|
||||
instructions: instructions,
|
||||
}
|
||||
}
|
||||
|
||||
// Program represents an eBPF program that has been validated.
|
||||
//
|
||||
// All fields of Program are immutable.
|
||||
//
|
||||
// +stateify savable
|
||||
type Program struct {
|
||||
// instructions is a list of eBPF instructions.
|
||||
instructions []linux.EBPFInstruction
|
||||
|
||||
// id is the program's ID.
|
||||
id BPFID
|
||||
|
||||
// progType is the program's type.
|
||||
progType linux.BPFProgramType
|
||||
}
|
||||
|
||||
// ID returns the unique identifier for the eBPF program.
|
||||
func (p *Program) ID() BPFID {
|
||||
return p.id
|
||||
}
|
||||
|
||||
// ProgType returns the type of the eBPF program.
|
||||
func (p *Program) ProgType() linux.BPFProgramType {
|
||||
return p.progType
|
||||
}
|
||||
|
||||
// Validate validates an unverified eBPF program.
|
||||
//
|
||||
// Currently, no validation is performed, so the resulting program MUST not be run.
|
||||
func (uprog *UnverifiedProgram) Validate(id BPFID, progType linux.BPFProgramType) (Program, error) {
|
||||
prog := Program{
|
||||
instructions: uprog.instructions,
|
||||
id: id,
|
||||
progType: progType,
|
||||
}
|
||||
return prog, nil
|
||||
}
|
||||
70
pkg/ebpf/ebpf_state_autogen.go
Normal file
70
pkg/ebpf/ebpf_state_autogen.go
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// automatically generated by stateify.
|
||||
|
||||
package ebpf
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sagernet/gvisor/pkg/state"
|
||||
)
|
||||
|
||||
func (uprog *UnverifiedProgram) StateTypeName() string {
|
||||
return "pkg/ebpf.UnverifiedProgram"
|
||||
}
|
||||
|
||||
func (uprog *UnverifiedProgram) StateFields() []string {
|
||||
return []string{
|
||||
"instructions",
|
||||
}
|
||||
}
|
||||
|
||||
func (uprog *UnverifiedProgram) beforeSave() {}
|
||||
|
||||
// +checklocksignore
|
||||
func (uprog *UnverifiedProgram) StateSave(stateSinkObject state.Sink) {
|
||||
uprog.beforeSave()
|
||||
stateSinkObject.Save(0, &uprog.instructions)
|
||||
}
|
||||
|
||||
func (uprog *UnverifiedProgram) afterLoad(context.Context) {}
|
||||
|
||||
// +checklocksignore
|
||||
func (uprog *UnverifiedProgram) StateLoad(ctx context.Context, stateSourceObject state.Source) {
|
||||
stateSourceObject.Load(0, &uprog.instructions)
|
||||
}
|
||||
|
||||
func (p *Program) StateTypeName() string {
|
||||
return "pkg/ebpf.Program"
|
||||
}
|
||||
|
||||
func (p *Program) StateFields() []string {
|
||||
return []string{
|
||||
"instructions",
|
||||
"id",
|
||||
"progType",
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Program) beforeSave() {}
|
||||
|
||||
// +checklocksignore
|
||||
func (p *Program) StateSave(stateSinkObject state.Sink) {
|
||||
p.beforeSave()
|
||||
stateSinkObject.Save(0, &p.instructions)
|
||||
stateSinkObject.Save(1, &p.id)
|
||||
stateSinkObject.Save(2, &p.progType)
|
||||
}
|
||||
|
||||
func (p *Program) afterLoad(context.Context) {}
|
||||
|
||||
// +checklocksignore
|
||||
func (p *Program) StateLoad(ctx context.Context, stateSourceObject state.Source) {
|
||||
stateSourceObject.Load(0, &p.instructions)
|
||||
stateSourceObject.Load(1, &p.id)
|
||||
stateSourceObject.Load(2, &p.progType)
|
||||
}
|
||||
|
||||
func init() {
|
||||
state.Register((*UnverifiedProgram)(nil))
|
||||
state.Register((*Program)(nil))
|
||||
}
|
||||
155
pkg/ebpf/types.go
Normal file
155
pkg/ebpf/types.go
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
// Copyright 2026 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ebpf
|
||||
|
||||
import (
|
||||
"github.com/sagernet/gvisor/pkg/abi/linux"
|
||||
)
|
||||
|
||||
// CgroupAttachType is an attachment type that is valid for a cgroup eBPF program.
|
||||
type CgroupAttachType uint
|
||||
|
||||
// Subset of attachment types that are valid for cgroup eBPF programs.
|
||||
const (
|
||||
CGROUP_INET_INGRESS CgroupAttachType = iota
|
||||
CGROUP_INET_EGRESS
|
||||
CGROUP_INET_SOCK_CREATE
|
||||
CGROUP_SOCK_OPS
|
||||
CGROUP_DEVICE
|
||||
CGROUP_INET4_BIND
|
||||
CGROUP_INET6_BIND
|
||||
CGROUP_INET4_CONNECT
|
||||
CGROUP_INET6_CONNECT
|
||||
CGROUP_UNIX_CONNECT
|
||||
CGROUP_INET4_POST_BIND
|
||||
CGROUP_INET6_POST_BIND
|
||||
CGROUP_UDP4_SENDMSG
|
||||
CGROUP_UDP6_SENDMSG
|
||||
CGROUP_UNIX_SENDMSG
|
||||
CGROUP_SYSCTL
|
||||
CGROUP_UDP4_RECVMSG
|
||||
CGROUP_UDP6_RECVMSG
|
||||
CGROUP_UNIX_RECVMSG
|
||||
CGROUP_GETSOCKOPT
|
||||
CGROUP_SETSOCKOPT
|
||||
CGROUP_INET4_GETPEERNAME
|
||||
CGROUP_INET6_GETPEERNAME
|
||||
CGROUP_UNIX_GETPEERNAME
|
||||
CGROUP_INET4_GETSOCKNAME
|
||||
CGROUP_INET6_GETSOCKNAME
|
||||
CGROUP_UNIX_GETSOCKNAME
|
||||
CGROUP_INET_SOCK_RELEASE
|
||||
MAX_CGROUP_BPF_ATTACH_TYPE uint = iota
|
||||
)
|
||||
|
||||
// AttachType is an interface implemented by each subsystem's subset of valid
|
||||
// attachment types.
|
||||
type AttachType interface {
|
||||
// MatchingProgType returns the program type that expects to be attached
|
||||
// at this attachment type.
|
||||
//
|
||||
// Analogous to kernel/bpf/syscall.c:attach_type_to_prog_type() in Linux.
|
||||
MatchingProgType() linux.BPFProgramType
|
||||
}
|
||||
|
||||
// MatchingProgType implements AttachType.MatchingProgType.
|
||||
func (c CgroupAttachType) MatchingProgType() linux.BPFProgramType {
|
||||
switch c {
|
||||
case CGROUP_INET_INGRESS, CGROUP_INET_EGRESS:
|
||||
return linux.BPF_PROG_TYPE_CGROUP_SKB
|
||||
case CGROUP_INET_SOCK_CREATE, CGROUP_INET_SOCK_RELEASE, CGROUP_INET4_POST_BIND, CGROUP_INET6_POST_BIND:
|
||||
return linux.BPF_PROG_TYPE_CGROUP_SOCK
|
||||
case CGROUP_INET4_BIND, CGROUP_INET6_BIND, CGROUP_INET4_CONNECT, CGROUP_INET6_CONNECT, CGROUP_UNIX_CONNECT, CGROUP_INET4_GETPEERNAME, CGROUP_INET6_GETPEERNAME, CGROUP_UNIX_GETPEERNAME, CGROUP_INET4_GETSOCKNAME, CGROUP_INET6_GETSOCKNAME, CGROUP_UNIX_GETSOCKNAME, CGROUP_UDP4_SENDMSG, CGROUP_UDP6_SENDMSG, CGROUP_UNIX_SENDMSG, CGROUP_UDP4_RECVMSG, CGROUP_UDP6_RECVMSG, CGROUP_UNIX_RECVMSG:
|
||||
return linux.BPF_PROG_TYPE_CGROUP_SOCK_ADDR
|
||||
case CGROUP_SOCK_OPS:
|
||||
return linux.BPF_PROG_TYPE_SOCK_OPS
|
||||
case CGROUP_DEVICE:
|
||||
return linux.BPF_PROG_TYPE_CGROUP_DEVICE
|
||||
case CGROUP_SYSCTL:
|
||||
return linux.BPF_PROG_TYPE_CGROUP_SYSCTL
|
||||
case CGROUP_GETSOCKOPT, CGROUP_SETSOCKOPT:
|
||||
return linux.BPF_PROG_TYPE_CGROUP_SOCKOPT
|
||||
default:
|
||||
return linux.BPF_PROG_TYPE_UNSPEC
|
||||
}
|
||||
}
|
||||
|
||||
// ParseAttachmentType takes a raw linux.BPFAttachType provided by userspace and converts
|
||||
// it an appropriately-typed BPFAttachType object depending on which subsystem it is to be
|
||||
// attached to.
|
||||
//
|
||||
// ParseAttachmentType returns nil if the attachment type is unknown or unsupported.
|
||||
func ParseAttachmentType(b linux.BPFAttachType) AttachType {
|
||||
switch b {
|
||||
case linux.BPF_CGROUP_INET_INGRESS:
|
||||
return CGROUP_INET_INGRESS
|
||||
case linux.BPF_CGROUP_INET_EGRESS:
|
||||
return CGROUP_INET_EGRESS
|
||||
case linux.BPF_CGROUP_INET_SOCK_CREATE:
|
||||
return CGROUP_INET_SOCK_CREATE
|
||||
case linux.BPF_CGROUP_SOCK_OPS:
|
||||
return CGROUP_SOCK_OPS
|
||||
case linux.BPF_CGROUP_DEVICE:
|
||||
return CGROUP_DEVICE
|
||||
case linux.BPF_CGROUP_INET4_BIND:
|
||||
return CGROUP_INET4_BIND
|
||||
case linux.BPF_CGROUP_INET6_BIND:
|
||||
return CGROUP_INET6_BIND
|
||||
case linux.BPF_CGROUP_INET4_CONNECT:
|
||||
return CGROUP_INET4_CONNECT
|
||||
case linux.BPF_CGROUP_INET6_CONNECT:
|
||||
return CGROUP_INET6_CONNECT
|
||||
case linux.BPF_CGROUP_UNIX_CONNECT:
|
||||
return CGROUP_UNIX_CONNECT
|
||||
case linux.BPF_CGROUP_INET4_POST_BIND:
|
||||
return CGROUP_INET4_POST_BIND
|
||||
case linux.BPF_CGROUP_INET6_POST_BIND:
|
||||
return CGROUP_INET6_POST_BIND
|
||||
case linux.BPF_CGROUP_UDP4_SENDMSG:
|
||||
return CGROUP_UDP4_SENDMSG
|
||||
case linux.BPF_CGROUP_UDP6_SENDMSG:
|
||||
return CGROUP_UDP6_SENDMSG
|
||||
case linux.BPF_CGROUP_UNIX_SENDMSG:
|
||||
return CGROUP_UNIX_SENDMSG
|
||||
case linux.BPF_CGROUP_SYSCTL:
|
||||
return CGROUP_SYSCTL
|
||||
case linux.BPF_CGROUP_UDP4_RECVMSG:
|
||||
return CGROUP_UDP4_RECVMSG
|
||||
case linux.BPF_CGROUP_UDP6_RECVMSG:
|
||||
return CGROUP_UDP6_RECVMSG
|
||||
case linux.BPF_CGROUP_UNIX_RECVMSG:
|
||||
return CGROUP_UNIX_RECVMSG
|
||||
case linux.BPF_CGROUP_GETSOCKOPT:
|
||||
return CGROUP_GETSOCKOPT
|
||||
case linux.BPF_CGROUP_SETSOCKOPT:
|
||||
return CGROUP_SETSOCKOPT
|
||||
case linux.BPF_CGROUP_INET4_GETPEERNAME:
|
||||
return CGROUP_INET4_GETPEERNAME
|
||||
case linux.BPF_CGROUP_INET6_GETPEERNAME:
|
||||
return CGROUP_INET6_GETPEERNAME
|
||||
case linux.BPF_CGROUP_UNIX_GETPEERNAME:
|
||||
return CGROUP_UNIX_GETPEERNAME
|
||||
case linux.BPF_CGROUP_INET4_GETSOCKNAME:
|
||||
return CGROUP_INET4_GETSOCKNAME
|
||||
case linux.BPF_CGROUP_INET6_GETSOCKNAME:
|
||||
return CGROUP_INET6_GETSOCKNAME
|
||||
case linux.BPF_CGROUP_UNIX_GETSOCKNAME:
|
||||
return CGROUP_UNIX_GETSOCKNAME
|
||||
case linux.BPF_CGROUP_INET_SOCK_RELEASE:
|
||||
return CGROUP_INET_SOCK_RELEASE
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue