carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "github.com/carlosframework/platform/internal/rootstate"
5 "golang.org/x/sys/unix"
6 "os"
7 "testing"
8)
9
10func TestPlan14PersistentChrootMountBoundary(t *testing.T) {
11 if !plan14RootFixture(t) {
12 return
13 }
14 for _, p := range []string{"/data", "/view"} {
15 if e := os.Mkdir(p, 0755); e != nil {
16 t.Fatal(e)
17 }
18 }
19 if e := unix.Mount("/data", "/view", "", unix.MS_BIND, ""); e != nil {
20 t.Fatal(e)
21 }
22 defer unix.Unmount("/view", 0)
23 f, e := os.Open("/view")
24 if e != nil {
25 t.Fatal(e)
26 }
27 defer f.Close()
28 before, e := rootstate.ObjectIdentity(f)
29 if e != nil || before.MountLineage == "" {
30 t.Fatal(before, e)
31 }
32 if e := unix.Mount("/view", "/view", "", unix.MS_BIND, ""); e != nil {
33 t.Fatal(e)
34 }
35 second, e := os.Open("/view")
36 if e != nil {
37 t.Fatal(e)
38 }
39 after, e := rootstate.ObjectIdentity(second)
40 second.Close()
41 unmount := unix.Unmount("/view", 0)
42 if e != nil || unmount != nil || before.Same(after) {
43 t.Fatal("substituted mount", e, unmount, before, after)
44 }
45 restored, e := rootstate.ObjectIdentity(f)
46 if e != nil || !before.Same(restored) {
47 t.Fatal("restored mount", e)
48 }
49 if err := unix.Unmount("/view", unix.MNT_DETACH); err != nil {
50 t.Fatal(err)
51 }
52 if err := unix.Mount("/data", "/view", "", unix.MS_BIND, ""); err != nil {
53 t.Fatal(err)
54 }
55 replacement, err := os.Open("/view")
56 if err != nil {
57 t.Fatal(err)
58 }
59 replaced, err := rootstate.ObjectIdentity(replacement)
60 replacement.Close()
61 if err != nil || replaced.MountUnique == before.MountUnique || !replaced.SameMountNamespace(before) || replaced.MountLineage != before.MountLineage || replaced.Filesystem != before.Filesystem || replaced.Handle != before.Handle || replaced.Inode != before.Inode {
62 t.Fatal("replacement did not preserve geometry and persistent object", before, replaced, err)
63 }
64 if before.Same(replaced) {
65 t.Fatal("replacement mount with unchanged geometry accepted")
66 }
67 replaced.Mount = before.Mount
68 if before.Same(replaced) {
69 t.Fatal("replacement mount accepted with a recycled legacy number")
70 }
71 for _, path := range []string{"/source", "/parent", "/parent/view"} {
72 if err := os.Mkdir(path, 0755); err != nil {
73 t.Fatal(err)
74 }
75 }
76 if err := unix.Mount("/source", "/parent/view", "", unix.MS_BIND, ""); err != nil {
77 t.Fatal(err)
78 }
79 defer unix.Unmount("/parent/view", 0)
80 capture := func() rootstate.FileIdentity {
81 f, err := os.Open("/parent/view")
82 if err != nil {
83 t.Fatal(err)
84 }
85 defer f.Close()
86 id, err := rootstate.ObjectIdentity(f)
87 if err != nil {
88 t.Fatal(err)
89 }
90 return id
91 }
92 child := capture()
93 if err := unix.Mount("/parent", "/parent", "", unix.MS_BIND|unix.MS_REC, ""); err != nil {
94 t.Fatal(err)
95 }
96 defer unix.Unmount("/parent", unix.MNT_DETACH)
97 rebound := capture()
98 if child.MountRoot != rebound.MountRoot || child.MountPoint != rebound.MountPoint || child.Filesystem != rebound.Filesystem || child.Handle != rebound.Handle || child.Inode != rebound.Inode {
99 t.Fatal("recursive bind changed the child fixture", child, rebound)
100 }
101 if child.Same(rebound) || rebound.Same(child) {
102 t.Fatal("recursive ancestor substitution accepted")
103 }
104}
105