policy

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ReservedSpecFD         = 3
	FirstPathHandleChildFD = ReservedSpecFD + 1
)

ReservedSpecFD is fd 3, on which the Linux re-exec parent passes the sealed stage-2 spec to its child. FirstPathHandleChildFD is the first descriptor a grant path handle may occupy, one above it: stdio holds 0-2 and the spec holds 3. Both live next to FSRule compilation so descriptor collision is impossible even though this pure compiler is also built on non-Linux hosts, and so the Linux stage-2 entry point and the rule enumerator cannot drift.

View Source
const GlobMeta = "*?["

GlobMeta are the glob metacharacters whose presence makes an entry a glob rather than a literal path.

View Source
const (
	NullDevicePath = "/dev/null"
)

Variables

View Source
var (
	// ErrMalformed reports a grant binding that is structurally invalid.
	ErrMalformed = errors.New("sandbox: grant token malformed")
	// ErrTargetChanged reports that a granted filesystem target was replaced
	// between the grant being issued and the spawn being prepared.
	ErrTargetChanged = errors.New("sandbox: granted filesystem target changed")
	// ErrUnsupportedClass reports a grant whose class cannot be enforced by the
	// compiled policy — for example an exact path Landlock cannot express.
	ErrUnsupportedClass = errors.New("sandbox: grant class unsupported")
)

These sentinels are raised while compiling or re-validating a policy that a grant has widened, so they must be defined at this layer rather than in the grant package that sits above it. The grant package re-exports each one under its ErrGrant* name, so a single value satisfies errors.Is on both sides.

Functions

func BaselineEnvAllowlist

func BaselineEnvAllowlist() []string

func CanonicalPath

func CanonicalPath(path string) (string, error)

func CloseRuleFiles

func CloseRuleFiles(files []*os.File)

func ContainsPort

func ContainsPort(ports []uint16, port uint16) bool

func EntryPrecedence

func EntryPrecedence(entry FSEntry) int

EntryPrecedence refines lexical specificity with scope shape. An exact path controls only one object and therefore outranks a recursive tree rooted at the same spelling, without opening any child of that tree.

func FileIdentity

func FileIdentity(path string) (string, error)

func GlobRegexp

func GlobRegexp(glob string) *regexp.Regexp

GlobRegexp compiles a glob pattern into an anchored regexp implementing the §5.1 glob semantics: "**" crosses directory separators, "*" and "?" stay within a single segment, and all other characters are matched literally. It returns nil if the pattern cannot be compiled (a malformed bracket expression). The nil is not itself a match verdict: callers decide the fail-closed direction — denyMatches treats nil as a match (over-deny), while entryMatches treats nil as a non-match (under-grant on the allow side).

func GlobToRegexp

func GlobToRegexp(glob string) string

GlobToRegexp translates a glob into an anchored regexp source string. filepath.Match has no "**", so the translation is done by hand: "**" -> ".*", "*" and "?" stay within the current platform's path separator, bracket expressions are emitted from the canonical rune representation (with a leading "!" negation rewritten to regexp "^"), and every literal rune is escaped via regexp.QuoteMeta so metacharacters such as "." match literally.

func IsAccessRestricted

func IsAccessRestricted(entries []FSEntry, access FSAccess) bool

func LiteralMatches

func LiteralMatches(entryPath, target string, exact bool) bool

LiteralMatches reports whether target is entryPath or is nested under it at a path boundary, so "/work/repo" matches "/work/repo" and "/work/repo/src" but not "/work/repository". A platform volume root matches everything on that volume.

func MatchingPathHandleAncestor

func MatchingPathHandleAncestor(handles []*PathHandle, path string, exact bool) int

MatchingPathHandleAncestor returns the longest identity-pinned handle that can resolve path. Exact-file handles match only their exact target; directory handles match their target and descendants. Equal targets retain scope-shape compatibility so an exact directory rule cannot silently become a tree.

func MatchingPathHandleIdentityAncestor

func MatchingPathHandleIdentityAncestor(handles []*PathHandle, path string) int

func MetadataDenyCIDRs

func MetadataDenyCIDRs() []string

func PathUnder

func PathUnder(parent, path string) bool

func RealHome

func RealHome() (string, error)

func RevalidatePathBinding

func RevalidatePathBinding(binding *PathBinding, target string) error

func SamePathHandleIdentity

func SamePathHandleIdentity(left, right *PathHandle) bool

SamePathHandleIdentity reports whether two independently opened handles pin the same canonical target and complete platform identity.

func ValidateLandlockExactPaths

func ValidateLandlockExactPaths(entries []FSEntry, handles []*PathHandle) error

Types

type CompiledFS

type CompiledFS struct {
	Allows []FSAllow
	Denies []FSDeny
}

func CompileFS

func CompileFS(entries []FSEntry) CompiledFS

func CompileFSWithPathHandles

