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
179
pkg/eventfd/eventfd.go
Normal file
179
pkg/eventfd/eventfd.go
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
// Copyright 2021 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 eventfd wraps Linux's eventfd(2) syscall.
|
||||
package eventfd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/sagernet/gvisor/pkg/hostarch"
|
||||
"github.com/sagernet/gvisor/pkg/rawfile"
|
||||
"github.com/sagernet/gvisor/pkg/safecopy"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const sizeofUint64 = 8
|
||||
|
||||
// Eventfd represents a Linux eventfd object.
|
||||
type Eventfd struct {
|
||||
fd int
|
||||
mmioAddr uintptr
|
||||
mmioCtrl MMIOController
|
||||
}
|
||||
|
||||
// Create returns an initialized eventfd.
|
||||
func Create() (Eventfd, error) {
|
||||
fd, _, err := unix.RawSyscall(unix.SYS_EVENTFD2, 0, 0, 0)
|
||||
if err != 0 {
|
||||
return Eventfd{}, fmt.Errorf("failed to create eventfd: %v", error(err))
|
||||
}
|
||||
if err := unix.SetNonblock(int(fd), true); err != nil {
|
||||
unix.Close(int(fd))
|
||||
return Eventfd{}, err
|
||||
}
|
||||
return Eventfd{fd: int(fd)}, nil
|
||||
}
|
||||
|
||||
// Wrap returns an initialized Eventfd using the provided fd.
|
||||
func Wrap(fd int) Eventfd {
|
||||
return Eventfd{fd: fd}
|
||||
}
|
||||
|
||||
// Close closes the eventfd, after which it should not be used.
|
||||
func (ev Eventfd) Close() error {
|
||||
if ev.mmioCtrl != nil {
|
||||
ev.mmioCtrl.Close(ev)
|
||||
}
|
||||
return unix.Close(ev.fd)
|
||||
}
|
||||
|
||||
// Dup copies the eventfd, calling dup(2) on the underlying file descriptor.
|
||||
func (ev Eventfd) Dup() (Eventfd, error) {
|
||||
other, err := unix.Dup(ev.fd)
|
||||
if err != nil {
|
||||
return Eventfd{}, fmt.Errorf("failed to dup: %v", other)
|
||||
}
|
||||
return Eventfd{fd: other}, nil
|
||||
}
|
||||
|
||||
// Notify alerts other users of the eventfd. Users can receive alerts by
|
||||
// calling Wait or Read.
|
||||
func (ev Eventfd) Notify() error {
|
||||
return ev.Write(1)
|
||||
}
|
||||
|
||||
// Write writes a specific value to the eventfd.
|
||||
func (ev Eventfd) Write(val uint64) error {
|
||||
var buf [sizeofUint64]byte
|
||||
hostarch.ByteOrder.PutUint64(buf[:], val)
|
||||
if ev.mmioAddr != 0 && ev.mmioCtrl.Enabled() {
|
||||
if _, err := safecopy.CopyOut(ev.mmioPtr(), buf[:]); err == nil {
|
||||
return nil
|
||||
}
|
||||
// Fall back to using a syscall.
|
||||
}
|
||||
for {
|
||||
n, err := nonBlockingWrite(ev.fd, buf[:])
|
||||
if err == unix.EINTR {
|
||||
continue
|
||||
}
|
||||
if err != nil || n != sizeofUint64 {
|
||||
panic(fmt.Sprintf("bad write to eventfd: got %d bytes, wanted %d with error %v", n, sizeofUint64, err))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// MMIOWrite is equivalent to Write, but returns an error if the write cannot be
|
||||
// implemented by writing to the address set by EnableMMIO. This is primarily
|
||||
// useful for testing.
|
||||
func (ev Eventfd) MMIOWrite(val uint64) error {
|
||||
var buf [sizeofUint64]byte
|
||||
hostarch.ByteOrder.PutUint64(buf[:], val)
|
||||
if ev.mmioAddr == 0 {
|
||||
return fmt.Errorf("no MMIO address set")
|
||||
}
|
||||
if !ev.mmioCtrl.Enabled() {
|
||||
return fmt.Errorf("MMIO is temporarily disabled")
|
||||
}
|
||||
_, err := safecopy.CopyOut(ev.mmioPtr(), buf[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// Wait blocks until eventfd is non-zero (i.e. someone calls Notify or Write).
|
||||
func (ev Eventfd) Wait() error {
|
||||
_, err := ev.Read()
|
||||
return err
|
||||
}
|
||||
|
||||
// Read blocks until eventfd is non-zero (i.e. someone calls Notify or Write)
|
||||
// and returns the value read.
|
||||
func (ev Eventfd) Read() (uint64, error) {
|
||||
var tmp [sizeofUint64]byte
|
||||
n, errno := rawfile.BlockingRead(ev.fd, tmp[:])
|
||||
if errno != 0 {
|
||||
return 0, errno
|
||||
}
|
||||
if n == 0 {
|
||||
return 0, io.EOF
|
||||
}
|
||||
if n != sizeofUint64 {
|
||||
panic(fmt.Sprintf("short read from eventfd: got %d bytes, wanted %d", n, sizeofUint64))
|
||||
}
|
||||
return hostarch.ByteOrder.Uint64(tmp[:]), nil
|
||||
}
|
||||
|
||||
// FD returns the underlying file descriptor. Use with care, as this breaks the
|
||||
// Eventfd abstraction.
|
||||
func (ev Eventfd) FD() int {
|
||||
return ev.fd
|
||||
}
|
||||
|
||||
// MMIOController controls eventfd memory-mapped I/O.
|
||||
type MMIOController interface {
|
||||
// Enabled returns true if writing to the associated MMIO address can
|
||||
// succeed. This is inherently racy, so if the memory-mapped write faults,
|
||||
// the eventfd will fall back to writing using a syscall.
|
||||
Enabled() bool
|
||||
|
||||
// Close is called when the associated Eventfd is closed.
|
||||
Close(ev Eventfd)
|
||||
}
|
||||
|
||||
// EnableMMIO causes future calls to ev.Write() to use memory-mapped writes to
|
||||
// addr, subject to ctrl. EnableMMIO cannot be called concurrently with Write,
|
||||
// MMIOWrite, or MMIOAddr.
|
||||
//
|
||||
// This feature is used to support KVM ioeventfds. Since this requires that
|
||||
// addr is mapped read-only or with no permissions in the host virtual address
|
||||
// space (so that writes in host mode fault), it cannot reasonably be
|
||||
// Go-managed memory, so it's safe to type as uintptr rather than a pointer.
|
||||
func (ev *Eventfd) EnableMMIO(addr uintptr, ctrl MMIOController) {
|
||||
ev.mmioAddr = addr
|
||||
ev.mmioCtrl = ctrl
|
||||
}
|
||||
|
||||
// DisableMMIO undoes the effect of a previous call to EnableMMIO. DisableMMIO
|
||||
// cannot be called concurrently with Write, MMIOWrite, or MMIOAddr.
|
||||
func (ev *Eventfd) DisableMMIO() {
|
||||
ev.mmioAddr = 0
|
||||
ev.mmioCtrl = nil
|
||||
}
|
||||
|
||||
// MMIOAddr returns the address set by the last call to EnableMMIO.
|
||||
func (ev Eventfd) MMIOAddr() uintptr {
|
||||
return ev.mmioAddr
|
||||
}
|
||||
3
pkg/eventfd/eventfd_state_autogen.go
Normal file
3
pkg/eventfd/eventfd_state_autogen.go
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// automatically generated by stateify.
|
||||
|
||||
package eventfd
|
||||
40
pkg/eventfd/eventfd_unsafe.go
Normal file
40
pkg/eventfd/eventfd_unsafe.go
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2021 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 eventfd
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func (ev Eventfd) mmioPtr() unsafe.Pointer {
|
||||
return unsafe.Pointer(ev.mmioAddr)
|
||||
}
|
||||
|
||||
// nonBlockingWrite writes the given buffer to a file descriptor. It fails if
|
||||
// partial data is written.
|
||||
func nonBlockingWrite(fd int, buf []byte) (int, error) {
|
||||
var ptr unsafe.Pointer
|
||||
if len(buf) > 0 {
|
||||
ptr = unsafe.Pointer(&buf[0])
|
||||
}
|
||||
|
||||
nwritten, _, errno := unix.RawSyscall(unix.SYS_WRITE, uintptr(fd), uintptr(ptr), uintptr(len(buf)))
|
||||
if errno != 0 {
|
||||
return int(nwritten), errno
|
||||
}
|
||||
return int(nwritten), nil
|
||||
}
|
||||
3
pkg/eventfd/eventfd_unsafe_state_autogen.go
Normal file
3
pkg/eventfd/eventfd_unsafe_state_autogen.go
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
// automatically generated by stateify.
|
||||
|
||||
package eventfd
|
||||
Loading…
Add table
Add a link
Reference in a new issue