diff --git a/cmd/fpkg/main.go b/cmd/fpkg/main.go index 480833b..2fbefdb 100644 --- a/cmd/fpkg/main.go +++ b/cmd/fpkg/main.go @@ -19,7 +19,6 @@ import ( "git.gensokyo.uk/security/fortify/internal/fmsg" "git.gensokyo.uk/security/fortify/internal/sandbox" "git.gensokyo.uk/security/fortify/internal/sys" - "git.gensokyo.uk/security/fortify/seccomp" ) const shellPath = "/run/current-system/sw/bin/bash" @@ -60,10 +59,7 @@ func main() { flagDropShell bool ) c := command.New(os.Stderr, log.Printf, "fpkg", func([]string) error { - fmsg.Store(flagVerbose) - if flagVerbose { - seccomp.CPrintln = log.Println - } + internal.InstallFmsg(flagVerbose) return nil }). Flag(&flagVerbose, "v", command.BoolFlag(false), "Print debug messages to the console"). diff --git a/helper/bwrap/config_test.go b/helper/bwrap/config_test.go index 678f49d..7e78c8f 100644 --- a/helper/bwrap/config_test.go +++ b/helper/bwrap/config_test.go @@ -1,7 +1,6 @@ package bwrap_test import ( - "log" "os" "slices" "testing" @@ -12,8 +11,9 @@ import ( ) func TestConfig_Args(t *testing.T) { - seccomp.CPrintln = log.Println - t.Cleanup(func() { seccomp.CPrintln = nil }) + oldF := seccomp.GetOutput() + seccomp.SetOutput(t.Log) + t.Cleanup(func() { seccomp.SetOutput(oldF) }) testCases := []struct { name string diff --git a/helper/bwrap/seccomp.go b/helper/bwrap/seccomp.go index 8e55171..f5132be 100644 --- a/helper/bwrap/seccomp.go +++ b/helper/bwrap/seccomp.go @@ -48,20 +48,21 @@ func (c *Config) seccompArgs() FDBuilder { {c.Syscall.Bluetooth, seccomp.FlagBluetooth, "bluetooth"}, } ) - if seccomp.CPrintln != nil { + scmpPrintln := seccomp.GetOutput() + if scmpPrintln != nil { optd = make([]string, 1, len(optCond)+1) optd[0] = "common" } for _, opt := range optCond { if opt.v { opts |= opt.o - if seccomp.CPrintln != nil { + if scmpPrintln != nil { optd = append(optd, opt.d) } } } - if seccomp.CPrintln != nil { - seccomp.CPrintln(fmt.Sprintf("seccomp flags: %s", optd)) + if scmpPrintln != nil { + scmpPrintln(fmt.Sprintf("seccomp flags: %s", optd)) } return &seccompBuilder{seccomp.NewFile(opts)} diff --git a/internal/app/shim/main.go b/internal/app/shim/main.go index 6cbb147..64df53d 100644 --- a/internal/app/shim/main.go +++ b/internal/app/shim/main.go @@ -17,7 +17,6 @@ import ( "git.gensokyo.uk/security/fortify/internal" "git.gensokyo.uk/security/fortify/internal/app/init0" "git.gensokyo.uk/security/fortify/internal/fmsg" - "git.gensokyo.uk/security/fortify/seccomp" ) // everything beyond this point runs as unconstrained target user @@ -48,7 +47,7 @@ func Main() { log.Fatalf("cannot decode shim setup payload: %v", err) } else { - fmsg.Store(payload.Verbose) + internal.InstallFmsg(payload.Verbose) closeSetup = f } @@ -121,9 +120,6 @@ func Main() { } helper.BubblewrapName = payload.Exec[0] // resolved bwrap path by parent - if fmsg.Load() { - seccomp.CPrintln = log.Println - } ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() // unreachable diff --git a/internal/output.go b/internal/output.go new file mode 100644 index 0000000..db37f55 --- /dev/null +++ b/internal/output.go @@ -0,0 +1,13 @@ +package internal + +import ( + "git.gensokyo.uk/security/fortify/internal/fmsg" + "git.gensokyo.uk/security/fortify/seccomp" +) + +func InstallFmsg(verbose bool) { + fmsg.Store(verbose) + if verbose { + seccomp.SetOutput(fmsg.Verbose) + } +} diff --git a/internal/sandbox/init.go b/internal/sandbox/init.go index 0249e58..85fcb13 100644 --- a/internal/sandbox/init.go +++ b/internal/sandbox/init.go @@ -72,11 +72,8 @@ func Init(exit func(code int)) { log.Fatal("invalid setup parameters") } - fmsg.Store(params.Verbose) + internal.InstallFmsg(params.Verbose) fmsg.Verbose("received setup parameters") - if params.Verbose { - seccomp.CPrintln = fmsg.Verbose - } closeSetup = f offsetSetup = int(setupFile.Fd() + 1) } diff --git a/main.go b/main.go index ac5532e..1a7e853 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,6 @@ import ( "git.gensokyo.uk/security/fortify/internal/sandbox" "git.gensokyo.uk/security/fortify/internal/state" "git.gensokyo.uk/security/fortify/internal/sys" - "git.gensokyo.uk/security/fortify/seccomp" "git.gensokyo.uk/security/fortify/system" ) @@ -71,10 +70,7 @@ func buildCommand(out io.Writer) command.Command { flagJSON bool ) c := command.New(out, log.Printf, "fortify", func([]string) error { - fmsg.Store(flagVerbose) - if flagVerbose { - seccomp.CPrintln = log.Println - } + internal.InstallFmsg(flagVerbose) return nil }). Flag(&flagVerbose, "v", command.BoolFlag(false), "Print debug messages to the console"). diff --git a/seccomp/export_test.go b/seccomp/export_test.go index 991517f..34bb306 100644 --- a/seccomp/export_test.go +++ b/seccomp/export_test.go @@ -4,7 +4,6 @@ import ( "crypto/sha512" "errors" "io" - "log" "slices" "syscall" "testing" @@ -79,8 +78,9 @@ func TestExport(t *testing.T) { buf := make([]byte, 8) for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - seccomp.CPrintln = log.Println - t.Cleanup(func() { seccomp.CPrintln = nil }) + oldF := seccomp.GetOutput() + seccomp.SetOutput(t.Log) + t.Cleanup(func() { seccomp.SetOutput(oldF) }) e := seccomp.New(tc.opts) digest := sha512.New() diff --git a/seccomp/output.go b/seccomp/output.go new file mode 100644 index 0000000..d583c9e --- /dev/null +++ b/seccomp/output.go @@ -0,0 +1,30 @@ +package seccomp + +import "C" +import "sync/atomic" + +var printlnP atomic.Pointer[func(v ...any)] + +func SetOutput(f func(v ...any)) { + if f == nil { + // avoid storing nil function + printlnP.Store(nil) + } else { + printlnP.Store(&f) + } +} + +func GetOutput() func(v ...any) { + if fp := printlnP.Load(); fp == nil { + return nil + } else { + return *fp + } +} + +//export F_println +func F_println(v *C.char) { + if fp := printlnP.Load(); fp != nil { + (*fp)(C.GoString(v)) + } +} diff --git a/seccomp/seccomp.go b/seccomp/seccomp.go index 05c314c..2e73047 100644 --- a/seccomp/seccomp.go +++ b/seccomp/seccomp.go @@ -13,8 +13,6 @@ import ( "syscall" ) -var CPrintln func(v ...any) - // LibraryError represents a libseccomp error. type LibraryError struct { Prefix string @@ -99,7 +97,7 @@ func buildFilter(fd int, opts SyscallOpts) error { // this removes repeated transitions between C and Go execution // when producing log output via F_println and CPrintln is nil - if CPrintln != nil { + if fp := printlnP.Load(); fp != nil { opts |= flagVerbose } @@ -114,10 +112,3 @@ func buildFilter(fd int, opts SyscallOpts) error { } return err } - -//export F_println -func F_println(v *C.char) { - if CPrintln != nil { - CPrintln(C.GoString(v)) - } -}