func CompileFSWithPathHandles(entries []FSEntry, handles []*PathHandle) CompiledFS

func (CompiledFS) HasCarveout

func (compiled CompiledFS) HasCarveout() bool

HasCarveout reports whether a writable allow contains a nested write deny.

func (CompiledFS) HasLiteralDeny

func (compiled CompiledFS) HasLiteralDeny() bool

HasLiteralDeny reports whether any literal deny rule survived compilation.

func (CompiledFS) Resolve

func (compiled CompiledFS) Resolve(path string) FSAccess

Resolve reports the access this compiled policy grants at path.

func (CompiledFS) SnapshotAxes

func (compiled CompiledFS) SnapshotAxes() FSAccess

SnapshotAxes reports the access axes for which a recursive allow contains a narrower literal deny. It also includes write when read or execute is denied: granting directory write would permit pathname replacement around the denied axis, so recursive denied scopes derive write denial throughout their subtree. Landlock must enumerate existing unaffected children instead of granting the covering allow root on each returned axis.

type Effective

type Effective struct {
	Workspace        string
	FS               []FSEntry
	RuntimeBaselines []string
	Net              NetPolicy
	Env              EnvPolicy
	Limits           Limits
	Isolation        profile.Isolation
	Home             profile.Home
	// ProjectionRoots contains only configured roots eligible for a Windows
	// restricting-SID ACL projection. Host volumes and runtime baselines are absent.
	ProjectionRoots []string
	// RequiredGuarantees is the immutable public-profile requirement snapshot.
	// Backends use it only for typed mechanism selection errors; achieved bits
	// remain authoritative and are checked independently by the executor.
	RequiredGuarantees uint64
}

func Clone

func Clone(p Effective) Effective

func Compile

func Compile(prof *profile.Profile) (Effective, error)

type EnvPolicy

type EnvPolicy struct {
	Inherit bool
	Allow   []string
	Set     map[string]string
}

type FSAccess

type FSAccess uint8
const (
	ReadAccess FSAccess = 1 << iota
	ExecAccess
	WriteAccess
)
const DenyAccess FSAccess = 0

func NormalizedDenied

func NormalizedDenied(entry FSEntry) FSAccess

func ResolveFS

func ResolveFS(entries []FSEntry, path string) FSAccess

ResolveFS computes the effective FSAccess a policy grants to an absolute target path, applying the SPEC §5.1 precedence model. It is a pure function: it makes no OS or filesystem calls and only reasons over the entries and the path string, so it is a faithful statement of policy intent shared by the OS backends and the ReadGuard adapter.

The model resolves read, execute, and write independently. For each bit, the most-specific matching entry wins; explicit deny wins a true tie. Exact paths outrank trees at the same spelling, so an approved exact object can open without opening children. Glob denies remain hard fail-closed overrides because backend glob masking cannot safely restore narrower descendants. If no entry controls a bit, that bit is denied.

Contract: target must be an absolute, canonical, symlink-resolved path. ResolveFS is purely lexical — it does no symlink resolution and performs only the platform path-key normalization used by literal matches plus filepath.Clean. Windows keys fold case and separators; Unix keys remain byte and separator sensitive. Passing an unresolved path could let a deny be bypassed via a symlink or a case variant on macOS.

type FSAllow

type FSAllow struct {
	Path   string
	Access FSAccess
	Exact  bool
}

type FSDeny

type FSDeny struct {
	Path   string
	Access FSAccess
	Exact  bool
}

type FSEntry

type FSEntry struct {
	Path   string
	Access FSAccess
	Denied FSAccess
	Exact  bool
	// Canonical marks a grant path already resolved and identity-bound by the
	// executor. Backends must not follow it through symlinks again.
	Canonical bool
}

func MinimalRuntimeEntries

func MinimalRuntimeEntries() []FSEntry

type FSRule

type FSRule struct {
	Path           string
	Target         string
	ParentFD       int
	Access         FSAccess
	LandlockAccess uint64
	IsDir          bool
}

func EnumerateFSRules

func EnumerateFSRules(compiled CompiledFS) []FSRule

EnumerateFSRules compiles only path-backed directory rules for callers that cannot retain descriptors. Direct regular-file rules require EnumerateFSRulesWithPathHandles so their checked inode remains bound until stage 2. Other direct filesystem node classes are omitted fail-narrow.

func EnumerateFSRulesWithPathHandles

func EnumerateFSRulesWithPathHandles(compiled CompiledFS, handles []*PathHandle) ([]FSRule, []*os.File, error)

type Limits

type Limits struct {
	MaxPIDs     int
	MaxMemBytes int64
	MaxCPUPct   int
	Disabled    bool
}

type NetPolicy

type NetPolicy struct {
	Loopback  bool
	Private   bool
	Ports     []uint16
	ProxyPort uint16
	DNS       bool
	Open      bool
}

type PathBinding

