Documentation
¶
Index ¶
- Constants
- Variables
- func BaselineEnvAllowlist() []string
- func CanonicalPath(path string) (string, error)
- func CloseRuleFiles(files []*os.File)
- func ContainsPort(ports []uint16, port uint16) bool
- func EntryPrecedence(entry FSEntry) int
- func FileIdentity(path string) (string, error)
- func GlobRegexp(glob string) *regexp.Regexp
- func GlobToRegexp(glob string) string
- func IsAccessRestricted(entries []FSEntry, access FSAccess) bool
- func LiteralMatches(entryPath, target string, exact bool) bool
- func MatchingPathHandleAncestor(handles []*PathHandle, path string, exact bool) int
- func MatchingPathHandleIdentityAncestor(handles []*PathHandle, path string) int
- func MetadataDenyCIDRs() []string
- func PathUnder(parent, path string) bool
- func RealHome() (string, error)
- func RevalidatePathBinding(binding *PathBinding, target string) error
- func SamePathHandleIdentity(left, right *PathHandle) bool
- func ValidateLandlockExactPaths(entries []FSEntry, handles []*PathHandle) error
- type CompiledFS
- type Effective
- type EnvPolicy
- type FSAccess
- type FSAllow
- type FSDeny
- type FSEntry
- type FSRule
- type Limits
- type NetPolicy
- type PathBinding
- type PathHandle
- func (handle *PathHandle) Access() FSAccess
- func (handle *PathHandle) Close() error
- func (handle *PathHandle) Exact() bool
- func (handle *PathHandle) File() *os.File
- func (handle *PathHandle) IsDir() bool
- func (handle *PathHandle) NativeHandle() uintptr
- func (handle *PathHandle) SetAccess(access FSAccess)
- func (handle *PathHandle) Target() string
- type PathHandleSet
- type PinnedPathResolution
- type PinnedPathResolver
Constants ¶
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.
const AllAccess = ReadAccess | ExecAccess | WriteAccess
const GlobMeta = "*?["
GlobMeta are the glob metacharacters whose presence makes an entry a glob rather than a literal path.
const (
NullDevicePath = "/dev/null"
)
Variables ¶
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 CloseRuleFiles ¶
func ContainsPort ¶
func EntryPrecedence ¶
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 GlobRegexp ¶
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 ¶
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 LiteralMatches ¶
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 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 ¶
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
}
type FSAccess ¶
type FSAccess uint8
const DenyAccess FSAccess = 0
func NormalizedDenied ¶
func ResolveFS ¶
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 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 PathBinding ¶
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 ¶
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.