Documentation
¶
Overview ¶
Package uffd provides Linux userfaultfd helpers without cgo at runtime.
Index ¶
- Constants
- Variables
- func CheckSupport() error
- func CheckSupportWithFlags(flags uintptr) error
- func GetCopyBytes(copy *UffdioCopy) int64
- func GetMoveBytes(move *UffdioMove) int64
- func GetMsgArg(msg *UffdMsg) [24]byte
- func GetMsgEvent(msg *UffdMsg) uint8
- func GetPagefaultAddress(pagefault *UffdPagefault) uint64
- func Handle(uffd UFFD, start uintptr, src io.ReaderAt) error
- func HandleContext(ctx context.Context, uffd UFFD, start uintptr, src io.ReaderAt) error
- func Populate(uffd UFFD, address uintptr, data []byte) (int64, error)
- func PopulateMove(uffd UFFD, address uintptr, data []byte) (int64, error)
- func ReceiveFDs(conn *net.UnixConn, num int) ([]uintptr, error)
- func SendFDs(conn *net.UnixConn, fds []uintptr) error
- func SendUFFD(conn *net.UnixConn, uffd UFFD, start uintptr) error
- type Fault
- type Handler
- type HandlerOptions
- type MoveBuffer
- type Registration
- type Resolver
- type UFFD
- type UffdMsg
- type UffdPagefault
- type UffdioAPI
- type UffdioCopy
- type UffdioMove
- type UffdioRange
- type UffdioRegister
Constants ¶
const ( // UFFD_O_CLOEXEC requests that Open mark the returned descriptor // close-on-exec. UFFD_O_CLOEXEC = uintptr(unix.O_CLOEXEC) // UFFD_O_NONBLOCK requests that Open return a non-blocking descriptor. UFFD_O_NONBLOCK = uintptr(unix.O_NONBLOCK) // UFFD_OPEN_DEFAULT keeps the returned fd close-on-exec and non-blocking. // // Callers that specifically want a userspace-fault-only descriptor can add // UFFD_USER_MODE_ONLY explicitly. UFFD_OPEN_DEFAULT = uffdSharedOpenFlags // UFFD_API is the userfaultfd API version passed to UFFDIO_API during // descriptor initialisation. UFFD_API = uint64(0xAA) // UFFD_EVENT_PAGEFAULT identifies a missing-page event in UffdMsg.Event. UFFD_EVENT_PAGEFAULT = uint8(0x12) // UFFDIO_REGISTER_MODE_MISSING requests missing-page tracking when // registering a virtual address range. UFFDIO_REGISTER_MODE_MISSING = uint64(1) // UFFDIO_API is the ioctl number used to negotiate the userfaultfd API // version and feature bits. UFFDIO_API = uintptr(0xC018AA3F) // UFFDIO_REGISTER is the ioctl number used to register a virtual address // range for userfaultfd tracking. UFFDIO_REGISTER = uintptr(0xC020AA00) // UFFDIO_COPY is the ioctl number used to resolve a fault by copying bytes // into the registered range. UFFDIO_COPY = uintptr(0xC028AA03) // UFFDIO_MOVE is the ioctl number used to resolve a fault by moving page // contents into the registered range. UFFDIO_MOVE = uintptr(0xC028AA05) )
const ( // UFFD_FEATURE_MOVE is the feature bit negotiated through UFFDIO_API that // enables UFFDIO_MOVE support for a descriptor. UFFD_FEATURE_MOVE = uint64(1 << 16) // UFFD_USER_MODE_ONLY requests a descriptor that handles faults originating // in user mode and skips kernel-mode faults. UFFD_USER_MODE_ONLY = uintptr(1) )
Variables ¶
var ( // ErrUnexpectedEventType indicates that a userfaultfd event other than a // missing-page fault was received by Handle. ErrUnexpectedEventType = errors.New("unexpected event type") // ErrInvalidFDsLength indicates that a Unix rights message contained an // unexpected number of file descriptors. ErrInvalidFDsLength = errors.New("invalid file descriptors length") // ErrUnsupportedPlatform indicates that the current GOOS/GOARCH does not // support the low-level userfaultfd implementation in this package. ErrUnsupportedPlatform = errors.New("userfaultfd is unsupported on this platform") // ErrInvalidPopulateRange indicates that Populate was asked to operate on a // destination or buffer length that is not page aligned. ErrInvalidPopulateRange = errors.New("populate range must be page aligned") )
Functions ¶
func CheckSupport ¶
func CheckSupport() error
CheckSupport verifies that the running kernel supports at least the fallback UFFDIO_COPY mode used by this package and that the current process can open a userfaultfd with UFFD_OPEN_DEFAULT.
func CheckSupportWithFlags ¶
CheckSupportWithFlags verifies that the running kernel supports at least the fallback UFFDIO_COPY mode used by this package and that the current process can open a userfaultfd with the supplied flags.
func GetCopyBytes ¶
func GetCopyBytes(copy *UffdioCopy) int64
GetCopyBytes returns the completion count written back by UFFDIO_COPY.
func GetMoveBytes ¶
func GetMoveBytes(move *UffdioMove) int64
GetMoveBytes returns the completion count written back by UFFDIO_MOVE.
func GetMsgArg ¶
GetMsgArg returns the raw 24-byte argument payload from a raw uffd_msg.
Callers can reinterpret the bytes according to the event type.
func GetMsgEvent ¶
GetMsgEvent returns the event discriminator from a raw uffd_msg.
func GetPagefaultAddress ¶
func GetPagefaultAddress(pagefault *UffdPagefault) uint64
GetPagefaultAddress returns the fault address encoded in a pagefault payload.
func HandleContext ¶
HandleContext serves missing-page userfaultfd events until the context is cancelled or an error occurs.
It reads faulted pages from src using offsets relative to start, stages the bytes in an internal mmap-backed scratch page, and resolves faults with PopulateMove so MOVE is used when the descriptor supports it and COPY is used otherwise.
func Populate ¶
Populate resolves one missing-page range with UFFDIO_COPY.
address must be page aligned and len(data) must be a multiple of the system page size, otherwise it returns ErrInvalidPopulateRange.
func PopulateMove ¶
PopulateMove resolves one missing-page range while allowing UFFDIO_MOVE when the descriptor advertises support for it and the target address falls within a registered range known to this package. Callers must ensure that the source buffer is safe to hand to MOVE, which clears the source PTE so later access faults in zero-filled memory again within the same anonymous mapping.
address must be page aligned and len(data) must be a multiple of the system page size, otherwise it returns ErrInvalidPopulateRange.
func ReceiveFDs ¶
ReceiveFDs receives num file descriptors via SCM_RIGHTS on conn.
If num is zero or negative it returns an empty slice and no error.
func SendFDs ¶
SendFDs sends the supplied file descriptors over conn using SCM_RIGHTS.
If fds is empty it returns nil without writing to the socket.
Types ¶
type Fault ¶
type Fault struct {
// Address is the memory address at which the fault occured.
Address uintptr
}
Fault describes a missing-page event delivered by userfaultfd.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler serves missing-page events and delegates page population to a callback.
func NewHandler ¶
func NewHandler(uffd UFFD, opts *HandlerOptions) *Handler
NewHandler creates a reusable fault handler for the given userfaultfd.
When opts is nil it uses a 100ms poll timeout and keeps the serving goroutine locked to its OS thread, which is the safest default for low-level fault handling code.
func (*Handler) Serve ¶
Serve processes userfaultfd missing-page events until the context is cancelled or an error occurs.
Each missing-page event is decoded into a Fault and passed to onFault along with a Resolver tied to the handler's descriptor. If onFault returns an error, Serve stops immediately and returns it.
type HandlerOptions ¶
HandlerOptions configures a generic fault handler.
By default, NewHandler polls every 100ms and locks the goroutine to its OS thread while serving faults. DisableLockOSThread turns that behaviour off.
type MoveBuffer ¶
type MoveBuffer []byte
MoveBuffer is a mmap-backed buffer that is safe to use with PopulateMove. Call Close when the buffer is no longer needed.
func AllocateMoveBuffer ¶
func AllocateMoveBuffer(length int) (MoveBuffer, error)
AllocateMoveBuffer returns a mmap-backed buffer with a length rounded up to the system page size so it can be used directly with PopulateMove.
func (MoveBuffer) Bytes ¶
func (b MoveBuffer) Bytes() []byte
Bytes returns the underlying page-aligned buffer.
type Registration ¶
type Registration struct {
// contains filtered or unexported fields
}
Registration owns an mmap-backed region registered with a userfaultfd and the descriptor that tracks it. Call Close when the registration is no longer needed.
func Register ¶
func Register(length int) (*Registration, error)
Register allocates an anonymous mapping of length bytes, opens and initialises a userfaultfd with UFFD_OPEN_DEFAULT, and registers the mapping for missing-page tracking.
The returned Registration owns both the descriptor and the full underlying mapping. Registration.Bytes() is clipped to the requested length, while the underlying mapping is rounded up to the system page size. Registration.Start() is the base address passed to fault handlers when converting fault offsets back into reader offsets.
func RegisterWithFlags ¶
func RegisterWithFlags(length int, flags uintptr) (*Registration, error)
RegisterWithFlags is like Register, but opens the underlying userfaultfd with the supplied flags before initialising and registering it.
This is useful when callers want the convenience registration flow but still need to opt into descriptor flags such as UFFD_USER_MODE_ONLY explicitly.
func (*Registration) Bytes ¶
func (r *Registration) Bytes() []byte
Bytes returns the registered region clipped to the originally requested length.
func (*Registration) Close ¶
func (r *Registration) Close() error
Close releases both the userfaultfd and the underlying mapping. It is safe to call Close on a nil or already-closed Registration.
func (*Registration) Start ¶
func (r *Registration) Start() uintptr
Start returns the base address used to translate fault offsets back into reader offsets.
func (*Registration) UFFD ¶
func (r *Registration) UFFD() UFFD
UFFD returns the userfaultfd associated with the registration.
type Resolver ¶
type Resolver struct {
// contains filtered or unexported fields
}
Resolver resolves faults by populating pages in the registered region.
func (Resolver) Populate ¶
Populate resolves one missing-page range with UFFDIO_COPY.
This is the Resolver form of Populate and inherits the same alignment requirements and error semantics.
func (Resolver) PopulateMove ¶
PopulateMove resolves one missing-page range while allowing UFFDIO_MOVE when the descriptor advertises support for it and the target address falls within a registered range known to this package. Callers must ensure that the source buffer is safe to hand to MOVE.
This is the Resolver form of PopulateMove and inherits the same alignment requirements and fallback behaviour.
type UFFD ¶
type UFFD uintptr
UFFD is a raw userfaultfd file descriptor.
The exported methods on UFFD wrap the kernel ioctls needed to initialise the descriptor, register memory ranges, and close the fd when it is no longer needed.
func Open ¶
Open creates a userfaultfd descriptor using the supplied flags.
It prefers the userfaultfd syscall, retries without UFFD_USER_MODE_ONLY when an older kernel rejects that flag, and falls back to /dev/userfaultfd when the syscall path is blocked with EPERM.
func ReceiveUFFD ¶
ReceiveUFFD receives a userfaultfd and its associated start address from a Unix domain socket.
In addition to the fd itself, it restores cached feature and registered-range metadata sent by SendUFFD so the receiving process can make the same PopulateMove decisions as the sender.
func (UFFD) Close ¶
Close closes the userfaultfd descriptor and discards any cached capability information associated with it.
func (UFFD) Init ¶
Init negotiates the userfaultfd API version and the requested feature bits.
On success, Init caches the feature set accepted by the kernel so later calls to PopulateMove and the convenience handlers can decide whether MOVE is safe for this descriptor.
type UffdMsg ¶
UffdMsg mirrors Linux struct uffd_msg and carries events read from a userfaultfd descriptor.
type UffdPagefault ¶
UffdPagefault mirrors the pagefault payload stored in UffdMsg.Arg for UFFD_EVENT_PAGEFAULT events.
type UffdioAPI ¶
UffdioAPI mirrors Linux struct uffdio_api, used with UFFDIO_API to negotiate feature bits and discover supported ioctls.
func NewUffdioAPI ¶
NewUffdioAPI builds a UFFDIO_API request struct for callers using raw userfaultfd ioctls directly.
type UffdioCopy ¶
UffdioCopy mirrors Linux struct uffdio_copy, used with UFFDIO_COPY to resolve missing pages from a source buffer.
func NewUffdioCopy ¶
NewUffdioCopy builds a UFFDIO_COPY request struct using b as the source buffer and address as the destination address in the registered range.
type UffdioMove ¶
UffdioMove mirrors Linux struct uffdio_move, used with UFFDIO_MOVE to move page contents into a registered range.
func NewUffdioMove ¶
NewUffdioMove builds a UFFDIO_MOVE request struct using b as the source buffer and address as the destination address in the registered range.
type UffdioRange ¶
UffdioRange mirrors Linux struct uffdio_range and identifies a virtual address range in a process.
type UffdioRegister ¶
type UffdioRegister struct {
Range UffdioRange
Mode uint64
Ioctls uint64
}
UffdioRegister mirrors Linux struct uffdio_register, used with UFFDIO_REGISTER to register ranges for fault tracking.
func NewUffdioRegister ¶
func NewUffdioRegister(start, length, mode uint64) UffdioRegister
NewUffdioRegister builds a UFFDIO_REGISTER request struct covering the range [start, start+length] with the supplied mode bits.