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 host
4
5import (
6 "errors"
7 "os"
8 "path/filepath"
9 "strconv"
10 "testing"
11)
12
13func rev3HoldTarget(t *testing.T, fx *writersKernelFixture, pid, fd int, target string) {
14 t.Helper()
15 dir := filepath.Join(fx.proc, strconv.Itoa(pid), "task", strconv.Itoa(pid), "fd")
16 if err := os.MkdirAll(dir, 0o700); err != nil {
17 t.Fatal(err)
18 }
19 if err := os.Symlink(target, filepath.Join(dir, strconv.Itoa(fd))); err != nil {
20 t.Fatal(err)
21 }
22}
23
24func TestRev3NoProcessCoversDeletedDatabaseAndWAL(t *testing.T) {
25 for _, suffix := range []string{"", "-wal"} {
26 t.Run(suffix, func(t *testing.T) {
27 fx := newWritersKernelFixture(t)
28 fx.dropAgentHolds(t)
29 target := fx.db + suffix
30 for _, path := range []string{fx.db, fx.db + "-wal"} {
31 if err := os.Remove(path); err != nil {
32 t.Fatal(err)
33 }
34 }
35 rev3HoldTarget(t, fx, 31, 8, target+" (deleted)")
36 if _, err := fx.noProcess(t, false); err == nil {
37 t.Fatalf("deleted holder passed: %v", err)
38 }
39 })
40 }
41}
42
43func TestRev3NoProcessCoversNestedInstallationFiles(t *testing.T) {
44 fx := newWritersKernelFixture(t)
45 fx.dropAgentHolds(t)
46 nested := filepath.Join(filepath.Dir(fx.db), "sqlite", "scratch.db")
47 if err := os.MkdirAll(filepath.Dir(nested), 0o700); err != nil {
48 t.Fatal(err)
49 }
50 if err := os.WriteFile(nested, nil, 0o600); err != nil {
51 t.Fatal(err)
52 }
53 rev3HoldTarget(t, fx, 32, 9, nested)
54 if _, err := fx.noProcess(t, false); !errors.Is(err, ErrClaimStopIdentity) {
55 t.Fatalf("nested holder passed: %v", err)
56 }
57}
58
59func TestRev3NoProcessScansWhenInstallationDirectoryIsEmpty(t *testing.T) {
60 fx := newWritersKernelFixture(t)
61 fx.dropAgentHolds(t)
62 if err := os.Remove(fx.db); err != nil {
63 t.Fatal(err)
64 }
65 if err := os.Remove(fx.db + "-wal"); err != nil {
66 t.Fatal(err)
67 }
68 target := filepath.Join(filepath.Dir(fx.db), "gone.db")
69 rev3HoldTarget(t, fx, 33, 10, target+" (deleted)")
70 if _, err := fx.noProcess(t, false); !errors.Is(err, ErrClaimStopIdentity) {
71 t.Fatalf("empty directory suppressed descriptor scan: %v", err)
72 }
73}
74
75func TestRev3NoProcessPrefixHasPathBoundary(t *testing.T) {
76 fx := newWritersKernelFixture(t)
77 fx.dropAgentHolds(t)
78 sibling := filepath.Dir(fx.db) + "-old"
79 if err := os.Mkdir(sibling, 0o700); err != nil {
80 t.Fatal(err)
81 }
82 target := filepath.Join(sibling, "data.db")
83 if err := os.WriteFile(target, nil, 0o600); err != nil {
84 t.Fatal(err)
85 }
86 rev3HoldTarget(t, fx, 34, 11, target)
87 if _, err := fx.noProcess(t, false); err != nil {
88 t.Fatalf("prefix sibling matched: %v", err)
89 }
90}
91
92func TestRev3NoProcessDescriptorScanErrorsFailClosed(t *testing.T) {
93 fx := newWritersKernelFixture(t)
94 fx.dropAgentHolds(t)
95 dir := filepath.Join(fx.proc, "35", "task", "35", "fd")
96 if err := os.MkdirAll(dir, 0o700); err != nil {
97 t.Fatal(err)
98 }
99 if err := os.WriteFile(filepath.Join(dir, "12"), nil, 0o600); err != nil {
100 t.Fatal(err)
101 }
102 if _, err := fx.noProcess(t, false); err == nil {
103 t.Fatal("unreadable descriptor entry passed")
104 }
105}
106
107func TestRev3NoProcessCoversUnlinkedNestedFile(t *testing.T) {
108 fx := newWritersKernelFixture(t)
109 fx.dropAgentHolds(t)
110 for _, p := range []string{fx.db, fx.db + "-wal"} {
111 if err := os.Remove(p); err != nil {
112 t.Fatal(err)
113 }
114 }
115 nested := filepath.Join(filepath.Dir(fx.db), "sqlite", "gone.db")
116 if err := os.MkdirAll(filepath.Dir(nested), 0700); err != nil {
117 t.Fatal(err)
118 }
119 if err := os.WriteFile(nested, nil, 0600); err != nil {
120 t.Fatal(err)
121 }
122 if err := os.Remove(nested); err != nil {
123 t.Fatal(err)
124 }
125 rev3HoldTarget(t, fx, 36, 13, nested+" (deleted)")
126 if _, err := fx.noProcess(t, false); !errors.Is(err, ErrClaimStopIdentity) {
127 t.Fatalf("unlinked nested holder passed: %v", err)
128 }
129}
130