secureopen

package
v0.172.11 Latest Latest
Warning

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

Go to latest
Published: Sep 29, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package secureopen is the seam every fd-relative, symlink-refusing directory open in this repository goes through: opening the filesystem root, creating-or-opening one already-validated path segment under an already-open parent directory descriptor, and the Fstatat probe that turns a plain "open failed" into a specific "refusing symlinked directory" error. Real, the production implementation, is exactly the three syscalls (Open, Mkdirat, Openat, Fstatat) internal/worktrees' openAbsoluteDirectoryNoFollow and openPrivateChild used inline before this package existed: same flags (O_NOFOLLOW|O_DIRECTORY), same create-tolerates-EEXIST handling, same symlink probe. Callers keep their own loop structure, create-vs-must-exist branching and error-wrapping text unchanged -- behaviour with Real is byte-for-byte what it was before this package existed.

Fault injection is never a package-level variable: every helper takes an explicit Opener argument, defaulted to Real{} by the one production call site in each caller, so tests using different Fakes race nothing and stay safe under t.Parallel(). Fake implements internal/testsweep.Failer (CallCount/FailCall), so internal/testsweep.Sweep can drive a happy-path body once per call it makes to cover every error return a multi-call sequence reaches, matching internal/runner/runnertest.Fake and internal/filewrite's Injector, the two existing seams this one follows. Fake.Hook goes one step further than a plain injected error: it runs arbitrary code immediately before one chosen call's real syscall, so a test can create a genuine TOCTOU race -- swap a directory for a symlink, or replace it with a different directory, between an earlier check and this call -- and the real syscall that follows observes the real condition instead of a simulated one.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Fake

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

Fake is a scriptable Opener that otherwise delegates to Real, so a successful call still performs the real syscall and hands back a real, usable descriptor. Build one with NewFake, arrange FailCall and/or Hook, then pass it where production code takes an Opener.

Fake counts OpenRoot, Mkdir, OpenDir and IsSymlink together, in the order it answers them, the same "every call this type answers, combined" convention internal/runner/runnertest.Fake uses for Run/Start/Detach/ Interactive.

func NewFake

func NewFake() *Fake

NewFake returns a Fake that delegates every call to Real until FailCall or Hook is armed.

func (*Fake) CallCount

func (f *Fake) CallCount() int

CallCount reports how many calls the Fake has answered so far, across OpenRoot, Mkdir, OpenDir and IsSymlink combined. It implements internal/testsweep.Failer.

func (*Fake) FailCall

func (f *Fake) FailCall(callNum int, err error)

FailCall arranges for the callNum'th call (1-indexed, counting OpenRoot, Mkdir, OpenDir and IsSymlink together in the order the Fake answers them) to fail with err instead of performing its real syscall; every other call keeps delegating to Real. IsSymlink has no error to return, so a failed IsSymlink call reports false -- its documented behaviour for "the probe itself did not work". A callNum of 0 disables the override. It implements internal/testsweep.Failer.

func (*Fake) Hook

func (f *Fake) Hook(callNum int, fn func())

Hook arranges for fn to run once, immediately before the callNum'th call performs its real syscall -- letting a test create a genuine race (swap a directory for a symlink, replace it with a different directory, remove it) that the real syscall which follows then observes for real, instead of a simulated failure. It works standalone or alongside FailCall, which may target the same or a different call number; when both target the same call, Hook runs first and the call still fails with FailCall's error rather than reaching the real syscall.

func (f *Fake) IsSymlink(parentFD int, name string) bool

IsSymlink implements Opener.

func (*Fake) Mkdir

func (f *Fake) Mkdir(parentFD int, name string) error

Mkdir implements Opener.

func (*Fake) OpenDir

func (f *Fake) OpenDir(parentFD int, name string) (int, error)

OpenDir implements Opener.

func (*Fake) OpenRoot

func (f *Fake) OpenRoot(root string) (int, error)

OpenRoot implements Opener.

type Opener

type Opener interface {
	// OpenRoot opens root read-only, O_DIRECTORY|O_NOFOLLOW.
	OpenRoot(root string) (fd int, err error)
	// Mkdir creates name under parentFD, mode 0o755. It returns the
	// syscall's own error, including unix.EEXIST -- callers decide
	// whether EEXIST is tolerated.
	Mkdir(parentFD int, name string) error
	// OpenDir opens name under parentFD, requiring it to already exist:
	// O_RDONLY|O_DIRECTORY|O_NOFOLLOW.
	OpenDir(parentFD int, name string) (fd int, err error)
	// IsSymlink reports whether name under parentFD is a symlink. Callers
	// use it only after OpenDir has already failed, to turn a generic
	// open error into a specific "refusing symlinked directory" one; a
	// probe failure (the entry is gone, or worse) reports false, so the
	// caller falls back to its generic error, exactly as before this
	// package existed.
	IsSymlink(parentFD int, name string) bool
}

Opener is the fd-relative directory-open primitive. Real is the production implementation; a test builds a Fake instead.

type Real

type Real struct{}

Real is the production Opener: exactly today's syscalls, nothing else.

func (Real) IsSymlink(parentFD int, name string) bool

IsSymlink implements Opener.

func (Real) Mkdir

func (Real) Mkdir(parentFD int, name string) error

Mkdir implements Opener.

func (Real) OpenDir

func (Real) OpenDir(parentFD int, name string) (int, error)

OpenDir implements Opener.

func (Real) OpenRoot

func (Real) OpenRoot(root string) (int, error)

OpenRoot implements Opener.

Jump to

Keyboard shortcuts

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