v0.328.0 (unreleased): live finding on 9201 (rc.4) — roots resolved through their nearest existing ancestor; no symlink resolve for the placeholder check
gates / gates (push) Successful in 45s
gates / gates (push) Successful in 45s
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
1 parent
09ac87a843
commit
99f9117296
4 files changed
+33
-4
No files matched your search
@@ -53,6 +53,10 @@ still refuses and the app page still says so.
|
|||||||
household's folders come through `${USERDATA_PATH}`. Every catalog bind already uses `${HDD_PATH}/appdata/…`.
|
household's folders come through `${USERDATA_PATH}`. Every catalog bind already uses `${HDD_PATH}/appdata/…`.
|
||||||
Known limit, stated: one app can still name ANOTHER app's `appdata/<name>` (paperless-ngx's folder is `paperless`,
|
Known limit, stated: one app can still name ANOTHER app's `appdata/<name>` (paperless-ngx's folder is `paperless`,
|
||||||
so a per-app rule needs a name map) — filed. Red-proved (`P2/redproof-security-review-round3.txt`).
|
so a per-app rule needs a name map) — filed. Red-proved (`P2/redproof-security-review-round3.txt`).
|
||||||
|
- **Found live on demo-hp 9201 with rc.4:** the first sync refused every app NOT installed (sabnzbd, sonarr, …): on
|
||||||
|
the box the placeholder roots do not exist, so the symlink resolve could not resolve the ROOT and nothing matched. A
|
||||||
|
root is now resolved through its nearest existing ancestor too, and the placeholder check (no app env) resolves no
|
||||||
|
symlinks at all. `TestAdmit_RootsThatDoNotExistYet`, red-proved (`P2/redproof-live-root-resolve.txt`).
|
||||||
|
|
||||||
## v0.327.1 — files.<domain> reaches FileBrowser again: a file route by name, not Docker labels (2026-10-17)
|
## v0.327.1 — files.<domain> reaches FileBrowser again: a file route by name, not Docker labels (2026-10-17)
|
||||||
|
|
||||||
|
|||||||
@@ -548,8 +548,9 @@ func (c *checker) underRoot(p string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, r := range c.roots {
|
for _, r := range c.roots {
|
||||||
rr, rerr := c.p.Resolve(r)
|
// A root is resolved the same way (nearest existing ancestor): a drive folder not created yet must not make
|
||||||
if rerr == nil && within(rp, rr) {
|
// every bind under it "outside" (found live on 9201 with rc.4: every not-installed app refused).
|
||||||
|
if rr, ok := c.resolveExisting(r); ok && within(rp, rr) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -417,3 +417,24 @@ func TestAdmit_HDDPathRootIsAppdataOnly(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Found live on 9201 (rc.4): with Resolve set, roots that do not exist yet (a drive folder not created, or the
|
||||||
|
// placeholder env) made every bind "outside". A root is resolved through its nearest existing ancestor too.
|
||||||
|
func TestAdmit_RootsThatDoNotExistYet(t *testing.T) {
|
||||||
|
root := t.TempDir()
|
||||||
|
if err := os.MkdirAll(filepath.Join(root, "mnt", "felhom-drives"), 0o755); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
resolve := func(s string) (string, error) {
|
||||||
|
r, err := filepath.EvalSymlinks(filepath.Join(root, s))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
rel, _ := filepath.Rel(root, r)
|
||||||
|
return "/" + rel, nil
|
||||||
|
}
|
||||||
|
c := "services:\n app:\n image: x/y:1\n volumes:\n - ${USERDATA_PATH}/media:/m\n - ${HDD_PATH}/appdata/app:/c\n"
|
||||||
|
if err := Admit("app", []byte(c), PlaceholderEnv(), Policy{Resolve: resolve}); err != nil {
|
||||||
|
t.Fatalf("binds under roots that do not exist yet were refused: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,11 +50,14 @@ func (m *Manager) policyEnv(env map[string]string) map[string]string {
|
|||||||
// app's refusal line.
|
// app's refusal line.
|
||||||
func (m *Manager) admitCompose(name string, data []byte, env map[string]string) error {
|
func (m *Manager) admitCompose(name string, data []byte, env map[string]string) error {
|
||||||
e := privpolicy.PlaceholderEnv()
|
e := privpolicy.PlaceholderEnv()
|
||||||
|
pol := privpolicy.Policy{SystemDataPath: m.sysDataPath}
|
||||||
if env != nil {
|
if env != nil {
|
||||||
e = m.policyEnv(env)
|
e = m.policyEnv(env)
|
||||||
|
// Resolve (real paths only — the placeholder env names no real folder): a bind source that is a symlink out
|
||||||
|
// of its data root is outside; it is judged where it points.
|
||||||
|
pol.Resolve = filepath.EvalSymlinks
|
||||||
}
|
}
|
||||||
// Resolve: a bind source that is a symlink out of its data root is outside (it is judged where it points).
|
err := privpolicy.Admit(name, data, e, pol)
|
||||||
err := privpolicy.Admit(name, data, e, privpolicy.Policy{SystemDataPath: m.sysDataPath, Resolve: filepath.EvalSymlinks})
|
|
||||||
m.noteAdmission(name, data, err)
|
m.noteAdmission(name, data, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user