snapshot: sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1
Содержимое пина, зафиксированного в go.mod sing-box-lx, одним коммитом без истории. Полная история SagerNet/gvisor — 1.45 ГБ и клонируется в каждой CI-джобе; наша дельта — одна вставка в одну функцию, история для неё не нужна. Module path github.com/sagernet/gvisor сохранён намеренно: на него опирается replace-директива суперпроекта. Патч поверх — отдельным коммитом, чтобы дельта читалась одним git show и переносилась на новый пин копированием. SPECS/TASKS/048-GVISOR_HANDSHAKE_NIL_CRASH
This commit is contained in:
commit
2c4ae3b0a4
712 changed files with 185689 additions and 0 deletions
552
pkg/abi/linux/signal.go
Normal file
552
pkg/abi/linux/signal.go
Normal file
|
|
@ -0,0 +1,552 @@
|
|||
// Copyright 2018 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 linux
|
||||
|
||||
import (
|
||||
"github.com/sagernet/gvisor/pkg/bits"
|
||||
"github.com/sagernet/gvisor/pkg/hostarch"
|
||||
)
|
||||
|
||||
const (
|
||||
// SignalMaximum is the highest valid signal number.
|
||||
SignalMaximum = 64
|
||||
|
||||
// FirstStdSignal is the lowest standard signal number.
|
||||
FirstStdSignal = 1
|
||||
|
||||
// LastStdSignal is the highest standard signal number.
|
||||
LastStdSignal = 31
|
||||
|
||||
// FirstRTSignal is the lowest real-time signal number.
|
||||
//
|
||||
// 32 (SIGCANCEL) and 33 (SIGSETXID) are used internally by glibc.
|
||||
FirstRTSignal = 32
|
||||
|
||||
// LastRTSignal is the highest real-time signal number.
|
||||
LastRTSignal = 64
|
||||
|
||||
// NumStdSignals is the number of standard signals.
|
||||
NumStdSignals = LastStdSignal - FirstStdSignal + 1
|
||||
|
||||
// NumRTSignals is the number of realtime signals.
|
||||
NumRTSignals = LastRTSignal - FirstRTSignal + 1
|
||||
)
|
||||
|
||||
// Signal is a signal number.
|
||||
type Signal int
|
||||
|
||||
// IsValid returns true if s is a valid standard or realtime signal. (0 is not
|
||||
// considered valid; interfaces special-casing signal number 0 should check for
|
||||
// 0 first before asserting validity.)
|
||||
func (s Signal) IsValid() bool {
|
||||
return s > 0 && s <= SignalMaximum
|
||||
}
|
||||
|
||||
// IsStandard returns true if s is a standard signal.
|
||||
//
|
||||
// Preconditions: s.IsValid().
|
||||
func (s Signal) IsStandard() bool {
|
||||
return s <= LastStdSignal
|
||||
}
|
||||
|
||||
// IsRealtime returns true if s is a realtime signal.
|
||||
//
|
||||
// Preconditions: s.IsValid().
|
||||
func (s Signal) IsRealtime() bool {
|
||||
return s >= FirstRTSignal
|
||||
}
|
||||
|
||||
// Index returns the index for signal s into arrays of both standard and
|
||||
// realtime signals (e.g. signal masks).
|
||||
//
|
||||
// Preconditions: s.IsValid().
|
||||
func (s Signal) Index() int {
|
||||
return int(s - 1)
|
||||
}
|
||||
|
||||
// Signals.
|
||||
const (
|
||||
SIGABRT = Signal(6)
|
||||
SIGALRM = Signal(14)
|
||||
SIGBUS = Signal(7)
|
||||
SIGCHLD = Signal(17)
|
||||
SIGCLD = Signal(17)
|
||||
SIGCONT = Signal(18)
|
||||
SIGFPE = Signal(8)
|
||||
SIGHUP = Signal(1)
|
||||
SIGILL = Signal(4)
|
||||
SIGINT = Signal(2)
|
||||
SIGIO = Signal(29)
|
||||
SIGIOT = Signal(6)
|
||||
SIGKILL = Signal(9)
|
||||
SIGPIPE = Signal(13)
|
||||
SIGPOLL = Signal(29)
|
||||
SIGPROF = Signal(27)
|
||||
SIGPWR = Signal(30)
|
||||
SIGQUIT = Signal(3)
|
||||
SIGSEGV = Signal(11)
|
||||
SIGSTKFLT = Signal(16)
|
||||
SIGSTOP = Signal(19)
|
||||
SIGSYS = Signal(31)
|
||||
SIGTERM = Signal(15)
|
||||
SIGTRAP = Signal(5)
|
||||
SIGTSTP = Signal(20)
|
||||
SIGTTIN = Signal(21)
|
||||
SIGTTOU = Signal(22)
|
||||
SIGUNUSED = Signal(31)
|
||||
SIGURG = Signal(23)
|
||||
SIGUSR1 = Signal(10)
|
||||
SIGUSR2 = Signal(12)
|
||||
SIGVTALRM = Signal(26)
|
||||
SIGWINCH = Signal(28)
|
||||
SIGXCPU = Signal(24)
|
||||
SIGXFSZ = Signal(25)
|
||||
)
|
||||
|
||||
// SignalSet is a signal mask with a bit corresponding to each signal.
|
||||
//
|
||||
// +marshal
|
||||
type SignalSet uint64
|
||||
|
||||
// SignalSetSize is the size in bytes of a SignalSet.
|
||||
const SignalSetSize = 8
|
||||
|
||||
// MakeSignalSet returns SignalSet with the bit corresponding to each of the
|
||||
// given signals set.
|
||||
func MakeSignalSet(sigs ...Signal) SignalSet {
|
||||
indices := make([]int, len(sigs))
|
||||
for i, sig := range sigs {
|
||||
indices[i] = sig.Index()
|
||||
}
|
||||
return SignalSet(bits.Mask64(indices...))
|
||||
}
|
||||
|
||||
// SignalSetOf returns a SignalSet with a single signal set.
|
||||
func SignalSetOf(sig Signal) SignalSet {
|
||||
return SignalSet(bits.MaskOf64(sig.Index()))
|
||||
}
|
||||
|
||||
// ForEachSignal invokes f for each signal set in the given mask.
|
||||
func ForEachSignal(mask SignalSet, f func(sig Signal)) {
|
||||
bits.ForEachSetBit64(uint64(mask), func(i int) {
|
||||
f(Signal(i + 1))
|
||||
})
|
||||
}
|
||||
|
||||
// 'how' values for rt_sigprocmask(2).
|
||||
const (
|
||||
// SIG_BLOCK blocks the signals in the set.
|
||||
SIG_BLOCK = 0
|
||||
|
||||
// SIG_UNBLOCK blocks the signals in the set.
|
||||
SIG_UNBLOCK = 1
|
||||
|
||||
// SIG_SETMASK sets the signal mask to set.
|
||||
SIG_SETMASK = 2
|
||||
)
|
||||
|
||||
// Signal actions for rt_sigaction(2), from uapi/asm-generic/signal-defs.h.
|
||||
const (
|
||||
// SIG_DFL performs the default action.
|
||||
SIG_DFL = 0
|
||||
|
||||
// SIG_IGN ignores the signal.
|
||||
SIG_IGN = 1
|
||||
)
|
||||
|
||||
// Signal action flags for rt_sigaction(2), from uapi/asm-generic/signal.h.
|
||||
const (
|
||||
SA_NOCLDSTOP = 0x00000001
|
||||
SA_NOCLDWAIT = 0x00000002
|
||||
SA_SIGINFO = 0x00000004
|
||||
SA_RESTORER = 0x04000000
|
||||
SA_ONSTACK = 0x08000000
|
||||
SA_RESTART = 0x10000000
|
||||
SA_NODEFER = 0x40000000
|
||||
SA_RESETHAND = 0x80000000
|
||||
SA_NOMASK = SA_NODEFER
|
||||
SA_ONESHOT = SA_RESETHAND
|
||||
)
|
||||
|
||||
// Signal stack flags for signalstack(2), from include/uapi/linux/signal.h.
|
||||
const (
|
||||
SS_ONSTACK = 1
|
||||
SS_DISABLE = 2
|
||||
)
|
||||
|
||||
// SIGPOLL si_codes.
|
||||
const (
|
||||
// SI_POLL is defined as __SI_POLL in Linux 2.6.
|
||||
SI_POLL = 2 << 16
|
||||
|
||||
// POLL_IN indicates that data input available.
|
||||
POLL_IN = SI_POLL | 1
|
||||
|
||||
// POLL_OUT indicates that output buffers available.
|
||||
POLL_OUT = SI_POLL | 2
|
||||
|
||||
// POLL_MSG indicates that an input message available.
|
||||
POLL_MSG = SI_POLL | 3
|
||||
|
||||
// POLL_ERR indicates that there was an i/o error.
|
||||
POLL_ERR = SI_POLL | 4
|
||||
|
||||
// POLL_PRI indicates that a high priority input available.
|
||||
POLL_PRI = SI_POLL | 5
|
||||
|
||||
// POLL_HUP indicates that a device disconnected.
|
||||
POLL_HUP = SI_POLL | 6
|
||||
)
|
||||
|
||||
// Possible values for si_code.
|
||||
const (
|
||||
// SI_USER is sent by kill, sigsend, raise.
|
||||
SI_USER = 0
|
||||
|
||||
// SI_KERNEL is sent by the kernel from somewhere.
|
||||
SI_KERNEL = 0x80
|
||||
|
||||
// SI_QUEUE is sent by sigqueue.
|
||||
SI_QUEUE = -1
|
||||
|
||||
// SI_TIMER is sent by timer expiration.
|
||||
SI_TIMER = -2
|
||||
|
||||
// SI_MESGQ is sent by real time mesq state change.
|
||||
SI_MESGQ = -3
|
||||
|
||||
// SI_ASYNCIO is sent by AIO completion.
|
||||
SI_ASYNCIO = -4
|
||||
|
||||
// SI_SIGIO is sent by queued SIGIO.
|
||||
SI_SIGIO = -5
|
||||
|
||||
// SI_TKILL is sent by tkill system call.
|
||||
SI_TKILL = -6
|
||||
|
||||
// SI_DETHREAD is sent by execve() killing subsidiary threads.
|
||||
SI_DETHREAD = -7
|
||||
|
||||
// SI_ASYNCNL is sent by glibc async name lookup completion.
|
||||
SI_ASYNCNL = -60
|
||||
)
|
||||
|
||||
// CLD_* codes are only meaningful for SIGCHLD.
|
||||
const (
|
||||
// CLD_EXITED indicates that a task exited.
|
||||
CLD_EXITED = 1
|
||||
|
||||
// CLD_KILLED indicates that a task was killed by a signal.
|
||||
CLD_KILLED = 2
|
||||
|
||||
// CLD_DUMPED indicates that a task was killed by a signal and then dumped
|
||||
// core.
|
||||
CLD_DUMPED = 3
|
||||
|
||||
// CLD_TRAPPED indicates that a task was stopped by ptrace.
|
||||
CLD_TRAPPED = 4
|
||||
|
||||
// CLD_STOPPED indicates that a thread group completed a group stop.
|
||||
CLD_STOPPED = 5
|
||||
|
||||
// CLD_CONTINUED indicates that a group-stopped thread group was continued.
|
||||
CLD_CONTINUED = 6
|
||||
)
|
||||
|
||||
// SYS_* codes are only meaningful for SIGSYS.
|
||||
const (
|
||||
// SYS_SECCOMP indicates that a signal originates from seccomp.
|
||||
SYS_SECCOMP = 1
|
||||
)
|
||||
|
||||
// Possible values for Sigevent.Notify, aka struct sigevent::sigev_notify.
|
||||
const (
|
||||
SIGEV_SIGNAL = 0
|
||||
SIGEV_NONE = 1
|
||||
SIGEV_THREAD = 2
|
||||
SIGEV_THREAD_ID = 4
|
||||
)
|
||||
|
||||
// SIGTRAP si_codes
|
||||
const (
|
||||
TRAP_BRKPT = 1
|
||||
TRAP_TRACE = 2
|
||||
TRAP_BRANCH = 3
|
||||
TRAP_HWBKPT = 4
|
||||
)
|
||||
|
||||
// Sigevent represents struct sigevent.
|
||||
//
|
||||
// +marshal
|
||||
type Sigevent struct {
|
||||
Value uint64 // union sigval {int, void*}
|
||||
Signo int32
|
||||
Notify int32
|
||||
|
||||
// struct sigevent here contains 48-byte union _sigev_un. However, only
|
||||
// member _tid is significant to the kernel.
|
||||
Tid int32
|
||||
UnRemainder [44]byte
|
||||
}
|
||||
|
||||
// SigAction represents struct sigaction.
|
||||
//
|
||||
// +marshal
|
||||
// +stateify savable
|
||||
type SigAction struct {
|
||||
Handler uint64
|
||||
Flags uint64
|
||||
Restorer uint64
|
||||
Mask SignalSet
|
||||
}
|
||||
|
||||
// SignalStack represents information about a user stack, and is equivalent to
|
||||
// stack_t.
|
||||
//
|
||||
// +marshal
|
||||
// +stateify savable
|
||||
type SignalStack struct {
|
||||
Addr uint64
|
||||
Flags uint32
|
||||
_ uint32
|
||||
Size uint64
|
||||
}
|
||||
|
||||
// Contains checks if the stack pointer is within this stack.
|
||||
func (s *SignalStack) Contains(sp hostarch.Addr) bool {
|
||||
return hostarch.Addr(s.Addr) < sp && sp <= hostarch.Addr(s.Addr+s.Size)
|
||||
}
|
||||
|
||||
// Top returns the stack's top address.
|
||||
func (s *SignalStack) Top() hostarch.Addr {
|
||||
return hostarch.Addr(s.Addr + s.Size)
|
||||
}
|
||||
|
||||
// IsEnabled returns true iff this signal stack is marked as enabled.
|
||||
func (s *SignalStack) IsEnabled() bool {
|
||||
return s.Flags&SS_DISABLE == 0
|
||||
}
|
||||
|
||||
// SignalInfo represents information about a signal being delivered, and is
|
||||
// equivalent to struct siginfo in linux kernel(linux/include/uapi/asm-generic/siginfo.h).
|
||||
//
|
||||
// +marshal
|
||||
// +stateify savable
|
||||
type SignalInfo struct {
|
||||
Signo int32 // Signal number
|
||||
Errno int32 // Errno value
|
||||
Code int32 // Signal code
|
||||
_ uint32
|
||||
|
||||
// struct siginfo::_sifields is a union. In SignalInfo, fields in the union
|
||||
// are accessed through methods.
|
||||
//
|
||||
// For reference, here is the definition of _sifields: (_sigfault._trapno,
|
||||
// which does not exist on x86, omitted for clarity)
|
||||
//
|
||||
// union {
|
||||
// int _pad[SI_PAD_SIZE];
|
||||
//
|
||||
// /* kill() */
|
||||
// struct {
|
||||
// __kernel_pid_t _pid; /* sender's pid */
|
||||
// __ARCH_SI_UID_T _uid; /* sender's uid */
|
||||
// } _kill;
|
||||
//
|
||||
// /* POSIX.1b timers */
|
||||
// struct {
|
||||
// __kernel_timer_t _tid; /* timer id */
|
||||
// int _overrun; /* overrun count */
|
||||
// char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
|
||||
// sigval_t _sigval; /* same as below */
|
||||
// int _sys_private; /* not to be passed to user */
|
||||
// } _timer;
|
||||
//
|
||||
// /* POSIX.1b signals */
|
||||
// struct {
|
||||
// __kernel_pid_t _pid; /* sender's pid */
|
||||
// __ARCH_SI_UID_T _uid; /* sender's uid */
|
||||
// sigval_t _sigval;
|
||||
// } _rt;
|
||||
//
|
||||
// /* SIGCHLD */
|
||||
// struct {
|
||||
// __kernel_pid_t _pid; /* which child */
|
||||
// __ARCH_SI_UID_T _uid; /* sender's uid */
|
||||
// int _status; /* exit code */
|
||||
// __ARCH_SI_CLOCK_T _utime;
|
||||
// __ARCH_SI_CLOCK_T _stime;
|
||||
// } _sigchld;
|
||||
//
|
||||
// /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
|
||||
// struct {
|
||||
// void *_addr; /* faulting insn/memory ref. */
|
||||
// short _addr_lsb; /* LSB of the reported address */
|
||||
// } _sigfault;
|
||||
//
|
||||
// /* SIGPOLL */
|
||||
// struct {
|
||||
// __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */
|
||||
// int _fd;
|
||||
// } _sigpoll;
|
||||
//
|
||||
// /* SIGSYS */
|
||||
// struct {
|
||||
// void *_call_addr; /* calling user insn */
|
||||
// int _syscall; /* triggering system call number */
|
||||
// unsigned int _arch; /* AUDIT_ARCH_* of syscall */
|
||||
// } _sigsys;
|
||||
// } _sifields;
|
||||
//
|
||||
// _sifields is padded so that the size of siginfo is SI_MAX_SIZE = 128
|
||||
// bytes.
|
||||
Fields [128 - 16]byte
|
||||
}
|
||||
|
||||
// FixSignalCodeForUser fixes up si_code.
|
||||
//
|
||||
// The si_code we get from Linux may contain the kernel-specific code in the
|
||||
// top 16 bits if it's positive (e.g., from ptrace). Linux's
|
||||
// copy_siginfo_to_user does:
|
||||
// err |= __put_user((short)from->si_code, &to->si_code);
|
||||
// to mask out those bits and we need to do the same.
|
||||
func (s *SignalInfo) FixSignalCodeForUser() {
|
||||
if s.Code > 0 {
|
||||
s.Code &= 0x0000ffff
|
||||
}
|
||||
}
|
||||
|
||||
// PID returns the si_pid field.
|
||||
func (s *SignalInfo) PID() int32 {
|
||||
return int32(hostarch.ByteOrder.Uint32(s.Fields[0:4]))
|
||||
}
|
||||
|
||||
// SetPID mutates the si_pid field.
|
||||
func (s *SignalInfo) SetPID(val int32) {
|
||||
hostarch.ByteOrder.PutUint32(s.Fields[0:4], uint32(val))
|
||||
}
|
||||
|
||||
// UID returns the si_uid field.
|
||||
func (s *SignalInfo) UID() int32 {
|
||||
return int32(hostarch.ByteOrder.Uint32(s.Fields[4:8]))
|
||||
}
|
||||
|
||||
// SetUID mutates the si_uid field.
|
||||
func (s *SignalInfo) SetUID(val int32) {
|
||||
hostarch.ByteOrder.PutUint32(s.Fields[4:8], uint32(val))
|
||||
}
|
||||
|
||||
// Sigval returns the sigval field, which is aliased to both si_int and si_ptr.
|
||||
func (s *SignalInfo) Sigval() uint64 {
|
||||
return hostarch.ByteOrder.Uint64(s.Fields[8:16])
|
||||
}
|
||||
|
||||
// SetSigval mutates the sigval field.
|
||||
func (s *SignalInfo) SetSigval(val uint64) {
|
||||
hostarch.ByteOrder.PutUint64(s.Fields[8:16], val)
|
||||
}
|
||||
|
||||
// TimerID returns the si_timerid field.
|
||||
func (s *SignalInfo) TimerID() TimerID {
|
||||
return TimerID(hostarch.ByteOrder.Uint32(s.Fields[0:4]))
|
||||
}
|
||||
|
||||
// SetTimerID sets the si_timerid field.
|
||||
func (s *SignalInfo) SetTimerID(val TimerID) {
|
||||
hostarch.ByteOrder.PutUint32(s.Fields[0:4], uint32(val))
|
||||
}
|
||||
|
||||
// Overrun returns the si_overrun field.
|
||||
func (s *SignalInfo) Overrun() int32 {
|
||||
return int32(hostarch.ByteOrder.Uint32(s.Fields[4:8]))
|
||||
}
|
||||
|
||||
// SetOverrun sets the si_overrun field.
|
||||
func (s *SignalInfo) SetOverrun(val int32) {
|
||||
hostarch.ByteOrder.PutUint32(s.Fields[4:8], uint32(val))
|
||||
}
|
||||
|
||||
// Addr returns the si_addr field.
|
||||
func (s *SignalInfo) Addr() uint64 {
|
||||
return hostarch.ByteOrder.Uint64(s.Fields[0:8])
|
||||
}
|
||||
|
||||
// SetAddr sets the si_addr field.
|
||||
func (s *SignalInfo) SetAddr(val uint64) {
|
||||
hostarch.ByteOrder.PutUint64(s.Fields[0:8], val)
|
||||
}
|
||||
|
||||
// Status returns the si_status field.
|
||||
func (s *SignalInfo) Status() int32 {
|
||||
return int32(hostarch.ByteOrder.Uint32(s.Fields[8:12]))
|
||||
}
|
||||
|
||||
// SetStatus mutates the si_status field.
|
||||
func (s *SignalInfo) SetStatus(val int32) {
|
||||
hostarch.ByteOrder.PutUint32(s.Fields[8:12], uint32(val))
|
||||
}
|
||||
|
||||
// CallAddr returns the si_call_addr field.
|
||||
func (s *SignalInfo) CallAddr() uint64 {
|
||||
return hostarch.ByteOrder.Uint64(s.Fields[0:8])
|
||||
}
|
||||
|
||||
// SetCallAddr mutates the si_call_addr field.
|
||||
func (s *SignalInfo) SetCallAddr(val uint64) {
|
||||
hostarch.ByteOrder.PutUint64(s.Fields[0:8], val)
|
||||
}
|
||||
|
||||
// Syscall returns the si_syscall field.
|
||||
func (s *SignalInfo) Syscall() int32 {
|
||||
return int32(hostarch.ByteOrder.Uint32(s.Fields[8:12]))
|
||||
}
|
||||
|
||||
// SetSyscall mutates the si_syscall field.
|
||||
func (s *SignalInfo) SetSyscall(val int32) {
|
||||
hostarch.ByteOrder.PutUint32(s.Fields[8:12], uint32(val))
|
||||
}
|
||||
|
||||
// Arch returns the si_arch field.
|
||||
func (s *SignalInfo) Arch() uint32 {
|
||||
return hostarch.ByteOrder.Uint32(s.Fields[12:16])
|
||||
}
|
||||
|
||||
// SetArch mutates the si_arch field.
|
||||
func (s *SignalInfo) SetArch(val uint32) {
|
||||
hostarch.ByteOrder.PutUint32(s.Fields[12:16], val)
|
||||
}
|
||||
|
||||
// Band returns the si_band field.
|
||||
func (s *SignalInfo) Band() int64 {
|
||||
return int64(hostarch.ByteOrder.Uint64(s.Fields[0:8]))
|
||||
}
|
||||
|
||||
// SetBand mutates the si_band field.
|
||||
func (s *SignalInfo) SetBand(val int64) {
|
||||
// Note: this assumes the platform uses `long` as `__ARCH_SI_BAND_T`.
|
||||
// On some platforms, which gVisor doesn't support, `__ARCH_SI_BAND_T` is
|
||||
// `int`. See siginfo.h.
|
||||
hostarch.ByteOrder.PutUint64(s.Fields[0:8], uint64(val))
|
||||
}
|
||||
|
||||
// FD returns the si_fd field.
|
||||
func (s *SignalInfo) FD() uint32 {
|
||||
return hostarch.ByteOrder.Uint32(s.Fields[8:12])
|
||||
}
|
||||
|
||||
// SetFD mutates the si_fd field.
|
||||
func (s *SignalInfo) SetFD(val uint32) {
|
||||
hostarch.ByteOrder.PutUint32(s.Fields[8:12], val)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue