openexec

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Index

Constants

View Source
const (
	PROG_TYPE_LSM_OPEN   = "file_open"
	PROG_TYPE_LSM_EXEC   = "bprm_check_security"
	PROG_TYPE_TRACE_OPEN = "security_file_open"
	PROG_TYPE_TRACE_EXEC = "security_bprm_check"
)

Variables

View Source
var ErrBPFFSNotMounted = errors.New("bpffs is not mounted at /sys/fs/bpf on this node; mount it (mount -t bpf bpf /sys/fs/bpf) and restart the daemon")

ErrBPFFSNotMounted means the pin directory's parent is not a bpffs mount, so nothing can be pinned and no open or exec hook can be attached.

View Source
var ErrObservationUnavailable = errors.New("lsm: observation maps unavailable")

ErrObservationUnavailable reports that the loaded collection carries no events_map hash-of-maps, so per-cgid path counting cannot be turned on.

View Source
var ErrRunStatsUnavailable = errors.New("bpf run statistics unavailable")

ErrRunStatsUnavailable means the kernel cannot count program runs here (Linux < 5.8, or missing CAP_SYS_ADMIN), so execution cannot be verified.

ProgTypes maps each attach target to the PROG_TYPE_* value the kernel programs write into policy_ctx.prog_type to pick the entries map, so these values match _cprog/maps.h and cannot be changed on one side alone.

Functions

func CheckPinFS added in v0.1.3

func CheckPinFS() error

CheckPinFS returns ErrBPFFSNotMounted unless the pin directory's parent is a bpffs mount.

func ClearPins

func ClearPins() error

ClearPins wipes the pin directory at startup. The pinned maps outlive the process, so a restart would otherwise inherit prog arrays holding fds of programs this process never loaded.

func EnableRunStats added in v0.1.3

func EnableRunStats() (io.Closer, error)

EnableRunStats turns on run accounting for every loaded BPF program until the returned closer is called. Accounting costs a timestamp per program run, so callers keep it on only around verification.

func PathKeys

func PathKeys(values []string, allow bool) (keys []*runtimePolicyEntry, star bool, rejected []compiler.RejectedTarget)

PathKeys turns the accepted values of one allow or deny list into policy map entries: each path's bytes NUL-padded to the width the kernel side declares, exactly as bpf_probe_read_kernel_str leaves it. A directory prefix keys the same width under its own discriminant, keeping the trailing separator the kernel's ancestor walk produces. compiler.StarTarget yields no entry; it sets star, the default-deny sentinel SetDefaultDeny carries.

Types

type Dispatcher

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

A Dispatcher owns one hook: it is the only program attached to the kernel, and it tail-calls the executor that evaluates its entries map. Every policy of the hook writes into that one map under its own slot bit; the dispatcher hands out the slots and stays for the process lifetime. Callers serialize access (OpenExecManager holds its lock across every PolicyMap call), which is what makes the read-modify-write of a shared entry safe.

func NewDispatcherForTarget

func NewDispatcherForTarget(target string) (*Dispatcher, error)

func (*Dispatcher) AddPolicy

func (d *Dispatcher) AddPolicy() (uint32, error)

AddPolicy reserves the lowest free policy slot of this hook and returns it.

func (*Dispatcher) Attach

func (d *Dispatcher) Attach() error

Attach links the dispatcher's program to its hook. The tracepoint exec target carries no program: the file_open dispatcher is the one attached there, so linking again would run the handler twice per open.

func (*Dispatcher) Canary added in v0.1.3

func (d *Dispatcher) Canary() func() error

Canary returns an action that passes through this dispatcher's hook and changes nothing on the node. The target defaults to the running binary; tests point canaryTarget at a fixture instead of the real procfs.

func (*Dispatcher) Close added in v0.1.3

func (d *Dispatcher) Close() error

Close detaches the dispatcher and releases every object it loaded. The maps stay pinned on bpffs until ClearPins, so a caller replacing this dispatcher with one of the other hook type clears the pins in between. A handle whose close fails is kept, so the dispatcher still owns it and a retry of Close can release it; only what was released is forgotten.

func (*Dispatcher) Executed added in v0.1.3

func (d *Dispatcher) Executed(trigger func() error) (bool, error)

