aboutsummaryrefslogtreecommitdiffhomepage
path: root/fst/sandbox.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-01-15 10:07:51 +0900
committerOphestra <cat@gensokyo.uk>2025-01-15 10:13:18 +0900
commit562f5ed7971603a4e4e3315a7fe4188153bfc205 (patch)
tree2a751ea418e305c97bcef5625b5d4b8633b74834 /fst/sandbox.go
parentdb03565614821695efdb283a81a4733e6d321670 (diff)
fst: hide sockets exposed via Filesystem
This is mostly useful for permissive defaults. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'fst/sandbox.go')
-rw-r--r--fst/sandbox.go93
1 files changed, 90 insertions, 3 deletions
diff --git a/fst/sandbox.go b/fst/sandbox.go
index 32508fde..8def9086 100644
--- a/fst/sandbox.go
+++ b/fst/sandbox.go
@@ -2,8 +2,13 @@ package fst
import (
"errors"
+ "fmt"
+ "io/fs"
+ "path"
+ "git.gensokyo.uk/security/fortify/dbus"
"git.gensokyo.uk/security/fortify/helper/bwrap"
+ "git.gensokyo.uk/security/fortify/internal/fmsg"
"git.gensokyo.uk/security/fortify/internal/linux"
)
@@ -68,7 +73,8 @@ func (s *SandboxConfig) Bwrap(os linux.System) (*bwrap.Config, error) {
DieWithParent: true,
AsInit: true,
- // initialise map
+ // initialise unconditionally as Once cannot be justified
+ // for saving such a miniscule amount of memory
Chmod: make(bwrap.ChmodConfig),
}).
SetUID(uid).SetGID(uid).
@@ -89,16 +95,85 @@ func (s *SandboxConfig) Bwrap(os linux.System) (*bwrap.Config, error) {
}
}
+ // retrieve paths and hide them if they're made available in the sandbox
+ var hidePaths []string
+ sc := os.Paths()
+ hidePaths = append(hidePaths, sc.RuntimePath, sc.SharePath)
+ _, systemBusAddr := dbus.Address()
+ if entries, err := dbus.Parse([]byte(systemBusAddr)); err != nil {
+ return nil, err
+ } else {
+ // there is usually only one, do not preallocate
+ for _, entry := range entries {
+ if entry.Method != "unix" {
+ continue
+ }
+ for _, pair := range entry.Values {
+ if pair[0] == "path" {
+ if path.IsAbs(pair[1]) {
+ // get parent dir of socket
+ dir := path.Dir(pair[1])
+ if dir == "." || dir == "/" {
+ fmsg.VPrintf("dbus socket %q is in an unusual location", pair[1])
+ }
+ hidePaths = append(hidePaths, dir)
+ } else {
+ fmsg.VPrintf("dbus socket %q is not absolute", pair[1])
+ }
+ }
+ }
+ }
+ }
+ hidePathMatch := make([]bool, len(hidePaths))
+ for i := range hidePaths {
+ if err := evalSymlinks(os, &hidePaths[i]); err != nil {
+ return nil, err
+ }
+ }
+
for _, c := range s.Filesystem {
if c == nil {
continue
}
- src := c.Src
+
+ if !path.IsAbs(c.Src) {
+ return nil, fmt.Errorf("src path %q is not absolute", c.Src)
+ }
+
dest := c.Dst
if c.Dst == "" {
dest = c.Src
+ } else if !path.IsAbs(dest) {
+ return nil, fmt.Errorf("dst path %q is not absolute", dest)
+ }
+
+ srcH := c.Src
+ if err := evalSymlinks(os, &srcH); err != nil {
+ return nil, err
+ }
+
+ for i := range hidePaths {
+ // skip matched entries
+ if hidePathMatch[i] {
+ continue
+ }
+
+ if ok, err := deepContainsH(srcH, hidePaths[i]); err != nil {
+ return nil, err
+ } else if ok {
+ hidePathMatch[i] = true
+ fmsg.VPrintf("hiding paths from %q", c.Src)
+ }
+ }
+
+ conf.Bind(c.Src, dest, !c.Must, c.Write, c.Device)
+ }
+
+ // hide marked paths before setting up shares
+ for i, ok := range hidePathMatch {
+ if ok {
+ conf.Tmpfs(hidePaths[i], 8192)
}
- conf.Bind(src, dest, !c.Must, c.Write, c.Device)
}
for _, l := range s.Link {
@@ -133,3 +208,15 @@ func (s *SandboxConfig) Bwrap(os linux.System) (*bwrap.Config, error) {
return conf, nil
}
+
+func evalSymlinks(os linux.System, v *string) error {
+ if p, err := os.EvalSymlinks(*v); err != nil {
+ if !errors.Is(err, fs.ErrNotExist) {
+ return err
+ }
+ fmsg.VPrintf("path %q does not yet exist", *v)
+ } else {
+ *v = p
+ }
+ return nil
+}