type PathBinding struct {
	CanonicalPath string
	ExistingPath  string
	Identity      string
}

func CapturePathBinding

func CapturePathBinding(path string) (PathBinding, error)

type PathHandle

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

PathHandle owns the identity-bound descriptor for one exact-file or tree-directory grant between authentication and child confinement setup. Once opened, the underlying descriptor's identity binding never needs re-validation for as long as the handle stays open — a synchronous caller (Executor.RunCommandWithGrants) closes it once its one spawn completes; the asynchronous two-phase caller (PreparedProcess, exec.PrepareProcess/Start) instead retains it across the whole prepare-through-Start-through-process- exit window, closing it only once the eventual process's terminal cleanup runs. Either caller's retention duration is opaque to this type: it simply stays open, and therefore stays valid, until Close.

func AcquirePathHandle

func AcquirePathHandle(binding *PathBinding, target string, exact bool) (*PathHandle, error)

AcquirePathHandle opens an O_PATH descriptor pinned to target's identity at the moment of the call. The returned handle carries no expiry of its own — an O_PATH descriptor remains valid, and its captured identity remains an honest anti-TOCTOU pin, for as long as the caller keeps it open, whether that is the width of one synchronous spawn (Executor.run's Wrap/configure) or the width of an entire asynchronous PreparedProcess/Start/terminal- cleanup lifetime (exec.PrepareProcess): this function has no notion of which.

func (*PathHandle) Access

func (handle *PathHandle) Access() FSAccess

Access reports the filesystem access the grant that pinned this handle asked for. It is read by the executor when it folds a verified grant into the compiled policy.

func (*PathHandle) Close

func (handle *PathHandle) Close() error

func (*PathHandle) Exact

func (handle *PathHandle) Exact() bool

Exact reports whether the handle pins one file rather than a whole tree.

func (*PathHandle) File

func (handle *PathHandle) File() *os.File

File returns the pinned directory or file descriptor this handle holds open. The handle retains ownership; callers must not close the returned file.

func (*PathHandle) IsDir

func (handle *PathHandle) IsDir() bool

IsDir reports whether the pinned target is a directory.

func (*PathHandle) NativeHandle

func (handle *PathHandle) NativeHandle() uintptr

NativeHandle returns the borrowed platform handle while this PathHandle is open. The caller must never close it. A zero result means that this platform has no native handle or that ownership has already been released.

func (*PathHandle) SetAccess

func (handle *PathHandle) SetAccess(access FSAccess)

SetAccess records the filesystem access a verified grant asked for on this handle. The executor calls it once, immediately after acquiring the handle and before the handle joins a PathHandleSet.

func (*PathHandle) Target

func (handle *PathHandle) Target() string

Target reports the canonical path this handle is pinned to.

type PathHandleSet

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

PathHandleSet is the sole owner of every non-nil handle added to it. Equal canonical targets are safe to coalesce only when their opened object identities match. A mismatch closes the incoming handle and every handle the set already owns before returning ErrTargetChanged.

func (*PathHandleSet) Add

func (set *PathHandleSet) Add(handle *PathHandle) error

Add records a handle, merging access when two grants pin the same target and refusing the whole set when their identities disagree.

func (*PathHandleSet) Close

func (set *PathHandleSet) Close()

Close releases every handle the set holds.

func (*PathHandleSet) Sorted

func (set *PathHandleSet) Sorted() []*PathHandle

sorted returns a borrowed canonical-target-ordered view. The set retains sole ownership and closes the handles when its caller's operation finishes. Sorted returns the handles in a deterministic target order.

type PinnedPathResolution

type PinnedPathResolution struct {
	File    *os.File
	ChildFD int
	IsDir   bool
}

PinnedPathResolution is one path resolved through an identity-pinned handle: the open descriptor, the number it will carry in the child, and whether it is a directory.

type PinnedPathResolver

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

PinnedPathResolver is constructed fresh for each spawn wrap (see linuxWrapTransform/linuxWrap in internal/linux/backend.go) from the caller's still-open handles slice; it never outlives that one Wrap call, regardless of whether the handles it resolves against belong to a synchronous spawn or to an asynchronous PreparedProcess/Start whose own handles are retained for the whole process lifetime by the caller — this type itself holds nothing beyond one wrap's resolution.

func NewPinnedPathResolver

func NewPinnedPathResolver(handles []*PathHandle, firstFD int) *PinnedPathResolver

func (*PinnedPathResolver) Files

func (resolver *PinnedPathResolver) Files() []*os.File

Files returns the descriptors the resolver opened while enumerating rules. The caller takes responsibility for closing them via CloseRuleFiles.

func (*PinnedPathResolver) ResolveAny

func (resolver *PinnedPathResolver) ResolveAny(target string) (PinnedPathResolution, bool, error)

ResolveAny resolves target against any pinned handle, exact or tree.

Jump to

Keyboard shortcuts

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