aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-01-22 01:51:10 +0900
committerOphestra <cat@gensokyo.uk>2025-01-22 01:52:57 +0900
commit9a239fa1a5ad2ff248ca7a9d39342f66926c9fef (patch)
tree09efadb2ddf4eaeaf153d7e4b7d73e1b20d2fc1a
parent82029948e6d8d047edc02ccff354e16c419e5742 (diff)
helper/bwrap: integrate seccomp into helper interface
This makes API usage much cleaner, and encapsulates all bwrap arguments in argsWt. Signed-off-by: Ophestra <cat@gensokyo.uk>
-rw-r--r--dbus/proxy.go2
-rw-r--r--dbus/run.go2
-rw-r--r--fst/config.go10
-rw-r--r--fst/sandbox.go7
-rw-r--r--helper/bwrap.go41
-rw-r--r--helper/bwrap/arg.go63
-rw-r--r--helper/bwrap/config.go5
-rw-r--r--helper/bwrap/seccomp-export.c (renamed from internal/proc/priv/shim/export.c)2
-rw-r--r--helper/bwrap/seccomp-export.h (renamed from internal/proc/priv/shim/export.h)0
-rw-r--r--helper/bwrap/seccomp-resolve.go95
-rw-r--r--helper/bwrap/seccomp.go (renamed from internal/proc/priv/shim/seccomp.go)12
-rw-r--r--helper/bwrap/sequential.go6
-rw-r--r--helper/bwrap_test.go12
-rw-r--r--internal/app/app_pd_test.go2
-rw-r--r--internal/app/seal.go13
-rw-r--r--internal/app/start.go9
-rw-r--r--internal/proc/priv/shim/main.go120
-rw-r--r--internal/proc/priv/shim/payload.go3
-rw-r--r--internal/system/dbus.go2
-rw-r--r--ldd/exec.go3
-rw-r--r--main.go2
21 files changed, 224 insertions, 187 deletions
diff --git a/dbus/proxy.go b/dbus/proxy.go
index 9f78648c..59b887d2 100644
--- a/dbus/proxy.go
+++ b/dbus/proxy.go
@@ -66,7 +66,7 @@ func (p *Proxy) String() string {
return "(unsealed dbus proxy)"
}
-func (p *Proxy) Bwrap() []string {
+func (p *Proxy) BwrapStatic() []string {
return p.bwrap.Args()
}
diff --git a/dbus/run.go b/dbus/run.go
index addf5226..0a554bfb 100644
--- a/dbus/run.go
+++ b/dbus/run.go
@@ -110,7 +110,7 @@ func (p *Proxy) Start(ready chan error, output io.Writer, sandbox bool) error {
bc.Bind(k, k)
}
- h = helper.MustNewBwrap(bc, toolPath, p.seal, argF, nil)
+ h = helper.MustNewBwrap(bc, toolPath, p.seal, argF, nil, nil)
cmd = h.Unwrap()
p.bwrap = bc
}
diff --git a/fst/config.go b/fst/config.go
index ed0ac4cd..72cb2021 100644
--- a/fst/config.go
+++ b/fst/config.go
@@ -31,8 +31,6 @@ type ConfinementConfig struct {
Outer string `json:"home"`
// bwrap sandbox confinement configuration
Sandbox *SandboxConfig `json:"sandbox"`
- // seccomp syscall filter configuration
- Syscall *SyscallConfig `json:"syscall"`
// extra acl entries to append
ExtraPerms []*ExtraPermConfig `json:"extra_perms,omitempty"`
@@ -47,14 +45,6 @@ type ConfinementConfig struct {
Enablements system.Enablements `json:"enablements"`
}
-type SyscallConfig struct {
- DenyDevel bool `json:"deny_devel"`
- Multiarch bool `json:"multiarch"`
- Linux32 bool `json:"linux32"`
- Can bool `json:"can"`
- Bluetooth bool `json:"bluetooth"`
-}
-
type ExtraPermConfig struct {
Ensure bool `json:"ensure,omitempty"`
Path string `json:"path"`
diff --git a/fst/sandbox.go b/fst/sandbox.go
index 8def9086..0c3918a9 100644
--- a/fst/sandbox.go
+++ b/fst/sandbox.go
@@ -22,6 +22,8 @@ type SandboxConfig struct {
Net bool `json:"net,omitempty"`
// share all devices
Dev bool `json:"dev,omitempty"`
+ // seccomp syscall filter policy
+ Syscall *bwrap.SyscallPolicy `json:"syscall"`
// do not run in new session
NoNewSession bool `json:"no_new_session,omitempty"`
// map target user uid to privileged user uid in the user namespace
@@ -50,6 +52,10 @@ func (s *SandboxConfig) Bwrap(os linux.System) (*bwrap.Config, error) {
return nil, errors.New("nil sandbox config")
}
+ if s.Syscall == nil {
+ fmsg.VPrintln("syscall filter not configured, PROCEED WITH CAUTION")
+ }
+
var uid int
if !s.MapRealUID {
uid = 65534
@@ -69,6 +75,7 @@ func (s *SandboxConfig) Bwrap(os linux.System) (*bwrap.Config, error) {
so this capacity should eliminate copies for most setups */
Filesystem: make([]bwrap.FSBuilder, 0, 256),
+ Syscall: s.Syscall,
NewSession: !s.NoNewSession,
DieWithParent: true,
AsInit: true,
diff --git a/helper/bwrap.go b/helper/bwrap.go
index ad077312..851f2448 100644
--- a/helper/bwrap.go
+++ b/helper/bwrap.go
@@ -9,25 +9,17 @@ import (
"sync"
"git.gensokyo.uk/security/fortify/helper/bwrap"
- "git.gensokyo.uk/security/fortify/internal/proc"
)
// BubblewrapName is the file name or path to bubblewrap.
var BubblewrapName = "bwrap"
-type BwrapExtraFile struct {
- Name string
- File *os.File
-}
-
type bubblewrap struct {
// bwrap child file name
name string
// bwrap pipes
control *pipes
- // extra files with fd passed as argument
- extra []BwrapExtraFile
// returns an array of arguments passed directly
// to the child process spawned by bwrap
argF func(argsFD, statFD int) []string
@@ -54,14 +46,6 @@ func (b *bubblewrap) StartNotify(ready chan error) error {
return errors.New("exec: already started")
}
- // pass extra fd to bwrap
- for _, e := range b.extra {
- if e.File == nil {
- continue
- }
- b.Cmd.Args = append(b.Cmd.Args, e.Name, strconv.Itoa(int(proc.ExtraFile(b.Cmd, e.File))))
- }
-
// prepare bwrap pipe and args
if argsFD, _, err := b.control.prepareCmd(b.Cmd); err != nil {
return err
@@ -130,9 +114,10 @@ func (b *bubblewrap) Unwrap() *exec.Cmd {
func MustNewBwrap(
conf *bwrap.Config, name string,
wt io.WriterTo, argF func(argsFD, statFD int) []string,
- extra []BwrapExtraFile,
+ extraFiles []*os.File,
+ syncFd *os.File,
) Helper {
- b, err := NewBwrap(conf, name, wt, argF, extra)
+ b, err := NewBwrap(conf, name, wt, argF, extraFiles, syncFd)
if err != nil {
panic(err.Error())
} else {
@@ -146,23 +131,27 @@ func MustNewBwrap(
func NewBwrap(
conf *bwrap.Config, name string,
wt io.WriterTo, argF func(argsFD, statFD int) []string,
- extra []BwrapExtraFile,
+ extraFiles []*os.File,
+ syncFd *os.File,
) (Helper, error) {
b := new(bubblewrap)
- if args, err := NewCheckedArgs(conf.Args()); err != nil {
- return nil, err
- } else {
- b.control = &pipes{args: args}
- }
-
- b.extra = extra
b.argF = argF
b.name = name
if wt != nil {
b.controlPt = &pipes{args: wt}
}
+
b.Cmd = execCommand(BubblewrapName)
+ b.control = new(pipes)
+ args := conf.Args()
+ if fdArgs, err := conf.FDArgs(syncFd, &extraFiles); err != nil {
+ return nil, err
+ } else if b.control.args, err = NewCheckedArgs(append(args, fdArgs...)); err != nil {
+ return nil, err
+ } else {
+ b.Cmd.ExtraFiles = extraFiles
+ }
return b, nil
}
diff --git a/helper/bwrap/arg.go b/helper/bwrap/arg.go
index efdab823..d419ba50 100644
--- a/helper/bwrap/arg.go
+++ b/helper/bwrap/arg.go
@@ -1,6 +1,13 @@
package bwrap
-import "encoding/gob"
+import (
+ "encoding/gob"
+ "os"
+ "slices"
+ "strconv"
+
+ "git.gensokyo.uk/security/fortify/internal/proc"
+)
type Builder interface {
Len() int
@@ -12,6 +19,11 @@ type FSBuilder interface {
Builder
}
+type FDBuilder interface {
+ Len() int
+ Append(args *[]string, extraFiles *[]*os.File) error
+}
+
func init() {
gob.Register(new(pairF))
gob.Register(new(stringF))
@@ -45,6 +57,33 @@ func (s stringF) Append(args *[]string) {
*args = append(*args, s[0], s[1])
}
+type fileF struct {
+ name string
+ file *os.File
+}
+
+func (f *fileF) Len() int {
+ if f.file == nil {
+ return 0
+ }
+ return 2
+}
+
+func (f *fileF) Append(args *[]string, extraFiles *[]*os.File) error {
+ if f.file == nil {
+ return nil
+ }
+ extraFile(args, extraFiles, f.name, f.file)
+ return nil
+}
+
+func extraFile(args *[]string, extraFiles *[]*os.File, name string, f *os.File) {
+ if f == nil {
+ return
+ }
+ *args = append(*args, name, strconv.Itoa(int(proc.ExtraFileSlice(extraFiles, f))))
+}
+
// Args returns a slice of bwrap args corresponding to c.
func (c *Config) Args() (args []string) {
builders := []Builder{
@@ -75,3 +114,25 @@ func (c *Config) Args() (args []string) {
return
}
+
+func (c *Config) FDArgs(syncFd *os.File, extraFiles *[]*os.File) (args []string, err error) {
+ builders := []FDBuilder{
+ &seccompBuilder{c},
+ &fileF{positionalArgs[SyncFd], syncFd},
+ }
+
+ argc := 0
+ for _, b := range builders {
+ argc += b.Len()
+ }
+
+ args = make([]string, 0, argc)
+ *extraFiles = slices.Grow(*extraFiles, len(builders))
+
+ for _, b := range builders {
+ if err = b.Append(&args, extraFiles); err != nil {
+ break
+ }
+ }
+ return
+}
diff --git a/helper/bwrap/config.go b/helper/bwrap/config.go
index 8def27a6..b9fa0c12 100644
--- a/helper/bwrap/config.go
+++ b/helper/bwrap/config.go
@@ -47,6 +47,10 @@ type Config struct {
// (--chmod OCTAL PATH)
Chmod ChmodConfig `json:"chmod,omitempty"`
+ // load and use seccomp rules from FD (not repeatable)
+ // (--seccomp FD)
+ Syscall *SyscallPolicy
+
// create a new terminal session
// (--new-session)
NewSession bool `json:"new_session"`
@@ -70,7 +74,6 @@ type Config struct {
--file FD DEST Copy from FD to destination DEST
--bind-data FD DEST Copy from FD to file which is bind-mounted on DEST
--ro-bind-data FD DEST Copy from FD to file which is readonly bind-mounted on DEST
- --seccomp FD Load and use seccomp rules from FD (not repeatable)
--add-seccomp-fd FD Load and use seccomp rules from FD (repeatable)
--block-fd FD Block on FD until some data to read is available
--userns-block-fd FD Block on FD until the user namespace is ready
diff --git a/internal/proc/priv/shim/export.c b/helper/bwrap/seccomp-export.c
index 404dd135..40e3bea9 100644
--- a/internal/proc/priv/shim/export.c
+++ b/helper/bwrap/seccomp-export.c
@@ -2,7 +2,7 @@
#define _GNU_SOURCE // CLONE_NEWUSER
#endif
-#include "export.h"
+#include "seccomp-export.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
diff --git a/internal/proc/priv/shim/export.h b/helper/bwrap/seccomp-export.h
index 5df0dc65..5df0dc65 100644
--- a/internal/proc/priv/shim/export.h
+++ b/helper/bwrap/seccomp-export.h
diff --git a/helper/bwrap/seccomp-resolve.go b/helper/bwrap/seccomp-resolve.go
new file mode 100644
index 00000000..995a3719
--- /dev/null
+++ b/helper/bwrap/seccomp-resolve.go
@@ -0,0 +1,95 @@
+package bwrap
+
+import (
+ "fmt"
+ "io"
+ "os"
+
+ "git.gensokyo.uk/security/fortify/internal/fmsg"
+)
+
+type SyscallPolicy struct {
+ DenyDevel bool `json:"deny_devel"`
+ Multiarch bool `json:"multiarch"`
+ Linux32 bool `json:"linux32"`
+ Can bool `json:"can"`
+ Bluetooth bool `json:"bluetooth"`
+}
+
+type seccompBuilder struct {
+ config *Config
+}
+
+func (s *seccompBuilder) Len() int {
+ if s == nil {
+ return 0
+ }
+ return 2
+}
+
+func (s *seccompBuilder) Append(args *[]string, extraFiles *[]*os.File) error {
+ if s == nil {
+ return nil
+ }
+ if f, err := s.config.resolveSeccomp(); err != nil {
+ return err
+ } else {
+ extraFile(args, extraFiles, positionalArgs[Seccomp], f)
+ return nil
+ }
+}
+
+func (c *Config) resolveSeccomp() (*os.File, error) {
+ if c.Syscall == nil {
+ return nil, nil
+ }
+
+ // resolve seccomp filter opts
+ var (
+ opts syscallOpts
+ optd []string
+ optCond = [...]struct {
+ v bool
+ o syscallOpts
+ d string
+ }{
+ {!c.UserNS, flagDenyNS, "denyns"},
+ {c.NewSession, flagDenyTTY, "denytty"},
+ {c.Syscall.DenyDevel, flagDenyDevel, "denydevel"},
+ {c.Syscall.Multiarch, flagMultiarch, "multiarch"},
+ {c.Syscall.Linux32, flagLinux32, "linux32"},
+ {c.Syscall.Can, flagCan, "can"},
+ {c.Syscall.Bluetooth, flagBluetooth, "bluetooth"},
+ }
+ )
+ if CPrintln != nil {
+ optd = make([]string, 1, len(optCond)+1)
+ optd[0] = "common"
+ }
+ for _, opt := range optCond {
+ if opt.v {
+ opts |= opt.o
+ if fmsg.Verbose() {
+ optd = append(optd, opt.d)
+ }
+ }
+ }
+ if CPrintln != nil {
+ CPrintln(fmt.Sprintf("seccomp flags: %s", optd))
+ }
+
+ // export seccomp filter to tmpfile
+ if f, err := tmpfile(); err != nil {
+ return nil, err
+ } else {
+ return f, exportAndSeek(f, opts)
+ }
+}
+
+func exportAndSeek(f *os.File, opts syscallOpts) error {
+ if err := exportFilter(f.Fd(), opts); err != nil {
+ return err
+ }
+ _, err := f.Seek(0, io.SeekStart)
+ return err
+}
diff --git a/internal/proc/priv/shim/seccomp.go b/helper/bwrap/seccomp.go
index bf458742..abc2738b 100644
--- a/internal/proc/priv/shim/seccomp.go
+++ b/helper/bwrap/seccomp.go
@@ -1,9 +1,9 @@
-package shim
+package bwrap
/*
#cgo linux pkg-config: --static libseccomp
-#include "export.h"
+#include "seccomp-export.h"
*/
import "C"
import (
@@ -11,10 +11,10 @@ import (
"fmt"
"os"
"runtime"
-
- "git.gensokyo.uk/security/fortify/internal/fmsg"
)
+var CPrintln func(v ...any)
+
var resErr = [...]error{
0: nil,
1: errors.New("seccomp_init failed"),
@@ -77,5 +77,7 @@ func exportFilter(fd uintptr, opts syscallOpts) error {
//export F_println
func F_println(v *C.char) {
- fmsg.VPrintln(C.GoString(v))
+ if CPrintln != nil {
+ CPrintln(C.GoString(v))
+ }
}
diff --git a/helper/bwrap/sequential.go b/helper/bwrap/sequential.go
index 42a4b2b5..1776c235 100644
--- a/helper/bwrap/sequential.go
+++ b/helper/bwrap/sequential.go
@@ -43,6 +43,9 @@ const (
Overlay
TmpOverlay
ROOverlay
+
+ SyncFd
+ Seccomp
)
var positionalArgs = [...]string{
@@ -70,6 +73,9 @@ var positionalArgs = [...]string{
Overlay: "--overlay",
TmpOverlay: "--tmp-overlay",
ROOverlay: "--ro-overlay",
+
+ SyncFd: "--sync-fd",
+ Seccomp: "--seccomp",
}
type PermConfig[T FSBuilder] struct {
diff --git a/helper/bwrap_test.go b/helper/bwrap_test.go
index 9a565a42..0860d57a 100644
--- a/helper/bwrap_test.go
+++ b/helper/bwrap_test.go
@@ -34,7 +34,7 @@ func TestBwrap(t *testing.T) {
h := helper.MustNewBwrap(
sc, "fortify",
argsWt, argF,
- nil,
+ nil, nil,
)
if err := h.Start(); !errors.Is(err, os.ErrNotExist) {
@@ -47,7 +47,7 @@ func TestBwrap(t *testing.T) {
if got := helper.MustNewBwrap(
sc, "fortify",
argsWt, argF,
- nil,
+ nil, nil,
); got == nil {
t.Errorf("MustNewBwrap(%#v, %#v, %#v) got nil",
sc, argsWt, "fortify")
@@ -67,7 +67,7 @@ func TestBwrap(t *testing.T) {
helper.MustNewBwrap(
&bwrap.Config{Hostname: "\x00"}, "fortify",
nil, argF,
- nil,
+ nil, nil,
)
})
@@ -84,7 +84,7 @@ func TestBwrap(t *testing.T) {
helper.MustNewBwrap(
sc, "fortify",
nil, argF,
- nil,
+ nil, nil,
).StartNotify(make(chan error))))
})
@@ -94,7 +94,7 @@ func TestBwrap(t *testing.T) {
h := helper.MustNewBwrap(
sc, "crash-test-dummy",
nil, argFChecked,
- nil,
+ nil, nil,
)
cmd := h.Unwrap()
@@ -127,6 +127,6 @@ func TestBwrap(t *testing.T) {
})
t.Run("implementation compliance", func(t *testing.T) {
- testHelper(t, func() helper.Helper { return helper.MustNewBwrap(sc, "crash-test-dummy", argsWt, argF, nil) })
+ testHelper(t, func() helper.Helper { return helper.MustNewBwrap(sc, "crash-test-dummy", argsWt, argF, nil, nil) })
})
}
diff --git a/internal/app/app_pd_test.go b/internal/app/app_pd_test.go
index 968a11ab..98ddf31f 100644
--- a/internal/app/app_pd_test.go
+++ b/internal/app/app_pd_test.go
@@ -39,6 +39,7 @@ var testCasesPd = []sealTestCase{
Net: true,
UserNS: true,
Clearenv: true,
+ Syscall: new(bwrap.SyscallPolicy),
Chdir: "/home/chronos",
SetEnv: map[string]string{
"HOME": "/home/chronos",
@@ -258,6 +259,7 @@ var testCasesPd = []sealTestCase{
UserNS: true,
Chdir: "/home/chronos",
Clearenv: true,
+ Syscall: new(bwrap.SyscallPolicy),
SetEnv: map[string]string{
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/65534/bus",
"DBUS_SYSTEM_BUS_ADDRESS": "unix:path=/run/dbus/system_bus_socket",
diff --git a/internal/app/seal.go b/internal/app/seal.go
index bd0522a6..228be5c9 100644
--- a/internal/app/seal.go
+++ b/internal/app/seal.go
@@ -14,6 +14,7 @@ import (
"git.gensokyo.uk/security/fortify/acl"
"git.gensokyo.uk/security/fortify/dbus"
"git.gensokyo.uk/security/fortify/fst"
+ "git.gensokyo.uk/security/fortify/helper/bwrap"
"git.gensokyo.uk/security/fortify/internal/fmsg"
"git.gensokyo.uk/security/fortify/internal/linux"
"git.gensokyo.uk/security/fortify/internal/state"
@@ -52,8 +53,6 @@ type appSeal struct {
et system.Enablements
// initial config gob encoding buffer
ct io.WriterTo
- // pass-through seccomp config from config
- scmp *fst.SyscallConfig
// wayland socket direct access
directWayland bool
// extra UpdatePerm ops
@@ -196,6 +195,7 @@ func (a *app) Seal(config *fst.Config) error {
conf := &fst.SandboxConfig{
UserNS: true,
Net: true,
+ Syscall: new(bwrap.SyscallPolicy),
NoNewSession: true,
AutoEtc: true,
}
@@ -233,12 +233,6 @@ func (a *app) Seal(config *fst.Config) error {
conf.Filesystem = append(conf.Filesystem, &fst.FilesystemConfig{Src: "/dev/kvm", Device: true})
config.Confinement.Sandbox = conf
-
- // ensure syscall filter
- if config.Confinement.Syscall == nil {
- config.Confinement.Syscall = new(fst.SyscallConfig)
- config.Confinement.Syscall.Multiarch = true
- }
}
seal.directWayland = config.Confinement.Sandbox.DirectWayland
if b, err := config.Confinement.Sandbox.Bwrap(a.os); err != nil {
@@ -259,9 +253,8 @@ func (a *app) Seal(config *fst.Config) error {
// initialise system interface with full uid
seal.sys.I = system.New(seal.sys.user.uid)
- // pass through enablements and seccomp
+ // pass through enablements
seal.et = config.Confinement.Enablements
- seal.scmp = config.Confinement.Syscall
// this method calls all share methods in sequence
if err := seal.setupShares([2]*dbus.Config{config.Confinement.SessionBus, config.Confinement.SystemBus}, a.os); err != nil {
diff --git a/internal/app/start.go b/internal/app/start.go
index 87bb6fde..d0a0116d 100644
--- a/internal/app/start.go
+++ b/internal/app/start.go
@@ -76,11 +76,10 @@ func (a *app) Run(ctx context.Context, rs *RunState) error {
// send payload
if err = a.shim.Serve(shimSetupCtx, &shim.Payload{
- Argv: a.seal.command,
- Exec: shimExec,
- Bwrap: a.seal.sys.bwrap,
- Home: a.seal.sys.user.data,
- Syscall: a.seal.scmp,
+ Argv: a.seal.command,
+ Exec: shimExec,
+ Bwrap: a.seal.sys.bwrap,
+ Home: a.seal.sys.user.data,
Verbose: fmsg.Verbose(),
}); err != nil {
diff --git a/internal/proc/priv/shim/main.go b/internal/proc/priv/shim/main.go
index a92a3cfa..85c5bafe 100644
--- a/internal/proc/priv/shim/main.go
+++ b/internal/proc/priv/shim/main.go
@@ -2,8 +2,6 @@ package shim
import (
"errors"
- "flag"
- "io"
"os"
"path"
"strconv"
@@ -20,7 +18,7 @@ import (
// everything beyond this point runs as unconstrained target user
// proceed with caution!
-func Main(args []string) {
+func Main() {
// sharing stdout with fortify
// USE WITH CAUTION
fmsg.SetPrefix("shim")
@@ -31,46 +29,6 @@ func Main(args []string) {
panic("unreachable")
}
- set := flag.NewFlagSet("shim", flag.ExitOnError)
-
- // debug: export seccomp filter
- debugExportSeccomp := set.String("export-seccomp", "", "export the seccomp filter to file")
- debugExportSeccompFlags := [...]struct {
- o syscallOpts
- v *bool
- }{
- {flagDenyNS, set.Bool("deny-ns", false, "deny namespace-related syscalls")},
- {flagDenyTTY, set.Bool("deny-tty", false, "deny faking input ioctls")},
- {flagDenyDevel, set.Bool("deny-devel", false, "deny development syscalls")},
- {flagMultiarch, set.Bool("multiarch", false, "allow multiarch")},
- {flagLinux32, set.Bool("linux32", false, "allow PER_LINUX32")},
- {flagCan, set.Bool("can", false, "allow AF_CAN")},
- {flagBluetooth, set.Bool("bluetooth", false, "AF_BLUETOOTH")},
- }
-
- // Ignore errors; set is set for ExitOnError.
- _ = set.Parse(args[1:])
-
- // debug: export seccomp filter
- if *debugExportSeccomp != "" {
- var opts syscallOpts
- for _, opt := range debugExportSeccompFlags {
- if *opt.v {
- opts |= opt.o
- }
- }
-
- if f, err := os.Create(*debugExportSeccomp); err != nil {
- fmsg.Fatalf("cannot create %q: %v", *debugExportSeccomp, err)
- } else {
- mustExportFilter(f, opts)
- if err = f.Close(); err != nil {
- fmsg.Fatalf("cannot close %q: %v", *debugExportSeccomp, err)
- }
- }
- fmsg.Exit(0)
- }
-
// receive setup payload
var (
payload Payload
@@ -169,23 +127,19 @@ func Main(args []string) {
conf.Symlink("fortify", innerInit)
helper.BubblewrapName = payload.Exec[0] // resolved bwrap path by parent
+ if fmsg.Verbose() {
+ bwrap.CPrintln = fmsg.Println
+ }
if b, err := helper.NewBwrap(
conf, innerInit,
nil, func(int, int) []string { return make([]string, 0) },
- []helper.BwrapExtraFile{
- // keep this fd open while sandbox is running
- // (--sync-fd FD)
- {"--sync-fd", syncFd},
- // load and use seccomp rules from FD (not repeatable)
- // (--seccomp FD)
- {"--seccomp", mustResolveSeccomp(payload.Bwrap, payload.Syscall)},
- },
+ extraFiles,
+ syncFd,
); err != nil {
fmsg.Fatalf("malformed sandbox config: %v", err)
} else {
cmd := b.Unwrap()
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
- cmd.ExtraFiles = extraFiles
// run and pass through exit code
if err = b.Start(); err != nil {
@@ -200,65 +154,3 @@ func Main(args []string) {
}
}
}
-
-func mustResolveSeccomp(bwrap *bwrap.Config, syscall *fst.SyscallConfig) (seccompFd *os.File) {
- if syscall == nil {
- fmsg.VPrintln("syscall filter not configured, PROCEED WITH CAUTION")
- return
- }
-
- // resolve seccomp filter opts
- var (
- opts syscallOpts
- optd []string
- optCond = [...]struct {
- v bool
- o syscallOpts
- d string
- }{
- {!bwrap.UserNS, flagDenyNS, "denyns"},
- {bwrap.NewSession, flagDenyTTY, "denytty"},
- {syscall.DenyDevel, flagDenyDevel, "denydevel"},
- {syscall.Multiarch, flagMultiarch, "multiarch"},
- {syscall.Linux32, flagLinux32, "linux32"},
- {syscall.Can, flagCan, "can"},
- {syscall.Bluetooth, flagBluetooth, "bluetooth"},
- }
- )
- if fmsg.Verbose() {
- optd = make([]string, 1, len(optCond)+1)
- optd[0] = "fortify"
- }
- for _, opt := range optCond {
- if opt.v {
- opts |= opt.o
- if fmsg.Verbose() {
- optd = append(optd, opt.d)
- }
- }
- }
- if fmsg.Verbose() {
- fmsg.VPrintf("seccomp flags: %s", optd)
- }
-
- // export seccomp filter to tmpfile
- if f, err := tmpfile(); err != nil {
- fmsg.Fatalf("cannot create tmpfile: %v", err)
- panic("unreachable")
- } else {
- mustExportFilter(f, opts)
- seccompFd = f
- return
- }
-}
-
-func mustExportFilter(f *os.File, opts syscallOpts) {
- if err := exportFilter(f.Fd(), opts); err != nil {
- fmsg.Fatalf("cannot export seccomp filter: %v", err)
- panic("unreachable")
- }
- if _, err := f.Seek(0, io.SeekStart); err != nil {
- fmsg.Fatalf("cannot lseek seccomp file: %v", err)
- panic("unreachable")
- }
-}
diff --git a/internal/proc/priv/shim/payload.go b/internal/proc/priv/shim/payload.go
index 2d6854f9..e659e3fd 100644
--- a/internal/proc/priv/shim/payload.go
+++ b/internal/proc/priv/shim/payload.go
@@ -1,7 +1,6 @@
package shim
import (
- "git.gensokyo.uk/security/fortify/fst"
"git.gensokyo.uk/security/fortify/helper/bwrap"
)
@@ -18,8 +17,6 @@ type Payload struct {
Home string
// sync fd
Sync *uintptr
- // seccomp opts pass through
- Syscall *fst.SyscallConfig
// verbosity pass through
Verbose bool
diff --git a/internal/system/dbus.go b/internal/system/dbus.go
index 3bed540a..b74d5d30 100644
--- a/internal/system/dbus.go
+++ b/internal/system/dbus.go
@@ -99,7 +99,7 @@ func (d *DBus) apply(_ *I) error {
}
fmsg.VPrintln("starting message bus proxy:", d.proxy)
if fmsg.Verbose() { // save the extra bwrap arg build when verbose logging is off
- fmsg.VPrintln("message bus proxy bwrap args:", d.proxy.Bwrap())
+ fmsg.VPrintln("message bus proxy bwrap args:", d.proxy.BwrapStatic())
}
// background wait for proxy instance and notify completion
diff --git a/ldd/exec.go b/ldd/exec.go
index eec31e47..23c4e892 100644
--- a/ldd/exec.go
+++ b/ldd/exec.go
@@ -23,7 +23,8 @@ func Exec(p string) ([]*Entry, error) {
NewSession: true,
DieWithParent: true,
}).Bind("/", "/").DevTmpfs("/dev"), "ldd",
- nil, func(_, _ int) []string { return []string{p} }, nil,
+ nil, func(_, _ int) []string { return []string{p} },
+ nil, nil,
); err != nil {
return nil, err
} else {
diff --git a/main.go b/main.go
index 8909e5b4..e6e856b6 100644
--- a/main.go
+++ b/main.go
@@ -291,7 +291,7 @@ func main() {
// internal commands
case "shim":
- shim.Main(args)
+ shim.Main()
fmsg.Exit(0)
case "init":
init0.Main()