sysmsg

package
v0.0.0-...-5c0fc10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: Apache-2.0, BSD-3-Clause, MIT Imports: 12 Imported by: 2

Documentation

Overview

Package sysmsg provides a stub signal handler and a communication protocol between stub threads and the Sentry.

Note that this package is allowlisted for use of sync/atomic.

+checkalignedignore

Index

Constants

View Source
const (
	// MsgOffsetFromSharedStack is the offset of the Msg structure on
	// the thread stack.
	MsgOffsetFromSharedStack = PerThreadMemSize - hostarch.PageSize - PerThreadSharedStackOffset

	// SpinningQueueMemSize is the size of a spinning queue memory region.
	SpinningQueueMemSize = hostarch.PageSize
)

LINT.IfChange Per-thread stack layout:

*------------* | guard page | |------------| | | | sysstack | | | *------------* | guard page | |------------| | | | ^ | | / \ | | | | | altstack | |------------| | sysmsg | *------------*

View Source
const (
	// MaxFPStateLen is the largest possible FPState that we will save.
	// Note: This value was chosen to be able to fit ThreadContext into one page.
	MaxFPStateLen uint32 = 3584

	// AllocatedSizeofThreadContextStruct defines how much memory to allocate for
	// one instance of ThreadContext.
	// We over allocate the memory for it because:
	//   - The next instances needs to align to 64 bytes for purposes of xsave.
	//   - It's nice to align it to the page boundary.
	AllocatedSizeofThreadContextStruct uintptr = 4096
)
View Source
const (
	// PerThreadMemSize is the size of a per-thread memory region (32KB).
	PerThreadMemSize = 8 * hostarch.PageSize
	// GuardSize is the size of an unmapped region before the signal stack (4KB).
	GuardSize                   = hostarch.PageSize
	PerThreadPrivateStackOffset = GuardSize
	PerThreadPrivateStackSize   = 2 * hostarch.PageSize
	// PerThreadSharedStackSize is the size of a per-thread stack region (16KB, includes stack + sysmsg).
	PerThreadSharedStackSize   = 4 * hostarch.PageSize
	PerThreadSharedStackOffset = 4 * hostarch.PageSize
)

Variables

View Source
var SighandlerBlob []byte

SighandlerBlob contains the compiled code of the sysmsg signal handler.

Functions

func MsgToStackAddr

func MsgToStackAddr(msg uintptr) uintptr

MsgToStackAddr returns a start address of a stack.

func StackAddrToMsg

func StackAddrToMsg(sp uintptr) uintptr

StackAddrToMsg returns an address of a sysmsg structure.

func StackAddrToSyshandlerStack

func StackAddrToSyshandlerStack(sp uintptr) uintptr

StackAddrToSyshandlerStack returns an address of a syshandler stack.

Types

type ArchState

type ArchState struct {
	// contains filtered or unexported fields
}

ArchState defines variables specific to the architecture being used.

func (*ArchState) FpLen

func (s *ArchState) FpLen() int

FpLen returns the FP state length for AMD64.

func (*ArchState) Init

func (s *ArchState) Init()

Init initializes the arch specific state.

func (*ArchState) String

func (s *ArchState) String() string

type ContextState

type ContextState uint32

ContextState defines the reason the context has exited back to the sentry, or ContextStateNone if running/ready-to-run.

const (
	// ContextStateNone means that is either running in the user task or is ready
	// to run in the user task.
	ContextStateNone ContextState = iota
	// ContextStateSyscall means that a syscall event is triggered from the
	// sighandler.
	ContextStateSyscall
	// ContextStateFault means that there is a fault event that needs to be
	// handled.
	ContextStateFault
	// ContextStateSyscallTrap means that a syscall event is triggered from
	// a function call (syshandler).
	ContextStateSyscallTrap
	// ContextStateSyscallCanBePatched means that the syscall can be replaced
	// with a function call.
	ContextStateSyscallCanBePatched
	// ContextStateUnexpectedDeath means a stub thread died unexpectedly.
	ContextStateUnexpectedDeath
	// ContextStateInvalid is an invalid state that the sentry should never see.
	ContextStateInvalid
)

