carlos / platform Public

authority: retained directory descriptors (plan step 1, Part A): Dir with Child, List, Lookat, Readlink, OpenRegular, Recheck and Walk; Root by the platform walk from a pinned slash with its ancestry; the design's Part A tests; a link under O_DIRECTORY named as one; the walk's grammar refused before any system call

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 5bfcc7ba7d3603d3c101a9b07e9d2b92db4c72ac parent f331b55
5 files changed, +1195 −0
  • internal/authority/authority.go +144 −0
  • internal/authority/authority_other.go +42 −0
  • internal/authority/authority_unix.go +504 −0
  • internal/authority/authority_unix_test.go +485 −0
  • internal/authority/doc.go +20 −0

CI passed — run details

diff --git a/internal/authority/authority.go b/internal/authority/authority.go
new file mode 100644
index 000000000..9ecc9fa99
--- /dev/null
+++ b/internal/authority/authority.go
@@ -0,0 +1,144 @@
+package authority
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+)
+
+// Facts are what fstat says of an entry: enough to recognise it again.
+type Facts struct {
+ Dev, Ino uint64
+ UID uint32
+ Mode uint32 // the file type and permission bits as the kernel has them
+}
+
+// Same reports whether two facts name the same object of the same type.
+func (f Facts) Same(o Facts) bool {
+ return f.Dev == o.Dev && f.Ino == o.Ino && f.Mode&modeTypeMask == o.Mode&modeTypeMask
+}
+
+// Kind is what one look at a name found.
+type Kind int
+
+const (
+ Absent Kind = iota
+ Directory
+ Regular
+ Link
+ Other // a FIFO, a socket, a device
+)
+
+func (k Kind) String() string {
+ return [...]string{"absent", "directory", "regular", "link", "other"}[k]
+}
+
+// Entry is one listed name with its facts.
+type Entry struct {
+ Name string
+ Kind Kind
+ Facts Facts
+}
+
+// The refusals. Each is returned before any system call where the input
+// alone decides it.
+var (
+ ErrBadName = errors.New("authority: not a single name")
+ ErrEmptySpelling = errors.New("authority: an empty spelling")
+ ErrAscentPastRoot = errors.New("authority: \"..\" past the root")
+ ErrAscentAfterName = errors.New("authority: \"..\" after a named component")
+ ErrNotDirectory = errors.New("authority: not a directory")
+ ErrLink = errors.New("authority: a link where a directory is required")
+ ErrNotRegular = errors.New("authority: not the regular file that was looked at")
+ ErrOutside = errors.New("authority: outside every pinned root")
+ ErrNotPlatform = errors.New("authority: a component is not the platform's")
+ ErrChanged = errors.New("authority: the entry changed")
+ ErrClosed = errors.New("authority: closed")
+ ErrUnsupported = errors.New("authority: not supported on this platform")
+)
+
+// EdgeError names the edge (parent name, child name) a refusal is about.
+type EdgeError struct {
+ Name string
+ Err error
+}
+
+func (e *EdgeError) Error() string { return fmt.Sprintf("%s: %v", e.Name, e.Err) }
+func (e *EdgeError) Unwrap() error { return e.Err }
+
+// validName accepts one component: not empty, not "." or "..", no
+// separator, no NUL.
+func validName(name string) error {
+ if name == "" || name == "." || name == ".." || strings.ContainsAny(name, "/\x00") {
+ return ErrBadName
+ }
+ return nil
+}
+
+// platformOK is the platform walk's rule for one component: owned by a
+// platform uid and not writable by group or others.
+func platformOK(f Facts, platform func(uint32) bool) bool {
+ return platform != nil && platform(f.UID) && f.Mode&0o022 == 0
+}
+
+// Pins are what an absolute spelling is walked against: the pinned "/"
+// and the platform roots a walk may enter. Platform decides which uids
+// are the platform's.
+type Pins struct {
+ Slash *Dir
+ Roots []*Root
+ Platform func(uid uint32) bool
+}
+
+func (p *Pins) match(f Facts) *Root {
+ if p == nil {
+ return nil
+ }
+ for _, r := range p.Roots {
+ if r != nil && r.Dir != nil && r.facts.Same(f) {
+ return r
+ }
+ }
+ return nil
+}
+
+// Result is what a Walk found: the kind of the last component, its facts,
+// and, for a directory, a retained Dir for it. Close releases what the
+// walk opened and nothing it was given.
+type Result struct {
+ Kind Kind
+ Facts Facts
+ Dir *Dir
+ owned []*Dir
+}
+
+// Close closes the directories the walk acquired, deepest first.
+func (r *Result) Close() {
+ for i := len(r.owned) - 1; i >= 0; i-- {
+ r.owned[i].Close()
+ }
+ r.owned = nil
+}
+
+// normalise splits a spelling into components, dropping empty and "."
+// components, and reports whether the spelling demands a directory (a
+// trailing separator or a terminal ".").
+func normalise(spelling string) (comps []string, abs, wantDir bool, err error) {
+ if spelling == "" {
+ return nil, false, false, ErrEmptySpelling
+ }
+ if strings.ContainsRune(spelling, 0) {
+ return nil, false, false, ErrBadName
+ }
+ abs = spelling[0] == '/'
+ parts := strings.Split(spelling, "/")
+ last := parts[len(parts)-1]
+ wantDir = last == "" || last == "."
+ for _, p := range parts {
+ if p == "" || p == "." {
+ continue
+ }
+ comps = append(comps, p)
+ }
+ return comps, abs, wantDir, nil
+}
diff --git a/internal/authority/authority_other.go b/internal/authority/authority_other.go
new file mode 100644
index 000000000..9721d022d
--- /dev/null
+++ b/internal/authority/authority_other.go
@@ -0,0 +1,42 @@
+//go:build !unix
+
+package authority
+
+import "os"
+
+const modeTypeMask = 0o170000
+
+// Dir on a platform without openat: the replicator does not run here;
+// every operation is ErrUnsupported.
+type Dir struct {
+ facts Facts
+ name string
+ parent *Dir
+ root bool
+}
+
+func Open(string) (*Dir, error) { return nil, ErrUnsupported }
+func (d *Dir) Facts() Facts { return d.facts }
+func (d *Dir) Name() string { return d.name }
+func (d *Dir) Parent() *Dir { return d.parent }
+func (d *Dir) Depth() int { return 0 }
+func (d *Dir) Close() error { return nil }
+func (d *Dir) Child(string, *Facts) (*Dir, error) { return nil, ErrUnsupported }
+func (d *Dir) List() ([]Entry, error) { return nil, ErrUnsupported }
+func (d *Dir) Lookat(string) (Kind, Facts, error) { return Absent, Facts{}, ErrUnsupported }
+func (d *Dir) Readlink(string) (string, error) { return "", ErrUnsupported }
+func (d *Dir) OpenRegular(string, Facts) (*os.File, error) { return nil, ErrUnsupported }
+func (d *Dir) Recheck() error { return ErrUnsupported }
+func (d *Dir) Walk(string, *Pins) (Result, error) { return Result{}, ErrUnsupported }
+
+// Root on a platform without openat.
+type Root struct {
+ *Dir
+ Path string
+ facts Facts
+}
+
+func OpenRoot(*Dir, string, func(uint32) bool) (*Root, error) { return nil, ErrUnsupported }
+func (r *Root) Ancestry() []Facts { return nil }
+func (r *Root) AncestryChanged() (bool, error) { return true, ErrUnsupported }
+func (r *Root) Close() error { return nil }
diff --git a/internal/authority/authority_unix.go b/internal/authority/authority_unix.go
new file mode 100644
index 000000000..69cb85e7a
--- /dev/null
+++ b/internal/authority/authority_unix.go
@@ -0,0 +1,504 @@
+//go:build unix
+
+package authority
+
+import (
+ "errors"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+
+ "golang.org/x/sys/unix"
+)
+
+const modeTypeMask = unix.S_IFMT
+
+const dirFlags = unix.O_DIRECTORY | unix.O_NOFOLLOW | unix.O_RDONLY | unix.O_CLOEXEC | unix.O_NOCTTY
+
+// Dir is a retained directory descriptor.
+type Dir struct {
+ fd int
+ name string // the name it was acquired by from parent; "" for a start
+ parent *Dir
+ facts Facts
+ root bool // a Root: the top of a stack a Walk may not pop past
+ closed bool
+}
+
+func factsOf(st *unix.Stat_t) Facts {
+ return Facts{Dev: uint64(st.Dev), Ino: uint64(st.Ino), UID: st.Uid, Mode: uint32(st.Mode)}
+}
+
+func kindOf(mode uint32) Kind {
+ switch mode & unix.S_IFMT {
+ case unix.S_IFDIR:
+ return Directory
+ case unix.S_IFREG:
+ return Regular
+ case unix.S_IFLNK:
+ return Link
+ }
+ return Other
+}
+
+// Open opens a directory by pathname, following whatever the path
+// contains. It claims no authority: it is for the pinned "/" and for tests.
+func Open(path string) (*Dir, error) {
+ fd, err := unix.Open(path, unix.O_DIRECTORY|unix.O_RDONLY|unix.O_CLOEXEC|unix.O_NOCTTY, 0)
+ if err != nil {
+ return nil, &os.PathError{Op: "open", Path: path, Err: err}
+ }
+ var st unix.Stat_t
+ if err := unix.Fstat(fd, &st); err != nil {
+ unix.Close(fd)
+ return nil, &os.PathError{Op: "fstat", Path: path, Err: err}
+ }
+ return &Dir{fd: fd, facts: factsOf(&st)}, nil
+}
+
+// Facts returns the facts read when the Dir was acquired.
+func (d *Dir) Facts() Facts { return d.facts }
+
+// Name is the name the Dir was acquired by from its parent.
+func (d *Dir) Name() string { return d.name }
+
+// Parent is the Dir this one was acquired from, or nil.
+func (d *Dir) Parent() *Dir { return d.parent }
+
+// Depth is the number of Dirs above this one on its stack.
+func (d *Dir) Depth() int {
+ n := 0
+ for p := d.parent; p != nil; p = p.parent {
+ n++
+ }
+ return n
+}
+
+// Close closes this descriptor only; the stack above it stays.
+func (d *Dir) Close() error {
+ if d == nil || d.closed {
+ return nil
+ }
+ d.closed = true
+ return unix.Close(d.fd)
+}
+
+func (d *Dir) live() error {
+ if d == nil || d.closed {
+ return ErrClosed
+ }
+ return nil
+}
+
+// Child acquires one named subdirectory: openat with O_DIRECTORY and
+// O_NOFOLLOW (the kernel refuses a link, a FIFO or a device at lookup,
+// before any open effect), then fstat; when expect is given, the opened
+// directory must be the one the facts describe.
+func (d *Dir) Child(name string, expect *Facts) (*Dir, error) {
+ if err := d.live(); err != nil {
+ return nil, err
+ }
+ if err := validName(name); err != nil {
+ return nil, err
+ }
+ fd, err := unix.Openat(d.fd, name, dirFlags, 0)
+ if err != nil {
+ // Linux answers ENOTDIR, not ELOOP, for a link under O_DIRECTORY
+ // with O_NOFOLLOW; one look names it, so a link is never mistaken
+ // for a file. The link is not followed either way.
+ if err == unix.ENOTDIR {
+ if k, _, lerr := d.Lookat(name); lerr == nil && k == Link {
+ return nil, &EdgeError{Name: name, Err: ErrLink}
+ }
+ }
+ return nil, &EdgeError{Name: name, Err: err}
+ }
+ var st unix.Stat_t
+ if err := unix.Fstat(fd, &st); err != nil {
+ unix.Close(fd)
+ return nil, &EdgeError{Name: name, Err: err}
+ }
+ f := factsOf(&st)
+ if expect != nil && !expect.Same(f) {
+ unix.Close(fd)
+ return nil, &EdgeError{Name: name, Err: ErrChanged}
+ }
+ return &Dir{fd: fd, name: name, parent: d, facts: f}, nil
+}
+
+// List reads the directory through a fresh open file description (never a
+// dup, whose shared offset would make a second listing start where the
+// first ended), checked to be this directory, and looks at each entry
+// with fstatat without following links. Entries are sorted by name.
+func (d *Dir) List() ([]Entry, error) {
+ if err := d.live(); err != nil {
+ return nil, err
+ }
+ fd, err := unix.Openat(d.fd, ".", unix.O_DIRECTORY|unix.O_RDONLY|unix.O_CLOEXEC|unix.O_NOCTTY, 0)
+ if err != nil {
+ return nil, &EdgeError{Name: ".", Err: err}
+ }
+ var st unix.Stat_t
+ if err := unix.Fstat(fd, &st); err != nil {
+ unix.Close(fd)
+ return nil, &EdgeError{Name: ".", Err: err}
+ }
+ if !factsOf(&st).Same(d.facts) {
+ unix.Close(fd)
+ return nil, &EdgeError{Name: ".", Err: ErrChanged}
+ }
+ f := os.NewFile(uintptr(fd), ".")
+ names, err := f.Readdirnames(-1)
+ f.Close()
+ if err != nil {
+ return nil, &EdgeError{Name: ".", Err: err}
+ }
+ sort.Strings(names)
+ out := make([]Entry, 0, len(names))
+ for _, n := range names {
+ if n == "." || n == ".." {
+ continue
+ }
+ k, fs, err := d.Lookat(n)
+ if err != nil {
+ return nil, err
+ }
+ if k == Absent {
+ continue // gone between the listing and the look: churn
+ }
+ out = append(out, Entry{Name: n, Kind: k, Facts: fs})
+ }
+ return out, nil
+}
+
+// Lookat is fstatat of one name without following a link: its kind and
+// facts, or Absent with no error when there is nothing by that name.
+func (d *Dir) Lookat(name string) (Kind, Facts, error) {
+ if err := d.live(); err != nil {
+ return Absent, Facts{}, err
+ }
+ if err := validName(name); err != nil {
+ return Absent, Facts{}, err
+ }
+ var st unix.Stat_t
+ if err := unix.Fstatat(d.fd, name, &st, unix.AT_SYMLINK_NOFOLLOW); err != nil {
+ if err == unix.ENOENT {
+ return Absent, Facts{}, nil
+ }
+ return Absent, Facts{}, &EdgeError{Name: name, Err: err}
+ }
+ f := factsOf(&st)
+ return kindOf(f.Mode), f, nil
+}
+
+// Readlink reads one named link relative to the descriptor.
+func (d *Dir) Readlink(name string) (string, error) {
+ if err := d.live(); err != nil {
+ return "", err
+ }
+ if err := validName(name); err != nil {
+ return "", err
+ }
+ buf := make([]byte, 4096)
+ for {
+ n, err := unix.Readlinkat(d.fd, name, buf)
+ if err != nil {
+ return "", &EdgeError{Name: name, Err: err}
+ }
+ if n < len(buf) {
+ return string(buf[:n]), nil
+ }
+ buf = make([]byte, len(buf)*2)
+ }
+}
+
+// OpenRegular opens one named file for reading without following a link,
+// without blocking on a special file and without acquiring a terminal,
+// and requires it to be the regular file that was looked at.
+func (d *Dir) OpenRegular(name string, looked Facts) (*os.File, error) {
+ if err := d.live(); err != nil {
+ return nil, err
+ }
+ if err := validName(name); err != nil {
+ return nil, err
+ }
+ fd, err := unix.Openat(d.fd, name, unix.O_RDONLY|unix.O_NOFOLLOW|unix.O_NONBLOCK|unix.O_NOCTTY|unix.O_CLOEXEC, 0)
+ if err != nil {
+ return nil, &EdgeError{Name: name, Err: err}
+ }
+ var st unix.Stat_t
+ if err := unix.Fstat(fd, &st); err != nil {
+ unix.Close(fd)
+ return nil, &EdgeError{Name: name, Err: err}
+ }
+ f := factsOf(&st)
+ if kindOf(f.Mode) != Regular || f.Dev != looked.Dev || f.Ino != looked.Ino {
+ unix.Close(fd)
+ return nil, &EdgeError{Name: name, Err: ErrNotRegular}
+ }
+ return os.NewFile(uintptr(fd), name), nil
+}
+
+// Recheck looks at every edge of the stack from this Dir up to its top:
+// each child's name in its parent must still be the child's facts. A
+// difference anywhere is a changed edge, named.
+func (d *Dir) Recheck() error {
+ if err := d.live(); err != nil {
+ return err
+ }
+ for c := d; c.parent != nil; c = c.parent {
+ if err := c.parent.live(); err != nil {
+ return err
+ }
+ var st unix.Stat_t
+ if err := unix.Fstatat(c.parent.fd, c.name, &st, unix.AT_SYMLINK_NOFOLLOW); err != nil {
+ return &EdgeError{Name: c.name, Err: err}
+ }
+ if !factsOf(&st).Same(c.facts) {
+ return &EdgeError{Name: c.name, Err: ErrChanged}
+ }
+ }
+ return nil
+}
+
+// Walk classifies a captured link target. A relative spelling is walked
+// from this Dir; an absolute one from the pinned "/" under the platform
+// walk's rules until it enters a pinned root, then beneath that root. A
+// leading run of ".." pops the retained stack and is refused past the
+// root; ".." after a named component is refused. The last component is
+// looked at without following it and its kind returned; a spelling that
+// demands a directory of something else is ErrNotDirectory. A directory
+// result carries a retained Dir, which Close releases if the walk opened
+// it.
+func (d *Dir) Walk(spelling string, pins *Pins) (Result, error) {
+ if err := d.live(); err != nil {
+ return Result{}, err
+ }
+ comps, abs, wantDir, err := normalise(spelling)
+ if err != nil {
+ return Result{}, err
+ }
+ // the grammar first, before any system call: ".." only in a leading
+ // run, and that run no deeper than the stack above the root
+ ups := 0
+ for i, c := range comps {
+ if c != ".." {
+ for _, later := range comps[i:] {
+ if later == ".." {
+ return Result{}, ErrAscentAfterName
+ }
+ }
+ break
+ }
+ ups++
+ }
+ if ups > 0 && abs {
+ return Result{}, ErrAscentPastRoot
+ }
+ for p, n := d, ups; n > 0; n-- {
+ if p.root || p.parent == nil {
+ return Result{}, ErrAscentPastRoot
+ }
+ p = p.parent
+ }
+ cur := d
+ entered := true // a relative walk is already beneath its root
+ if abs {
+ if pins == nil || pins.Slash == nil {
+ return Result{}, ErrOutside
+ }
+ cur = pins.Slash
+ entered = false
+ }
+ res := Result{}
+ fail := func(err error) (Result, error) {
+ res.Close()
+ return Result{}, err
+ }
+ leading := true
+ for i, c := range comps {
+ last := i == len(comps)-1
+ if c == ".." {
+ if !leading {
+ return fail(ErrAscentAfterName)
+ }
+ if abs || cur.root || cur.parent == nil {
+ return fail(ErrAscentPastRoot)
+ }
+ cur = cur.parent
+ continue
+ }
+ leading = false
+ if !entered {
+ child, err := cur.Child(c, nil)
+ if err != nil {
+ return fail(&EdgeError{Name: c, Err: ErrOutside})
+ }
+ if !platformOK(child.facts, pins.Platform) {
+ child.Close()
+ return fail(&EdgeError{Name: c, Err: ErrNotPlatform})
+ }
+ if pin := pins.match(child.facts); pin != nil {
+ child.Close()
+ cur = pin.Dir
+ entered = true
+ } else {
+ res.owned = append(res.owned, child)
+ cur = child
+ }
+ if last {
+ if !entered {
+ return fail(&EdgeError{Name: c, Err: ErrOutside})
+ }
+ res.Kind, res.Facts, res.Dir = Directory, cur.facts, cur
+ return res, nil
+ }
+ continue
+ }
+ if !last {
+ child, err := cur.Child(c, nil)
+ if err != nil {
+ var ee *EdgeError
+ if errors.As(err, &ee) {
+ switch {
+ case errors.Is(ee.Err, unix.ENOENT):
+ res.Close()
+ return Result{Kind: Absent}, nil
+ case errors.Is(ee.Err, ErrLink):
+ res.Close()
+ return Result{Kind: Link}, nil
+ }
+ }
+ return fail(err)
+ }
+ res.owned = append(res.owned, child)
+ cur = child
+ continue
+ }
+ k, f, err := cur.Lookat(c)
+ if err != nil {
+ return fail(err)
+ }
+ if k == Absent {
+ res.Close()
+ return Result{Kind: Absent}, nil
+ }
+ if wantDir && k != Directory {
+ return fail(&EdgeError{Name: c, Err: ErrNotDirectory})
+ }
+ res.Kind, res.Facts = k, f
+ if k == Directory {
+ child, err := cur.Child(c, &f)
+ if err != nil {
+ return fail(err)
+ }
+ res.owned = append(res.owned, child)
+ res.Dir = child
+ }
+ return res, nil
+ }
+ // nothing named: the anchor or the popped directory, as a directory
+ if !entered {
+ return fail(ErrOutside)
+ }
+ res.Kind, res.Facts, res.Dir = Directory, cur.facts, cur
+ return res, nil
+}
+
+// Root is a Dir reached from a pinned "/" by a walk whose every component
+// is the platform's; the facts of that walk are its ancestry.
+type Root struct {
+ *Dir
+ Path string
+ slash *Dir
+ comps []string
+ ancestry []Facts
+ platform func(uint32) bool
+}
+
+// OpenRoot walks path's components from slash, requiring each to be a
+// directory (no link: O_NOFOLLOW), owned by a platform uid and not
+// writable by group or others. The intermediate Dirs are retained as the
+// root's stack. Path is spelled from slash, so "/var/lib/carlos" against
+// the real "/" is that directory, and against a test's "/" it is beneath it.
+func OpenRoot(slash *Dir, path string, platform func(uint32) bool) (*Root, error) {
+ if err := slash.live(); err != nil {
+ return nil, err
+ }
+ if !platformOK(slash.facts, platform) {
+ return nil, &EdgeError{Name: "/", Err: ErrNotPlatform}
+ }
+ var comps []string
+ for _, c := range strings.Split(filepath.Clean("/"+path), "/") {
+ if c != "" {
+ comps = append(comps, c)
+ }
+ }
+ cur := slash
+ var ancestry []Facts
+ var opened []*Dir
+ fail := func(err error) (*Root, error) {
+ for i := len(opened) - 1; i >= 0; i-- {
+ opened[i].Close()
+ }
+ return nil, err
+ }
+ for _, c := range comps {
+ child, err := cur.Child(c, nil)
+ if err != nil {
+ return fail(err)
+ }
+ if !platformOK(child.facts, platform) {
+ child.Close()
+ return fail(&EdgeError{Name: c, Err: ErrNotPlatform})
+ }
+ opened = append(opened, child)
+ ancestry = append(ancestry, child.facts)
+ cur = child
+ }
+ cur.root = true
+ return &Root{Dir: cur, Path: path, slash: slash, comps: comps, ancestry: ancestry, platform: platform}, nil
+}
+
+// Ancestry is the facts of each component of the root's walk, top down.
+func (r *Root) Ancestry() []Facts { return append([]Facts(nil), r.ancestry...) }
+
+// AncestryChanged walks the path again from the pinned "/" and reports
+// whether any component differs from the retained ancestry, or the walk
+// fails the platform rule now.
+func (r *Root) AncestryChanged() (bool, error) {
+ cur := r.slash
+ var opened []*Dir
+ defer func() {
+ for i := len(opened) - 1; i >= 0; i-- {
+ opened[i].Close()
+ }
+ }()
+ for i, c := range r.comps {
+ child, err := cur.Child(c, nil)
+ if err != nil {
+ return true, err
+ }
+ opened = append(opened, child)
+ if !platformOK(child.facts, r.platform) {
+ return true, &EdgeError{Name: c, Err: ErrNotPlatform}
+ }
+ if !child.facts.Same(r.ancestry[i]) {
+ return true, nil
+ }
+ cur = child
+ }
+ return false, nil
+}
+
+// Close closes the root and every intermediate Dir of its walk, not slash.
+func (r *Root) Close() error {
+ var first error
+ for c := r.Dir; c != nil && c != r.slash; c = c.parent {
+ if err := c.Close(); err != nil && first == nil {
+ first = err
+ }
+ }
+ return first
+}
diff --git a/internal/authority/authority_unix_test.go b/internal/authority/authority_unix_test.go
new file mode 100644
index 000000000..8ac1d8ef3
--- /dev/null
+++ b/internal/authority/authority_unix_test.go
@@ -0,0 +1,485 @@
+//go:build unix
+
+package authority
+
+import (
+ "errors"
+ "os"
+ "path/filepath"
+ "testing"
+ "time"
+
+ "golang.org/x/sys/unix"
+)
+
+func me(uid uint32) bool { return uid == uint32(os.Geteuid()) }
+
+// tempDir is t.TempDir with the mode the platform rule wants, whatever the
+// umask (0002 makes a plain temp directory group-writable).
+func tempDir(t *testing.T) string {
+ t.Helper()
+ base := t.TempDir()
+ if err := os.Chmod(base, 0o755); err != nil {
+ t.Fatal(err)
+ }
+ return base
+}
+
+func mkdir(t *testing.T, p string) {
+ t.Helper()
+ if err := os.MkdirAll(p, 0o755); err != nil {
+ t.Fatal(err)
+ }
+ // MkdirAll's mode is subject to the umask; set each created level
+ for q := p; q != "/" && q != "."; q = filepath.Dir(q) {
+ fi, err := os.Lstat(q)
+ if err != nil || !fi.IsDir() {
+ break
+ }
+ if fi.Mode().Perm()&0o022 == 0 {
+ break
+ }
+ if err := os.Chmod(q, 0o755); err != nil {
+ t.Fatal(err)
+ }
+ }
+}
+
+func write(t *testing.T, p, body string) {
+ t.Helper()
+ if err := os.WriteFile(p, []byte(body), 0o644); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func link(t *testing.T, target, p string) {
+ t.Helper()
+ if err := os.Symlink(target, p); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func fifo(t *testing.T, p string) {
+ t.Helper()
+ if err := unix.Mkfifo(p, 0o644); err != nil {
+ t.Fatal(err)
+ }
+}
+
+func open(t *testing.T, p string) *Dir {
+ t.Helper()
+ d, err := Open(p)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Cleanup(func() { d.Close() })
+ return d
+}
+
+func child(t *testing.T, d *Dir, name string) *Dir {
+ t.Helper()
+ c, err := d.Child(name, nil)
+ if err != nil {
+ t.Fatalf("Child(%s): %v", name, err)
+ }
+ t.Cleanup(func() { c.Close() })
+ return c
+}
+
+func edgeIs(err error, target error) bool {
+ var ee *EdgeError
+ return errors.As(err, &ee) && errors.Is(ee.Err, target)
+}
+
+// A platform ancestry with a group-writable component, a linked component
+// or a non-platform owner is refused; a clean one builds, and a component
+// replaced beneath it is a changed ancestry.
+func TestRootPlatformWalk(t *testing.T) {
+ base := tempDir(t)
+ slash := open(t, base)
+ mkdir(t, filepath.Join(base, "a", "b"))
+ if _, err := OpenRoot(slash, "a/b", func(uint32) bool { return false }); !edgeIs(err, ErrNotPlatform) {
+ t.Fatalf("non-platform owner: %v", err)
+ }
+ if err := os.Chmod(filepath.Join(base, "a"), 0o775); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := OpenRoot(slash, "a/b", me); !edgeIs(err, ErrNotPlatform) {
+ t.Fatalf("group-writable component: %v", err)
+ }
+ os.Chmod(filepath.Join(base, "a"), 0o755)
+ mkdir(t, filepath.Join(base, "real", "b"))
+ link(t, "real", filepath.Join(base, "lnk"))
+ if _, err := OpenRoot(slash, "lnk/b", me); !edgeIs(err, ErrLink) {
+ t.Fatalf("linked component: %v", err)
+ }
+ r, err := OpenRoot(slash, "a/b", me)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r.Close()
+ if len(r.Ancestry()) != 2 || r.Depth() != 2 || !r.root {
+ t.Fatalf("ancestry %d depth %d root %v", len(r.Ancestry()), r.Depth(), r.root)
+ }
+ if changed, err := r.AncestryChanged(); changed || err != nil {
+ t.Fatalf("unchanged ancestry read as changed: %v %v", changed, err)
+ }
+ if err := os.Rename(filepath.Join(base, "a", "b"), filepath.Join(base, "a", "c")); err != nil {
+ t.Fatal(err)
+ }
+ mkdir(t, filepath.Join(base, "a", "b"))
+ if changed, _ := r.AncestryChanged(); !changed {
+ t.Fatal("a replaced component not seen")
+ }
+ if err := r.Recheck(); !edgeIs(err, ErrChanged) {
+ t.Fatalf("Recheck on the moved root: %v", err)
+ }
+}
+
+// A directory swapped between List and Walk changes nothing: the walk is
+// from the retained descriptor, not the path.
+func TestSwapBetweenListAndWalk(t *testing.T) {
+ base := tempDir(t)
+ slash := open(t, base)
+ mkdir(t, filepath.Join(base, "A", "sub"))
+ write(t, filepath.Join(base, "A", "sub", "x"), "db")
+ link(t, "sub/x", filepath.Join(base, "A", "l"))
+ a := child(t, slash, "A")
+ entries, err := a.List()
+ if err != nil || len(entries) != 2 {
+ t.Fatalf("list: %v %v", entries, err)
+ }
+ if err := os.Rename(filepath.Join(base, "A"), filepath.Join(base, "old")); err != nil {
+ t.Fatal(err)
+ }
+ mkdir(t, filepath.Join(base, "A", "sub")) // the swap: an empty A in its place
+ target, err := a.Readlink("l")
+ if err != nil || target != "sub/x" {
+ t.Fatalf("readlink from the retained directory: %q %v", target, err)
+ }
+ res, err := a.Walk(target, nil)
+ if err != nil || res.Kind != Regular {
+ t.Fatalf("walk from the retained directory: %v %v", res.Kind, err)
+ }
+ fresh := open(t, filepath.Join(base, "A"))
+ res, err = fresh.Walk(target, nil)
+ if err != nil || res.Kind != Absent {
+ t.Fatalf("walk from the swapped-in directory: %v %v", res.Kind, err)
+ }
+}
+
+// A listed subdirectory replaced by a FIFO fails Child with ENOTDIR at
+// lookup, and nothing blocks on the FIFO.
+func TestChildRefusesFIFOWithoutBlocking(t *testing.T) {
+ base := tempDir(t)
+ slash := open(t, base)
+ mkdir(t, filepath.Join(base, "sub"))
+ entries, err := slash.List()
+ if err != nil || len(entries) != 1 || entries[0].Kind != Directory {
+ t.Fatalf("list: %v %v", entries, err)
+ }
+ if err := os.Rename(filepath.Join(base, "sub"), filepath.Join(base, "gone")); err != nil {
+ t.Fatal(err)
+ }
+ fifo(t, filepath.Join(base, "sub"))
+ done := make(chan error, 1)
+ go func() {
+ _, err := slash.Child("sub", &entries[0].Facts)
+ done <- err
+ }()
+ select {
+ case err := <-done:
+ if !edgeIs(err, unix.ENOTDIR) {
+ t.Fatalf("want ENOTDIR, got %v", err)
+ }
+ case <-time.After(5 * time.Second):
+ t.Fatal("Child blocked on a FIFO")
+ }
+ // the same for OpenRegular: a FIFO in a file's place is refused, not read
+ k, f, _ := slash.Lookat("sub")
+ if k != Other {
+ t.Fatalf("a FIFO looked at as %v", k)
+ }
+ go func() {
+ _, err := slash.OpenRegular("sub", f)
+ done <- err
+ }()
+ select {
+ case err := <-done:
+ if !edgeIs(err, ErrNotRegular) {
+ t.Fatalf("want ErrNotRegular, got %v", err)
+ }
+ case <-time.After(5 * time.Second):
+ t.Fatal("OpenRegular blocked on a FIFO")
+ }
+}
+
+// ".." pops the retained stack: past the root it is refused, after a named
+// component it is refused, and otherwise it is the parent, as a directory.
+func TestAscent(t *testing.T) {
+ base := tempDir(t)
+ slash := open(t, base)
+ mkdir(t, filepath.Join(base, "r", "a", "b"))
+ write(t, filepath.Join(base, "r", "f"), "x")
+ r, err := OpenRoot(slash, "r", me)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r.Close()
+ b := child(t, child(t, r.Dir, "a"), "b")
+ if _, err := b.Walk("../../..", nil); !errors.Is(err, ErrAscentPastRoot) {
+ t.Fatalf("past the root: %v", err)
+ }
+ if _, err := b.Walk("../x/..", nil); !errors.Is(err, ErrAscentAfterName) {
+ t.Fatalf("after a name: %v", err)
+ }
+ res, err := b.Walk("../..", nil)
+ if err != nil || res.Kind != Directory || !res.Facts.Same(r.Facts()) || res.Dir != r.Dir {
+ t.Fatalf("to the root: %v %v", res, err)
+ }
+ res.Close() // closes nothing it was not given
+ if err := r.Recheck(); err != nil {
+ t.Fatalf("the root was closed by a result that did not own it: %v", err)
+ }
+ res, err = b.Walk("../../f", nil)
+ if err != nil || res.Kind != Regular {
+ t.Fatalf("a file via ascent: %v %v", res.Kind, err)
+ }
+ if _, err := r.Walk("..", nil); !errors.Is(err, ErrAscentPastRoot) {
+ t.Fatalf("\"..\" from the root: %v", err)
+ }
+}
+
+// A retained child moved under another parent is a changed edge at Recheck,
+// and so is a new directory put in its place.
+func TestRecheckDetectsMovedChild(t *testing.T) {
+ base := tempDir(t)
+ slash := open(t, base)
+ mkdir(t, filepath.Join(base, "a", "b"))
+ mkdir(t, filepath.Join(base, "c"))
+ b := child(t, child(t, slash, "a"), "b")
+ if err := b.Recheck(); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.Rename(filepath.Join(base, "a", "b"), filepath.Join(base, "c", "b")); err != nil {
+ t.Fatal(err)
+ }
+ var ee *EdgeError
+ if err := b.Recheck(); !errors.As(err, &ee) || ee.Name != "b" {
+ t.Fatalf("moved child: %v", err)
+ }
+ mkdir(t, filepath.Join(base, "a", "b"))
+ if err := b.Recheck(); !edgeIs(err, ErrChanged) {
+ t.Fatalf("replaced child: %v", err)
+ }
+ // the moved directory itself still answers: its descriptor is the object
+ if _, err := b.List(); err != nil {
+ t.Fatalf("the retained descriptor stopped working: %v", err)
+ }
+}
+
+// List twice on one Dir gives the same entries, and Child with the listed
+// facts refuses when the entry changed between the listing and the
+// acquisition.
+func TestListAndChildExpect(t *testing.T) {
+ base := tempDir(t)
+ slash := open(t, base)
+ mkdir(t, filepath.Join(base, "sub"))
+ write(t, filepath.Join(base, "f"), "x")
+ link(t, "f", filepath.Join(base, "l"))
+ fifo(t, filepath.Join(base, "p"))
+ one, err := slash.List()
+ if err != nil {
+ t.Fatal(err)
+ }
+ two, err := slash.List()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(one) != 4 || len(two) != 4 {
+ t.Fatalf("%d and %d entries", len(one), len(two))
+ }
+ for i := range one {
+ if one[i] != two[i] {
+ t.Fatalf("listing differs: %v vs %v", one[i], two[i])
+ }
+ }
+ kinds := map[string]Kind{}
+ for _, e := range one {
+ kinds[e.Name] = e.Kind
+ }
+ if kinds["sub"] != Directory || kinds["f"] != Regular || kinds["l"] != Link || kinds["p"] != Other {
+ t.Fatalf("kinds %v", kinds)
+ }
+ if err := os.Rename(filepath.Join(base, "sub"), filepath.Join(base, "sub2")); err != nil {
+ t.Fatal(err)
+ }
+ mkdir(t, filepath.Join(base, "sub"))
+ if _, err := slash.Child("sub", &one[3].Facts); !edgeIs(err, ErrChanged) {
+ t.Fatalf("changed entry acquired: %v", err)
+ }
+ for _, bad := range []string{"", ".", "..", "a/b", "a\x00"} {
+ if _, err := slash.Child(bad, nil); !errors.Is(err, ErrBadName) {
+ t.Fatalf("Child(%q): %v", bad, err)
+ }
+ }
+}
+
+// Every link class is classified as written, none silently.
+func TestWalkClasses(t *testing.T) {
+ base := tempDir(t)
+ slash := open(t, base)
+ r := filepath.Join(base, "r")
+ mkdir(t, filepath.Join(r, "d", "inner"))
+ write(t, filepath.Join(r, "f"), "x")
+ link(t, "f", filepath.Join(r, "l"))
+ link(t, "d", filepath.Join(r, "ld"))
+ fifo(t, filepath.Join(r, "fifo"))
+ mkdir(t, filepath.Join(base, "other"))
+ write(t, filepath.Join(base, "other", "f"), "x")
+ mkdir(t, filepath.Join(base, "w", "x"))
+ os.Chmod(filepath.Join(base, "w"), 0o775)
+ root, err := OpenRoot(slash, "r", me)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer root.Close()
+ pins := &Pins{Slash: slash, Roots: []*Root{root}, Platform: me}
+ inner := child(t, child(t, root.Dir, "d"), "inner")
+
+ cases := []struct {
+ from *Dir
+ spelling string
+ kind Kind
+ err error
+ }{
+ {root.Dir, "d", Directory, nil},
+ {root.Dir, "f", Regular, nil},
+ {root.Dir, "l", Link, nil},
+ {root.Dir, "ld", Link, nil},
+ {root.Dir, "fifo", Other, nil},
+ {root.Dir, "nothing", Absent, nil},
+ {root.Dir, "d/", Directory, nil},
+ {root.Dir, "d/.", Directory, nil},
+ {root.Dir, "d//inner/", Directory, nil},
+ {root.Dir, "f/", Absent, ErrNotDirectory},
+ {root.Dir, "f/.", Absent, ErrNotDirectory},
+ {root.Dir, ".", Directory, nil},
+ {root.Dir, "./", Directory, nil},
+ {root.Dir, "", Absent, ErrEmptySpelling},
+ {root.Dir, "l/x", Link, nil},
+ {root.Dir, "ld/inner", Link, nil},
+ {root.Dir, "nothing/x", Absent, nil},
+ {root.Dir, "f/x", Absent, unix.ENOTDIR},
+ {inner, "../../f", Regular, nil},
+ {inner, "../..", Directory, nil},
+ {inner, "../../..", Absent, ErrAscentPastRoot},
+ {inner, "../d/../f", Absent, ErrAscentAfterName},
+ {root.Dir, "/r/f", Regular, nil},
+ {root.Dir, "/r/d/inner", Directory, nil},
+ {root.Dir, "/r", Directory, nil},
+ {root.Dir, "/r/", Directory, nil},
+ {root.Dir, "/", Absent, ErrOutside},
+ {root.Dir, "/other/f", Absent, ErrOutside},
+ {root.Dir, "/other", Absent, ErrOutside},
+ {root.Dir, "/w/x", Absent, ErrNotPlatform},
+ {root.Dir, "/missing/f", Absent, ErrOutside},
+ {root.Dir, "/r/../other/f", Absent, ErrAscentAfterName},
+ {root.Dir, "/../r/f", Absent, ErrAscentPastRoot},
+ {inner, "/r/nothing", Absent, nil},
+ }
+ for _, c := range cases {
+ res, err := c.from.Walk(c.spelling, pins)
+ if c.err != nil {
+ if err == nil || !(errors.Is(err, c.err) || edgeIs(err, c.err)) {
+ t.Errorf("Walk(%q): want %v, got kind %v err %v", c.spelling, c.err, res.Kind, err)
+ }
+ continue
+ }
+ if err != nil || res.Kind != c.kind {
+ t.Errorf("Walk(%q): want %v, got %v %v", c.spelling, c.kind, res.Kind, err)
+ }
+ if res.Kind == Directory && res.Dir == nil {
+ t.Errorf("Walk(%q): a directory with no Dir", c.spelling)
+ }
+ res.Close()
+ }
+ // the result of an absolute walk into the pinned root is the pinned Dir
+ res, err := root.Walk("/r", pins)
+ if err != nil || res.Dir != root.Dir {
+ t.Fatalf("/r is not the pinned root: %v %v", res.Dir, err)
+ }
+ res.Close()
+ // a walk without pins cannot take an absolute spelling anywhere
+ if _, err := root.Walk("/r/f", nil); !errors.Is(err, ErrOutside) {
+ t.Fatalf("absolute without pins: %v", err)
+ }
+ // a directory result's stack is retained and rechecks against the anchor
+ res, err = root.Walk("d/inner", nil)
+ if err != nil || res.Dir.Depth() != root.Depth()+2 {
+ t.Fatalf("stack: %v %v", res, err)
+ }
+ if err := res.Dir.Recheck(); err != nil {
+ t.Fatal(err)
+ }
+ if err := os.Rename(filepath.Join(r, "d"), filepath.Join(r, "d2")); err != nil {
+ t.Fatal(err)
+ }
+ if err := res.Dir.Recheck(); err == nil {
+ t.Fatal("a moved directory on the stack not seen")
+ }
+ res.Close()
+ if err := root.Recheck(); err != nil {
+ t.Fatalf("closing a result closed its anchor: %v", err)
+ }
+}
+
+// OpenRegular reads the file that was looked at and refuses a link, a FIFO
+// or another file in its place.
+func TestOpenRegular(t *testing.T) {
+ base := tempDir(t)
+ slash := open(t, base)
+ write(t, filepath.Join(base, "f"), "hello")
+ write(t, filepath.Join(base, "g"), "other")
+ _, f, err := slash.Lookat("f")
+ if err != nil {
+ t.Fatal(err)
+ }
+ fh, err := slash.OpenRegular("f", f)
+ if err != nil {
+ t.Fatal(err)
+ }
+ buf := make([]byte, 5)
+ if _, err := fh.Read(buf); err != nil || string(buf) != "hello" {
+ t.Fatalf("read %q %v", buf, err)
+ }
+ fh.Close()
+ if err := os.Rename(filepath.Join(base, "g"), filepath.Join(base, "f")); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := slash.OpenRegular("f", f); !edgeIs(err, ErrNotRegular) {
+ t.Fatalf("another file in its place: %v", err)
+ }
+ os.Remove(filepath.Join(base, "f"))
+ link(t, "/etc/hostname", filepath.Join(base, "f"))
+ if _, err := slash.OpenRegular("f", f); !edgeIs(err, unix.ELOOP) {
+ t.Fatalf("a link in its place: %v", err)
+ }
+}
+
+// A closed Dir refuses everything and closing it again is harmless.
+func TestClosed(t *testing.T) {
+ base := tempDir(t)
+ d, err := Open(base)
+ if err != nil {
+ t.Fatal(err)
+ }
+ d.Close()
+ d.Close()
+ if _, err := d.List(); !errors.Is(err, ErrClosed) {
+ t.Fatalf("List after Close: %v", err)
+ }
+ if _, err := d.Walk("x", nil); !errors.Is(err, ErrClosed) {
+ t.Fatalf("Walk after Close: %v", err)
+ }
+}
diff --git a/internal/authority/doc.go b/internal/authority/doc.go
new file mode 100644
index 000000000..ae3796d78
--- /dev/null
+++ b/internal/authority/doc.go
@@ -0,0 +1,20 @@
+// Package authority is Part A of the replicator's authority design
+// (docs/superpowers/specs/2026-10-03-replicator-pinned-roots-design.md): a
+// hand-walked, retained directory descriptor, and nothing resolved by
+// pathname after it is acquired.
+//
+// A Dir is one open directory descriptor with the facts (device, inode,
+// owner, mode) read at acquisition and a pointer to the Dir it was acquired
+// from, so a chain of Dirs is a stack. Every method takes a single name
+// and resolves it relative to the descriptor alone, with O_NOFOLLOW. List
+// uses a fresh open file description each time. Walk classifies a captured
+// link target by components from an anchor, popping the retained stack for
+// a leading run of ".." rather than asking the kernel for "..", and never
+// leaves the root it started in. A Root is a Dir reached from a pinned "/"
+// by a walk whose every component is the platform's.
+//
+// What this package does not claim: a bind mount or a device node already
+// inside a tree is reachable within containment; a swap put back between
+// two looks is not detected by polling. Those are the design's stated
+// support conditions and bounds, not this package's.
+package authority