Executed reports whether the dispatcher's program ran at least once between a run-count read and the completion of trigger. Run statistics must be enabled while it runs, or the counter never moves and a live hook reads as dead. A target that carries no program of its own (the fmod_ret exec target) is covered by the file_open dispatcher and reports true.

The counter is the kernel's per-program total, so it does not say which event caused an increment — and it does not need to. The question is whether the kernel calls this program at all: a ghost attach is never invoked, by anything, so its counter cannot move however busy the node is; a program that ran for some other process's open runs for the workload's too, since it is the same hook. Unrelated traffic can only make a live verdict arrive sooner. The trigger exists so a live program on an idle node is not misread as a ghost for want of any event in the window.

func (*Dispatcher) RemovePolicy added in v0.1.3

func (d *Dispatcher) RemovePolicy(slot uint32) error

type PathEventKey

type PathEventKey struct {
	Path     [maxPathLen]byte
	Decision uint32
}

PathEventKey identifies one observation counter: a path (or exec filename) plus the enforcement decision the kernel program applied to the operation. It mirrors `struct path_event_key` in _cprog/maps.h byte for byte — it is the map key cilium/ebpf marshals directly, and a layout drift from the BTF key is rejected at runtime.

func (PathEventKey) PathString

func (k PathEventKey) PathString() string

PathString returns the path without the NUL padding the kernel key carries.

type PolicyMap

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

A PolicyMap is one policy's view of its hook's shared entries map: every key it programs (allow/deny paths, cgids, flags) carries this policy's slot bit in the entry's value, alongside the bits of any other policy holding the same key.

func NewPolicyMap

func NewPolicyMap(d *Dispatcher, logger *logr.Logger) (*PolicyMap, error)

func (*PolicyMap) AddCgids

func (l *PolicyMap) AddCgids(cgids []uint64) error

func (*PolicyMap) AddTargets

func (l *PolicyMap) AddTargets(paths *compiler.AllowDenyPair) ([]compiler.RejectedTarget, error)

AddTargets programs a policy's paths into its entries map and returns every value PathKeys could not key.

func (*PolicyMap) Close

func (m *PolicyMap) Close() error

Close withdraws the policy from the kernel: cgids first, so the policy stops selecting anything before its rules go, then every other key it set.

func (*PolicyMap) DeleteCgids

func (l *PolicyMap) DeleteCgids(cgids []uint64) error

func (*PolicyMap) DeleteTargets

func (l *PolicyMap) DeleteTargets(paths *compiler.AllowDenyPair) ([]compiler.RejectedTarget, error)

DeleteTargets removes what AddTargets programmed for the same pair. Both derive their keys from PathKeys, so a value one of them can key is a value the other can key too.

func (*PolicyMap) SetDefaultDeny

func (l *PolicyMap) SetDefaultDeny(val bool) error

type Prog

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

A Prog is the policy executor for one attach target: the single program the dispatcher tail-calls, which evaluates the hook's entries map, plus the observation maps it records into.

func NewProgram

func NewProgram(d *Dispatcher) (*Prog, error)

func (*Prog) Close added in v0.1.3

func (p *Prog) Close() error

Close releases the inner observation maps this program created and every object its collection loaded. The dispatcher's prog array still holds the executor until the dispatcher itself is closed and the pins are cleared, so callers close the dispatcher afterwards. Handles whose close fails are kept.

func (*Prog) DisableObservation

func (l *Prog) DisableObservation(cgids []uint64) error

DisableObservation removes the events_map entry for each cgid and releases the inner map. A cgid that was never enabled is not an error.

func (*Prog) EnableObservation

func (l *Prog) EnableObservation(cgids []uint64) error

EnableObservation creates (or reuses) an inner hash map in events_map for each cgid so the kernel program starts recording path counts for it.

func (*Prog) ReadEvents

func (l *Prog) ReadEvents() (map[uint64]map[PathEventKey]uint32, error)

ReadEvents reads and resets the path counts of every observed cgid, through the long-lived inner-map handles EnableObservation created. Every cgid is visited even when one of them fails, so a single bad map cannot hide the counts of the rest.

func (*Prog) ReadEventsLost

func (l *Prog) ReadEventsLost() (uint64, error)

ReadEventsLost reports open/exec observations the kernel program could not record because the cgid's count map was full. It shares ReadEvents' single caller, so statLast needs no lock of its own.

Jump to

Keyboard shortcuts

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