Context State types.

func (*ContextState) CompareAndSwap

func (s *ContextState) CompareAndSwap(old, new ContextState) bool

CompareAndSwap performs a compare-and-swap operation on the state value.

func (*ContextState) Get

func (s *ContextState) Get() ContextState

Get returns the current state value.

func (*ContextState) Set

func (s *ContextState) Set(state ContextState)

Set atomically sets the state value.

type Msg

type Msg struct {
	// The next batch of fields is used to call the syshandler stub
	// function. A system call can be replaced with a function call. When
	// a function call is executed, it can't change the current process
	// stack, so it needs to save stack and instruction registers, switch
	// on its syshandler stack and call the jmp instruction to the syshandler
	// address.
	//
	// Self is a pointer to itself in a process address space.
	Self uint64
	// RetAddr is a return address from the syshandler function.
	RetAddr uint64
	// Syshandler is an address of the syshandler function.
	Syshandler uint64
	// SyshandlerStack is an address of  the thread syshandler stack.
	SyshandlerStack uint64
	// AppStack is a value of the stack register before calling the syshandler
	// function.
	AppStack uint64

	// State indicates to the sentry what the sysmsg thread is doing at a given
	// moment.
	State ThreadState
	// Context is a pointer to the ThreadContext struct that the current sysmsg
	// thread is processing.
	Context uint64

	// FaultJump is the size of a faulted instruction.
	FaultJump int32
	// Err is the error value with which the {sig|sys}handler crashes the stub
	// thread (see sysmsg.h:__panic).
	Err int32
	// ErrAdditional is an error value that gives additional information
	// about the panic.
	ErrAdditional int32
	// Line is the code line on which the {sig|sys}handler crashed the stub thread
	// (see sysmsg.h:panic).
	Line int32
	// Debug is a variable to use to get visibility into the stub from the sentry.
	Debug uint64
	// ThreadID is the ID of the sysmsg thread.
	ThreadID uint32
	// contains filtered or unexported fields
}

Msg contains the current state of the sysmsg thread.

func (*Msg) ConvertSysmsgErr

func (m *Msg) ConvertSysmsgErr() *platform.ContextError

ConvertSysmsgErr converts m.Err to platform.ContextError.

func (*Msg) Init

func (m *Msg) Init(threadID uint32)

Init initializes the message.

func (*Msg) String

func (m *Msg) String() string

func (*Msg) WakeSysmsgThread

func (m *Msg) WakeSysmsgThread() (bool, syscall.Errno)

WakeSysmsgThread calls futex wake on Sysmsg.State.

type StubError

type StubError int32

StubError are values that represent known stub-thread failure modes. Since these errors originate from the stub threads, look at sysmsg.h:stub_error.

const (
	// StubErrorBadSysmsg indicates sysmsg->self did not match sysmsg.
	StubErrorBadSysmsg StubError = 0x0bad0000 + iota
	// StubErrorBadThreadState indicates sysmsg->state was invalid.
	StubErrorBadThreadState
	// StubErrorBadSpinningQueueDecref indicates stubs removed more threads
	// from spinning queue than were put in.
	StubErrorBadSpinningQueueDecref
	// StubErrorArchPrctl indicates an error when calling arch_prctl.
	StubErrorArchPrctl
	// StubErrorFutex indicates an error when calling futex.
	StubErrorFutex
	// StubErrorBadContextID indicates a context received from the context
	// queue was of unexpected value.
	StubErrorBadContextID
	// StubErrorFpStateBadHeader indicates that the floating point state
	// header did not match the expected value.
	StubErrorFpStateBadHeader
)

type ThreadContext

