internal/outcome: attempt nscd path-hiding if present
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m46s
Test / ShareFS (push) Successful in 3m56s
Test / Hakurei (push) Successful in 4m9s
Test / Sandbox (race detector) (push) Successful in 5m42s
Test / Hakurei (race detector) (push) Successful in 6m50s
Test / Flake checks (push) Successful in 1m9s
Test / Create distribution (push) Successful in 52s
Test / Sandbox (push) Successful in 2m46s
Test / ShareFS (push) Successful in 3m56s
Test / Hakurei (push) Successful in 4m9s
Test / Sandbox (race detector) (push) Successful in 5m42s
Test / Hakurei (race detector) (push) Successful in 6m50s
Test / Flake checks (push) Successful in 1m9s
This avoids creating the mount point on musl setups which accomplishes nothing and can run into permission problems. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Vendored
+24
-4
@@ -1,21 +1,29 @@
|
|||||||
// Package env provides the [Paths] struct for efficiently building paths from the environment.
|
// Package env provides the [Paths] struct for efficiently building paths from
|
||||||
|
// the environment.
|
||||||
package env
|
package env
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"hakurei.app/check"
|
"hakurei.app/check"
|
||||||
|
"hakurei.app/fhs"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const VarRunNscd = fhs.Var + "run/nscd"
|
||||||
|
|
||||||
// Paths holds paths copied from the environment and is used to create [hst.Paths].
|
// Paths holds paths copied from the environment and is used to create [hst.Paths].
|
||||||
type Paths struct {
|
type Paths struct {
|
||||||
// TempDir is returned by [os.TempDir].
|
// TempDir is returned by [os.TempDir].
|
||||||
TempDir *check.Absolute
|
TempDir *check.Absolute
|
||||||
// RuntimePath is copied from $XDG_RUNTIME_DIR.
|
// RuntimePath is copied from $XDG_RUNTIME_DIR.
|
||||||
RuntimePath *check.Absolute
|
RuntimePath *check.Absolute
|
||||||
|
// Whether [VarRunNscd] is a directory.
|
||||||
|
HasNscd bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy expands [Paths] into [hst.Paths].
|
// Copy expands [Paths] into [hst.Paths].
|
||||||
@@ -37,14 +45,17 @@ func (env *Paths) Copy(v *hst.Paths, userid int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CopyPaths returns a populated [Paths].
|
// CopyPaths returns a populated [Paths].
|
||||||
func CopyPaths() *Paths { return CopyPathsFunc(log.Fatalf, os.TempDir, os.Getenv) }
|
func CopyPaths() *Paths {
|
||||||
|
return CopyPathsFunc(log.Fatalf, os.TempDir, os.Getenv, os.Stat)
|
||||||
|
}
|
||||||
|
|
||||||
// CopyPathsFunc returns a populated [Paths],
|
// CopyPathsFunc returns a populated [Paths], using the provided [log.Fatalf],
|
||||||
// using the provided [log.Fatalf], [os.TempDir], [os.Getenv] functions.
|
// [os.TempDir], [os.Getenv] functions.
|
||||||
func CopyPathsFunc(
|
func CopyPathsFunc(
|
||||||
fatalf func(format string, v ...any),
|
fatalf func(format string, v ...any),
|
||||||
tempdir func() string,
|
tempdir func() string,
|
||||||
getenv func(key string) string,
|
getenv func(key string) string,
|
||||||
|
stat func(name string) (fs.FileInfo, error),
|
||||||
) *Paths {
|
) *Paths {
|
||||||
const xdgRuntimeDir = "XDG_RUNTIME_DIR"
|
const xdgRuntimeDir = "XDG_RUNTIME_DIR"
|
||||||
|
|
||||||
@@ -61,5 +72,14 @@ func CopyPathsFunc(
|
|||||||
env.RuntimePath = a
|
env.RuntimePath = a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if fi, err := stat(VarRunNscd); err != nil {
|
||||||
|
if !errors.Is(err, fs.ErrNotExist) {
|
||||||
|
fatalf("%v", err)
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
env.HasNscd = fi.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
return &env
|
return &env
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+4
-1
@@ -2,6 +2,7 @@ package env_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -104,7 +105,9 @@ func TestCopyPaths(t *testing.T) {
|
|||||||
t.Fatalf("fatalf: %q, want %q", got, tc.fatal)
|
t.Fatalf("fatalf: %q, want %q", got, tc.fatal)
|
||||||
}
|
}
|
||||||
panic(stub.PanicExit)
|
panic(stub.PanicExit)
|
||||||
}, func() string { return tc.tmp }, func(key string) string { return tc.env[key] })
|
}, func() string { return tc.tmp }, func(key string) string { return tc.env[key] }, func(name string) (fs.FileInfo, error) {
|
||||||
|
return nil, fs.ErrNotExist
|
||||||
|
})
|
||||||
|
|
||||||
if tc.fatal != "" {
|
if tc.fatal != "" {
|
||||||
t.Fatalf("copyPaths: expected fatal %q", tc.fatal)
|
t.Fatalf("copyPaths: expected fatal %q", tc.fatal)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"hakurei.app/container/seccomp"
|
"hakurei.app/container/seccomp"
|
||||||
"hakurei.app/container/std"
|
"hakurei.app/container/std"
|
||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
|
"hakurei.app/internal/env"
|
||||||
"hakurei.app/internal/stub"
|
"hakurei.app/internal/stub"
|
||||||
"hakurei.app/internal/system"
|
"hakurei.app/internal/system"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
@@ -174,6 +175,7 @@ func checkOpBehaviour(t *testing.T, testCases []opBehaviourTestCase) {
|
|||||||
call("cmdOutput", stub.ExpectArgs{container.Nonexistent, os.Stderr, []string{}, "/"}, []byte("0"), nil),
|
call("cmdOutput", stub.ExpectArgs{container.Nonexistent, os.Stderr, []string{}, "/"}, []byte("0"), nil),
|
||||||
call("tempdir", stub.ExpectArgs{}, container.Nonexistent+"/tmp", nil),
|
call("tempdir", stub.ExpectArgs{}, container.Nonexistent+"/tmp", nil),
|
||||||
call("lookupEnv", stub.ExpectArgs{"XDG_RUNTIME_DIR"}, wantRuntimePath, nil),
|
call("lookupEnv", stub.ExpectArgs{"XDG_RUNTIME_DIR"}, wantRuntimePath, nil),
|
||||||
|
call("stat", stub.ExpectArgs{env.VarRunNscd}, stubFileInfoIsDir(true), nil),
|
||||||
call("getuid", stub.ExpectArgs{}, 1000, nil),
|
call("getuid", stub.ExpectArgs{}, 1000, nil),
|
||||||
call("getgid", stub.ExpectArgs{}, 100, nil),
|
call("getgid", stub.ExpectArgs{}, 100, nil),
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ func newOutcomeState(k syscallDispatcher, msg message.Msg, id *hst.ID, config *h
|
|||||||
Paths: env.CopyPathsFunc(k.fatalf, k.tempdir, func(key string) string {
|
Paths: env.CopyPathsFunc(k.fatalf, k.tempdir, func(key string) string {
|
||||||
v, _ := k.lookupEnv(key)
|
v, _ := k.lookupEnv(key)
|
||||||
return v
|
return v
|
||||||
}),
|
}, k.stat),
|
||||||
Container: config.Container,
|
Container: config.Container,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -710,7 +710,7 @@ func (k *stubNixOS) lookupEnv(key string) (string, bool) {
|
|||||||
func (k *stubNixOS) stat(name string) (fs.FileInfo, error) {
|
func (k *stubNixOS) stat(name string) (fs.FileInfo, error) {
|
||||||
switch name {
|
switch name {
|
||||||
case "/var/run/nscd":
|
case "/var/run/nscd":
|
||||||
return nil, nil
|
return stubFileInfoIsDir(true), nil
|
||||||
case "/run/user/1971/pulse":
|
case "/run/user/1971/pulse":
|
||||||
return nil, nil
|
return nil, nil
|
||||||
case "/run/user/1971/pulse/native":
|
case "/run/user/1971/pulse/native":
|
||||||
|
|||||||
@@ -18,13 +18,12 @@ import (
|
|||||||
"hakurei.app/hst"
|
"hakurei.app/hst"
|
||||||
"hakurei.app/internal/acl"
|
"hakurei.app/internal/acl"
|
||||||
"hakurei.app/internal/dbus"
|
"hakurei.app/internal/dbus"
|
||||||
|
"hakurei.app/internal/env"
|
||||||
"hakurei.app/internal/system"
|
"hakurei.app/internal/system"
|
||||||
"hakurei.app/internal/validate"
|
"hakurei.app/internal/validate"
|
||||||
"hakurei.app/message"
|
"hakurei.app/message"
|
||||||
)
|
)
|
||||||
|
|
||||||
const varRunNscd = fhs.Var + "run/nscd"
|
|
||||||
|
|
||||||
func init() { gob.Register(new(spParamsOp)) }
|
func init() { gob.Register(new(spParamsOp)) }
|
||||||
|
|
||||||
// spParamsOp initialises unordered fields of [container.Params] and the
|
// spParamsOp initialises unordered fields of [container.Params] and the
|
||||||
@@ -136,17 +135,23 @@ type spFilesystemOp struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *spFilesystemOp) toSystem(state *outcomeStateSys) error {
|
func (s *spFilesystemOp) toSystem(state *outcomeStateSys) error {
|
||||||
/* retrieve paths and hide them if they're made available in the sandbox;
|
// retrieve paths and hide them if they're made available in the sandbox
|
||||||
|
//
|
||||||
this feature tries to improve user experience of permissive defaults, and
|
// this feature tries to improve user experience of permissive defaults, and
|
||||||
to warn about issues in custom configuration; it is NOT a security feature
|
// to warn about issues in custom configuration; it is NOT a security feature
|
||||||
and should not be treated as such, ALWAYS be careful with what you bind */
|
// and should not be treated as such, ALWAYS be careful with what you bind
|
||||||
hidePaths := []string{
|
hidePaths := []string{
|
||||||
state.sc.RuntimePath.String(),
|
state.sc.RuntimePath.String(),
|
||||||
state.sc.SharePath.String(),
|
state.sc.SharePath.String(),
|
||||||
|
}
|
||||||
|
|
||||||
// this causes emulated passwd database to be bypassed on some /etc/ setups
|
if state.Paths == nil || state.HasNscd {
|
||||||
varRunNscd,
|
hidePaths = append(hidePaths,
|
||||||
|
// this causes emulated passwd database to be bypassed on some /etc/
|
||||||
|
// setups, made optional to avoid needlessly creating it on
|
||||||
|
// non-glibc systems when invoking permissive defaults
|
||||||
|
env.VarRunNscd,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// dbus.Address does not go through syscallDispatcher
|
// dbus.Address does not go through syscallDispatcher
|
||||||
|
|||||||
Reference in New Issue
Block a user