sysmsg

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Apr 30, 2024 License: Apache-2.0, MIT Imports: 11 Imported by: 0

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 (
	// PerThreadMemSize is the size of a per-thread memory region.
	PerThreadMemSize = 8 * hostarch.PageSize
	// GuardSize is the size of an unmapped region which is placed right
	// before the signal stack.
	GuardSize                   = hostarch.PageSize
	PerThreadPrivateStackOffset = GuardSize
	PerThreadPrivateStackSize   = 2 * hostarch.PageSize
	// PerThreadStackSharedSize is the size of a per-thread stack region.
	PerThreadSharedStackSize   = 4 * hostarch.PageSize
	PerThreadSharedStackOffset = 4 * hostarch.PageSize
	// MsgOffsetFromStack 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
)

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
	// ContextStateInvalid is an invalid state that the sentry should never see.
	ContextStateInvalid
)

Context State types.

func (*ContextState) Get

func (s *ContextState) Get() ContextState

Get returns the current state value.

func (*ContextState) Set

func (s *ContextState) Set(state ContextState)

Set atomicaly 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
}

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.

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