type ThreadContext struct {
	// FPState is a region of memory where:
	//   - syshandler saves FPU state to using xsave/fxsave
	//   - sighandler copies FPU state to from ucontext->uc_mcontext.fpregs
	// Note that xsave requires this region of memory to be 64 byte aligned;
	// therefore allocations of ThreadContext must be too.
	FPState [MaxFPStateLen]byte
	// FPStateChanged is set to true when the stub thread needs to restore FPState
	// because the sentry changed it.
	FPStateChanged uint64
	// Regs is the context's GP register set. The {sig|sys}handler will save and
	// restore the user app's registers here.
	Regs linux.PtraceRegs

	// SignalInfo is the siginfo struct.
	SignalInfo linux.SignalInfo
	// Signo is the signal that the stub is requesting the sentry to handle.
	Signo int64
	// State indicates the reason why the context has exited back to the sentry.
	State ContextState
	// Interrupt is set to indicate that this context has been interrupted.
	Interrupt uint32
	// ThreadID is the ID of the sysmsg thread that's currently working on the
	// context.
	ThreadID uint32
	// LastThreadID is the ID of the previous sysmsg thread that ran the context
	// (not the one currently working on it). This field is used by sysmsg threads
	// to detect whether fpstate may have changed since the last time they ran a
	// context.
	LastThreadID uint32
	// SentryFastPath is used to indicate to the stub thread that the sentry
	// goroutine used for this thread context is busy-polling for a response
	// instead of using FUTEX_WAIT.
	SentryFastPath uint32
	// AckedTime is used by sysmsg threads to signal to the sentry that this context
	// has been picked up from the context queue and is actively being worked on.
	// The stub thread puts down the timestamp at which it has started processing
	// this context.
	AckedTime uint64
	// StateChangedTime is the time when the ThreadContext.State changed, as
	// recorded by the stub thread when it gave it back to the sentry
	// (the sentry does not populate this field except to reset it).
	StateChangedTime uint64
	// TLS is a pointer to a thread local storage.
	// It is is only populated on ARM64.
	TLS uint64
	// Debug is a variable to use to get visibility into the stub from the sentry.
	Debug uint64
	// SigError is an error code that clarifies the nature of the signal.
	SigError uint64
}

ThreadContext contains the current context of the sysmsg thread. The struct facilitates switching contexts by allowing the sentry to switch pointers to this struct as it needs to.

N.B ThreadContexts are shared between all sysmsg threads within a subprocess, and are necessarily writeable by any thread within the subprocess. If a subprocess really wants to (i.e. sandbox break-out attempts) it can find where the TC region is mapped and use other threads to manipulate this data for a thread doing a context switch into the sentry. This is OK because as a rule we do not trust this data; if any funny business is going on the sentry simply kills the subprocess.

func (*ThreadContext) Init

func (c *ThreadContext) Init(initialThreadID uint32)

Init initializes the ThreadContext instance.

func (*ThreadContext) SleepOnState

func (c *ThreadContext) SleepOnState(curState ContextState, timeout *unix.Timespec) syscall.Errno

SleepOnState makes the caller sleep on the ThreadContext.State futex.

func (*ThreadContext) String

func (c *ThreadContext) String() string

type ThreadState

type ThreadState uint32

ThreadState is used to store a state of the sysmsg thread.

const (
	// ThreadStateNone means that the thread is executing the user workload.
	ThreadStateNone ThreadState = iota
	// ThreadStateDone means that last event has been handled and the stub thread
	// can be resumed.
	ThreadStateDone
	// ThreadStatePrep means that syshandler started filling the sysmsg struct.
	ThreadStatePrep
	// ThreadStateAsleep means that this thread fell asleep because there was not
	// enough contexts to process in the context queue.
	ThreadStateAsleep
	// ThreadStateInitializing is only set once at sysmsg thread creation time. It
	// is used to tell the signal handler that the thread does not yet have a
	// context.
	ThreadStateInitializing
)

func (*ThreadState) CompareAndSwap

func (s *ThreadState) CompareAndSwap(old, state ThreadState) bool

CompareAndSwap atomicaly compares and swaps the state value.

func (*ThreadState) Get

func (s *ThreadState) Get() ThreadState

Get returns the current state value.

func (*ThreadState) Set

func (s *ThreadState) Set(state ThreadState)

Set atomicaly sets the state value.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL