carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package instancefs
4
5import (
6 "errors"
7 "os"
8 "path/filepath"
9 "syscall"
10 "testing"
11 "time"
12)
13
14// OpenDirBeneath and OpenRootBeneath open a directory as OpenBeneath opens
15// a file: no symlink at the name or anywhere in dir, never waiting on a
16// FIFO, and nothing but a directory accepted.
17func TestOpenDirBeneathRefusesWhatATenantCanPlant(t *testing.T) {
18 opens := map[string]func(dir, name string) (func(), error){
19 "OpenDirBeneath": func(dir, name string) (func(), error) {
20 f, err := OpenDirBeneath(dir, name)
21 if err != nil {
22 return nil, err
23 }
24 return func() { f.Close() }, nil
25 },
26 "OpenRootBeneath": func(dir, name string) (func(), error) {
27 r, err := OpenRootBeneath(dir, name)
28 if err != nil {
29 return nil, err
30 }
31 return func() { r.Close() }, nil
32 },
33 }
34 for fn, openIt := range opens {
35 for _, tc := range []struct {
36 name string
37 plant func(t *testing.T, parent string)
38 dir func(parent string) string
39 want error
40 }{
41 {"a symlink at the name", func(t *testing.T, parent string) {
42 if err := os.Symlink(t.TempDir(), filepath.Join(parent, "d")); err != nil {
43 t.Fatal(err)
44 }
45 }, nil, ErrSymlink},
46 {"a symlinked parent", func(t *testing.T, parent string) {
47 if err := os.Mkdir(filepath.Join(parent, "d"), 0o700); err != nil {
48 t.Fatal(err)
49 }
50 if err := os.Symlink(parent, parent+".link"); err != nil {
51 t.Fatal(err)
52 }
53 }, func(parent string) string { return parent + ".link" }, ErrSymlink},
54 {"a FIFO", func(t *testing.T, parent string) {
55 if err := syscall.Mkfifo(filepath.Join(parent, "d"), 0o600); err != nil {
56 t.Fatal(err)
57 }
58 }, nil, nil},
59 {"a regular file", func(t *testing.T, parent string) {
60 if err := os.WriteFile(filepath.Join(parent, "d"), nil, 0o600); err != nil {
61 t.Fatal(err)
62 }
63 }, nil, nil},
64 } {
65 t.Run(fn+"/"+tc.name, func(t *testing.T) {
66 parent := filepath.Join(t.TempDir(), "inst")
67 if err := os.Mkdir(parent, 0o700); err != nil {
68 t.Fatal(err)
69 }
70 tc.plant(t, parent)
71 dir := parent
72 if tc.dir != nil {
73 dir = tc.dir(parent)
74 }
75 done := make(chan error, 1)
76 go func() {
77 c, err := openIt(dir, "d")
78 if c != nil {
79 c()
80 }
81 done <- err
82 }()
83 select {
84 case err := <-done:
85 // nil want is "not a directory": O_DIRECTORY answers
86 // ENOTDIR, and the fstat check ErrNotDir behind it.
87 notDir := errors.Is(err, syscall.ENOTDIR) || errors.Is(err, ErrNotDir)
88 if (tc.want == nil && !notDir) || (tc.want != nil && !errors.Is(err, tc.want)) {
89 t.Fatalf("got %v, want %v", err, tc.want)
90 }
91 case <-time.After(20 * time.Second):
92 t.Fatal("the open blocked on what was planted")
93 }
94 })
95 }
96 }
97}
98
99// What OpenRootBeneath hands back is the directory it vetted, even once
100// the path names something else.
101func TestOpenRootBeneathIsTheDirectoryItOpened(t *testing.T) {
102 parent := t.TempDir()
103 d := filepath.Join(parent, "d")
104 if err := os.Mkdir(d, 0o700); err != nil {
105 t.Fatal(err)
106 }
107 if err := os.WriteFile(filepath.Join(d, "mine"), []byte("x"), 0o600); err != nil {
108 t.Fatal(err)
109 }
110 r, err := OpenRootBeneath(parent, "d")
111 if err != nil {
112 t.Fatal(err)
113 }
114 defer r.Close()
115 if err := os.Rename(d, d+".moved"); err != nil {
116 t.Fatal(err)
117 }
118 if err := os.Symlink(t.TempDir(), d); err != nil {
119 t.Fatal(err)
120 }
121 if _, err := r.Stat("mine"); err != nil {
122 t.Fatalf("the root is not the directory that was opened: %v", err)
123 }
124 f, err := OpenDirBeneath(parent, ".")
125 if err != nil {
126 t.Fatalf("dir itself: %v", err)
127 }
128 f.Close()
129}
130
131// The root is the directory OpenDirBeneath vetted, never the path opened
132// again: a link swapped in between the two is not followed.
133func TestOpenRootBeneathNeverOpensThePathAgain(t *testing.T) {
134 parent := t.TempDir()
135 d := filepath.Join(parent, "d")
136 if err := os.Mkdir(d, 0o700); err != nil {
137 t.Fatal(err)
138 }
139 if err := os.WriteFile(filepath.Join(d, "mine"), []byte("x"), 0o600); err != nil {
140 t.Fatal(err)
141 }
142 prev := betweenOpenAndRoot
143 betweenOpenAndRoot = func() {
144 if err := os.Rename(d, d+".moved"); err != nil {
145 t.Error(err)
146 }
147 if err := os.Symlink(t.TempDir(), d); err != nil {
148 t.Error(err)
149 }
150 }
151 t.Cleanup(func() { betweenOpenAndRoot = prev })
152 r, err := OpenRootBeneath(parent, "d")
153 if err != nil {
154 t.Fatal(err)
155 }
156 defer r.Close()
157 if _, err := r.Stat("mine"); err != nil {
158 t.Fatalf("the root followed a link swapped in after the open: %v", err)
159 }
160}
161