fmsg: produce all output through fmsg
test / test (push) Successful in 17s
Details
test / test (push) Successful in 17s
Details
The behaviour of print functions from package fmt is not thread safe. Functions provided by fmsg wrap around Logger methods. This makes prefix much cleaner and makes it easy to deal with future changes to logging. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
This commit is contained in:
parent
380d1f4585
commit
42e0b168e3
11
config.go
11
config.go
|
@ -9,6 +9,7 @@ import (
|
||||||
"git.ophivana.moe/security/fortify/dbus"
|
"git.ophivana.moe/security/fortify/dbus"
|
||||||
"git.ophivana.moe/security/fortify/internal"
|
"git.ophivana.moe/security/fortify/internal"
|
||||||
"git.ophivana.moe/security/fortify/internal/app"
|
"git.ophivana.moe/security/fortify/internal/app"
|
||||||
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
"git.ophivana.moe/security/fortify/internal/system"
|
"git.ophivana.moe/security/fortify/internal/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ func init() {
|
||||||
func tryTemplate() {
|
func tryTemplate() {
|
||||||
if printTemplate {
|
if printTemplate {
|
||||||
if s, err := json.MarshalIndent(app.Template(), "", " "); err != nil {
|
if s, err := json.MarshalIndent(app.Template(), "", " "); err != nil {
|
||||||
fatalf("cannot generate template: %v", err)
|
fmsg.Fatalf("cannot generate template: %v", err)
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(string(s))
|
fmt.Println(string(s))
|
||||||
|
@ -77,10 +78,10 @@ func loadConfig() *app.Config {
|
||||||
// config from file
|
// config from file
|
||||||
c := new(app.Config)
|
c := new(app.Config)
|
||||||
if f, err := os.Open(confPath); err != nil {
|
if f, err := os.Open(confPath); err != nil {
|
||||||
fatalf("cannot access config file '%s': %s\n", confPath, err)
|
fmsg.Fatalf("cannot access config file %q: %s", confPath, err)
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
} else if err = json.NewDecoder(f).Decode(&c); err != nil {
|
} else if err = json.NewDecoder(f).Decode(&c); err != nil {
|
||||||
fatalf("cannot parse config file '%s': %s\n", confPath, err)
|
fmsg.Fatalf("cannot parse config file %q: %s", confPath, err)
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
} else {
|
} else {
|
||||||
return c
|
return c
|
||||||
|
@ -110,7 +111,7 @@ func configFromFlags() (config *app.Config) {
|
||||||
config.Confinement.SessionBus = dbus.NewConfig(dbusID, true, mpris)
|
config.Confinement.SessionBus = dbus.NewConfig(dbusID, true, mpris)
|
||||||
} else {
|
} else {
|
||||||
if c, err := dbus.NewConfigFromFile(dbusConfigSession); err != nil {
|
if c, err := dbus.NewConfigFromFile(dbusConfigSession); err != nil {
|
||||||
fatalf("cannot load session bus proxy config from %q: %s\n", dbusConfigSession, err)
|
fmsg.Fatalf("cannot load session bus proxy config from %q: %s", dbusConfigSession, err)
|
||||||
} else {
|
} else {
|
||||||
config.Confinement.SessionBus = c
|
config.Confinement.SessionBus = c
|
||||||
}
|
}
|
||||||
|
@ -119,7 +120,7 @@ func configFromFlags() (config *app.Config) {
|
||||||
// system bus proxy is optional
|
// system bus proxy is optional
|
||||||
if dbusConfigSystem != "nil" {
|
if dbusConfigSystem != "nil" {
|
||||||
if c, err := dbus.NewConfigFromFile(dbusConfigSystem); err != nil {
|
if c, err := dbus.NewConfigFromFile(dbusConfigSystem); err != nil {
|
||||||
fatalf("cannot load system bus proxy config from %q: %s\n", dbusConfigSystem, err)
|
fmsg.Fatalf("cannot load system bus proxy config from %q: %s", dbusConfigSystem, err)
|
||||||
} else {
|
} else {
|
||||||
config.Confinement.SystemBus = c
|
config.Confinement.SystemBus = c
|
||||||
}
|
}
|
||||||
|
|
18
error.go
18
error.go
|
@ -3,7 +3,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal/app"
|
"git.ophivana.moe/security/fortify/internal/app"
|
||||||
"git.ophivana.moe/security/fortify/internal/fmsg"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
|
@ -12,13 +11,13 @@ import (
|
||||||
func logWaitError(err error) {
|
func logWaitError(err error) {
|
||||||
var e *fmsg.BaseError
|
var e *fmsg.BaseError
|
||||||
if !fmsg.AsBaseError(err, &e) {
|
if !fmsg.AsBaseError(err, &e) {
|
||||||
fmt.Println("fortify: wait failed:", err)
|
fmsg.Println("wait failed:", err)
|
||||||
} else {
|
} else {
|
||||||
// Wait only returns either *app.ProcessError or *app.StateStoreError wrapped in a *app.BaseError
|
// Wait only returns either *app.ProcessError or *app.StateStoreError wrapped in a *app.BaseError
|
||||||
var se *app.StateStoreError
|
var se *app.StateStoreError
|
||||||
if !errors.As(err, &se) {
|
if !errors.As(err, &se) {
|
||||||
// does not need special handling
|
// does not need special handling
|
||||||
fmt.Print("fortify: " + e.Message())
|
fmsg.Print(e.Message())
|
||||||
} else {
|
} else {
|
||||||
// inner error are either unwrapped store errors
|
// inner error are either unwrapped store errors
|
||||||
// or joined errors returned by *appSealTx revert
|
// or joined errors returned by *appSealTx revert
|
||||||
|
@ -26,7 +25,7 @@ func logWaitError(err error) {
|
||||||
var ej app.RevertCompoundError
|
var ej app.RevertCompoundError
|
||||||
if !errors.As(se.InnerErr, &ej) {
|
if !errors.As(se.InnerErr, &ej) {
|
||||||
// does not require special handling
|
// does not require special handling
|
||||||
fmt.Print("fortify: " + e.Message())
|
fmsg.Print(e.Message())
|
||||||
} else {
|
} else {
|
||||||
errs := ej.Unwrap()
|
errs := ej.Unwrap()
|
||||||
|
|
||||||
|
@ -35,10 +34,10 @@ func logWaitError(err error) {
|
||||||
var eb *fmsg.BaseError
|
var eb *fmsg.BaseError
|
||||||
if !errors.As(ei, &eb) {
|
if !errors.As(ei, &eb) {
|
||||||
// unreachable
|
// unreachable
|
||||||
fmt.Println("fortify: invalid error type returned by revert:", ei)
|
fmsg.Println("invalid error type returned by revert:", ei)
|
||||||
} else {
|
} else {
|
||||||
// print inner *app.BaseError message
|
// print inner *app.BaseError message
|
||||||
fmt.Print("fortify: " + eb.Message())
|
fmsg.Print(eb.Message())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,13 +49,8 @@ func logBaseError(err error, message string) {
|
||||||
var e *fmsg.BaseError
|
var e *fmsg.BaseError
|
||||||
|
|
||||||
if fmsg.AsBaseError(err, &e) {
|
if fmsg.AsBaseError(err, &e) {
|
||||||
fmt.Print("fortify: " + e.Message())
|
fmsg.Print(e.Message())
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(message, err)
|
fmt.Println(message, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fatalf(format string, a ...any) {
|
|
||||||
fmt.Printf("fortify: "+format, a...)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *app) commandBuilderMachineCtl(shimEnv string) (args []string) {
|
func (a *app) commandBuilderMachineCtl(shimEnv string) (args []string) {
|
||||||
|
@ -14,7 +14,7 @@ func (a *app) commandBuilderMachineCtl(shimEnv string) (args []string) {
|
||||||
args = append(args, "shell", "--uid="+a.seal.sys.user.Username)
|
args = append(args, "shell", "--uid="+a.seal.sys.user.Username)
|
||||||
|
|
||||||
// --quiet
|
// --quiet
|
||||||
if !verbose.Get() {
|
if !fmsg.Verbose() {
|
||||||
args = append(args, "--quiet")
|
args = append(args, "--quiet")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package app
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -18,7 +18,7 @@ func (a *app) commandBuilderSudo(shimEnv string) (args []string) {
|
||||||
|
|
||||||
// -A?
|
// -A?
|
||||||
if _, ok := os.LookupEnv(sudoAskPass); ok {
|
if _, ok := os.LookupEnv(sudoAskPass); ok {
|
||||||
verbose.Printf("%s set, adding askpass flag\n", sudoAskPass)
|
fmsg.VPrintln(sudoAskPass, "set, adding askpass flag")
|
||||||
args = append(args, "-A")
|
args = append(args, "-A")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"git.ophivana.moe/security/fortify/internal/shim"
|
"git.ophivana.moe/security/fortify/internal/shim"
|
||||||
"git.ophivana.moe/security/fortify/internal/state"
|
"git.ophivana.moe/security/fortify/internal/state"
|
||||||
"git.ophivana.moe/security/fortify/internal/system"
|
"git.ophivana.moe/security/fortify/internal/system"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -152,7 +151,7 @@ func (a *app) Seal(config *Config) error {
|
||||||
|
|
||||||
// map sandbox config to bwrap
|
// map sandbox config to bwrap
|
||||||
if config.Confinement.Sandbox == nil {
|
if config.Confinement.Sandbox == nil {
|
||||||
verbose.Println("sandbox configuration not supplied, PROCEED WITH CAUTION")
|
fmsg.VPrintln("sandbox configuration not supplied, PROCEED WITH CAUTION")
|
||||||
|
|
||||||
// permissive defaults
|
// permissive defaults
|
||||||
conf := &SandboxConfig{
|
conf := &SandboxConfig{
|
||||||
|
@ -242,7 +241,7 @@ func (a *app) Seal(config *Config) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// verbose log seal information
|
// verbose log seal information
|
||||||
verbose.Println("created application seal as user",
|
fmsg.VPrintln("created application seal as user",
|
||||||
seal.sys.user.Username, "("+seal.sys.user.Uid+"),",
|
seal.sys.user.Username, "("+seal.sys.user.Uid+"),",
|
||||||
"method:", config.Method+",",
|
"method:", config.Method+",",
|
||||||
"launcher:", seal.toolPath+",",
|
"launcher:", seal.toolPath+",",
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -16,7 +15,6 @@ import (
|
||||||
"git.ophivana.moe/security/fortify/internal/shim"
|
"git.ophivana.moe/security/fortify/internal/shim"
|
||||||
"git.ophivana.moe/security/fortify/internal/state"
|
"git.ophivana.moe/security/fortify/internal/state"
|
||||||
"git.ophivana.moe/security/fortify/internal/system"
|
"git.ophivana.moe/security/fortify/internal/system"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Start starts the fortified child
|
// Start starts the fortified child
|
||||||
|
@ -71,14 +69,14 @@ func (a *app) Start() error {
|
||||||
Bwrap: a.seal.sys.bwrap,
|
Bwrap: a.seal.sys.bwrap,
|
||||||
WL: a.seal.wl != nil,
|
WL: a.seal.wl != nil,
|
||||||
|
|
||||||
Verbose: verbose.Get(),
|
Verbose: fmsg.Verbose(),
|
||||||
}, a.seal.wl); err != nil {
|
}, a.seal.wl); err != nil {
|
||||||
return fmsg.WrapErrorSuffix(err,
|
return fmsg.WrapErrorSuffix(err,
|
||||||
"cannot serve shim setup:")
|
"cannot serve shim setup:")
|
||||||
}
|
}
|
||||||
|
|
||||||
// start shim
|
// start shim
|
||||||
verbose.Println("starting shim as target user:", a.cmd)
|
fmsg.VPrintln("starting shim as target user:", a.cmd)
|
||||||
if err := a.cmd.Start(); err != nil {
|
if err := a.cmd.Start(); err != nil {
|
||||||
return fmsg.WrapErrorSuffix(err,
|
return fmsg.WrapErrorSuffix(err,
|
||||||
"cannot start process:")
|
"cannot start process:")
|
||||||
|
@ -178,12 +176,12 @@ func (a *app) Wait() (int, error) {
|
||||||
r = a.cmd.ProcessState.ExitCode()
|
r = a.cmd.ProcessState.ExitCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
verbose.Println("process", strconv.Itoa(a.cmd.Process.Pid), "exited with exit code", r)
|
fmsg.VPrintf("process %d exited with exit code %d", a.cmd.Process.Pid, r)
|
||||||
|
|
||||||
// close wayland connection
|
// close wayland connection
|
||||||
if a.seal.wl != nil {
|
if a.seal.wl != nil {
|
||||||
if err := a.seal.wl.Close(); err != nil {
|
if err := a.seal.wl.Close(); err != nil {
|
||||||
fmt.Println("fortify: cannot close wayland connection:", err)
|
fmsg.Println("cannot close wayland connection:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,10 +203,10 @@ func (a *app) Wait() (int, error) {
|
||||||
} else {
|
} else {
|
||||||
if l := len(states); l == 0 {
|
if l := len(states); l == 0 {
|
||||||
// cleanup globals as the final launcher
|
// cleanup globals as the final launcher
|
||||||
verbose.Println("no other launchers active, will clean up globals")
|
fmsg.VPrintln("no other launchers active, will clean up globals")
|
||||||
ec.Set(system.User)
|
ec.Set(system.User)
|
||||||
} else {
|
} else {
|
||||||
verbose.Printf("found %d active launchers, cleaning up without globals\n", l)
|
fmsg.VPrintf("found %d active launchers, cleaning up without globals", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
// accumulate capabilities of other launchers
|
// accumulate capabilities of other launchers
|
||||||
|
@ -222,7 +220,7 @@ func (a *app) Wait() (int, error) {
|
||||||
ec.Set(i)
|
ec.Set(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if verbose.Get() {
|
if fmsg.Verbose() {
|
||||||
labels := make([]string, 0, system.ELen+1)
|
labels := make([]string, 0, system.ELen+1)
|
||||||
for i := system.Enablement(0); i < system.Enablement(system.ELen+2); i++ {
|
for i := system.Enablement(0); i < system.Enablement(system.ELen+2); i++ {
|
||||||
if ec.Has(i) {
|
if ec.Has(i) {
|
||||||
|
@ -230,7 +228,7 @@ func (a *app) Wait() (int, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(labels) > 0 {
|
if len(labels) > 0 {
|
||||||
verbose.Println("reverting operations labelled", strings.Join(labels, ", "))
|
fmsg.VPrintln("reverting operations labelled", strings.Join(labels, ", "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,10 @@ package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -13,7 +14,7 @@ const (
|
||||||
|
|
||||||
var SdBootedV = func() bool {
|
var SdBootedV = func() bool {
|
||||||
if v, err := SdBooted(); err != nil {
|
if v, err := SdBooted(); err != nil {
|
||||||
fmt.Println("warn: read systemd marker:", err)
|
fmsg.Println("cannot read systemd marker:", err)
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
return v
|
return v
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
)
|
)
|
||||||
|
|
||||||
// state that remain constant for the lifetime of the process
|
// state that remain constant for the lifetime of the process
|
||||||
|
@ -37,16 +36,16 @@ func copySC() {
|
||||||
SharePath: path.Join(os.TempDir(), "fortify."+strconv.Itoa(os.Geteuid())),
|
SharePath: path.Join(os.TempDir(), "fortify."+strconv.Itoa(os.Geteuid())),
|
||||||
}
|
}
|
||||||
|
|
||||||
verbose.Println("process share directory at", sc.SharePath)
|
fmsg.VPrintf("process share directory at %q", sc.SharePath)
|
||||||
|
|
||||||
// runtimePath, runDirPath
|
// runtimePath, runDirPath
|
||||||
if r, ok := os.LookupEnv(xdgRuntimeDir); !ok {
|
if r, ok := os.LookupEnv(xdgRuntimeDir); !ok {
|
||||||
fmt.Println("Env variable", xdgRuntimeDir, "unset")
|
fmsg.Println("variable", xdgRuntimeDir, "unset")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
} else {
|
} else {
|
||||||
sc.RuntimePath = r
|
sc.RuntimePath = r
|
||||||
sc.RunDirPath = path.Join(sc.RuntimePath, "fortify")
|
sc.RunDirPath = path.Join(sc.RuntimePath, "fortify")
|
||||||
verbose.Println("XDG runtime directory at", sc.RunDirPath)
|
fmsg.VPrintf("XDG runtime directory at %q", sc.RunDirPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
scVal = sc
|
scVal = sc
|
||||||
|
|
|
@ -1,2 +1,41 @@
|
||||||
// Package fmsg provides various functions for output messages.
|
// Package fmsg provides various functions for output messages.
|
||||||
package fmsg
|
package fmsg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
std = log.New(os.Stdout, "fortify: ", 0)
|
||||||
|
warn = log.New(os.Stderr, "fortify: ", 0)
|
||||||
|
|
||||||
|
verbose = new(atomic.Bool)
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetPrefix(prefix string) {
|
||||||
|
prefix += ": "
|
||||||
|
std.SetPrefix(prefix)
|
||||||
|
warn.SetPrefix(prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Print(v ...any) {
|
||||||
|
warn.Print(v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printf(format string, v ...any) {
|
||||||
|
warn.Printf(format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Println(v ...any) {
|
||||||
|
warn.Println(v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fatal(v ...any) {
|
||||||
|
warn.Fatal(v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Fatalf(format string, v ...any) {
|
||||||
|
warn.Fatalf(format, v...)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package fmsg
|
||||||
|
|
||||||
|
func Verbose() bool {
|
||||||
|
return verbose.Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetVerbose(v bool) {
|
||||||
|
verbose.Store(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func VPrintf(format string, v ...any) {
|
||||||
|
if verbose.Load() {
|
||||||
|
std.Printf(format, v...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func VPrintln(v ...any) {
|
||||||
|
if verbose.Load() {
|
||||||
|
std.Println(v...)
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
@ -13,7 +12,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -25,49 +24,46 @@ const (
|
||||||
// proceed with caution!
|
// proceed with caution!
|
||||||
|
|
||||||
func doInit(fd uintptr) {
|
func doInit(fd uintptr) {
|
||||||
|
fmsg.SetPrefix("init")
|
||||||
|
|
||||||
// re-exec
|
// re-exec
|
||||||
if len(os.Args) > 0 && os.Args[0] != "fortify" && path.IsAbs(os.Args[0]) {
|
if len(os.Args) > 0 && os.Args[0] != "fortify" && path.IsAbs(os.Args[0]) {
|
||||||
if err := syscall.Exec(os.Args[0], []string{"fortify", "init"}, os.Environ()); err != nil {
|
if err := syscall.Exec(os.Args[0], []string{"fortify", "init"}, os.Environ()); err != nil {
|
||||||
fmt.Println("fortify-init: cannot re-exec self:", err)
|
fmsg.Println("cannot re-exec self:", err)
|
||||||
// continue anyway
|
// continue anyway
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
verbose.Prefix = "fortify-init:"
|
|
||||||
|
|
||||||
var payload Payload
|
var payload Payload
|
||||||
p := os.NewFile(fd, "config-stream")
|
p := os.NewFile(fd, "config-stream")
|
||||||
if p == nil {
|
if p == nil {
|
||||||
fmt.Println("fortify-init: invalid config descriptor")
|
fmsg.Fatal("invalid config descriptor")
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
if err := gob.NewDecoder(p).Decode(&payload); err != nil {
|
if err := gob.NewDecoder(p).Decode(&payload); err != nil {
|
||||||
fmt.Println("fortify-init: cannot decode init payload:", err)
|
fmsg.Fatal("cannot decode init payload:", err)
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
} else {
|
||||||
// sharing stdout with parent
|
// sharing stdout with parent
|
||||||
// USE WITH CAUTION
|
// USE WITH CAUTION
|
||||||
verbose.Set(payload.Verbose)
|
fmsg.SetVerbose(payload.Verbose)
|
||||||
|
|
||||||
// child does not need to see this
|
// child does not need to see this
|
||||||
if err = os.Unsetenv(EnvInit); err != nil {
|
if err = os.Unsetenv(EnvInit); err != nil {
|
||||||
fmt.Println("fortify-init: cannot unset", EnvInit+":", err)
|
fmsg.Println("cannot unset", EnvInit+":", err)
|
||||||
// not fatal
|
// not fatal
|
||||||
} else {
|
} else {
|
||||||
verbose.Println("received configuration")
|
fmsg.VPrintln("received configuration")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// close config fd
|
// close config fd
|
||||||
if err := p.Close(); err != nil {
|
if err := p.Close(); err != nil {
|
||||||
fmt.Println("fortify-init: cannot close config fd:", err)
|
fmsg.Println("cannot close config fd:", err)
|
||||||
// not fatal
|
// not fatal
|
||||||
}
|
}
|
||||||
|
|
||||||
// die with parent
|
// die with parent
|
||||||
if _, _, errno := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, uintptr(syscall.SIGKILL), 0); errno != 0 {
|
if _, _, errno := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_PDEATHSIG, uintptr(syscall.SIGKILL), 0); errno != 0 {
|
||||||
fmt.Println("fortify-init: prctl(PR_SET_PDEATHSIG, SIGKILL):", errno.Error())
|
fmsg.Fatal("prctl(PR_SET_PDEATHSIG, SIGKILL):", errno.Error())
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(payload.Argv0)
|
cmd := exec.Command(payload.Argv0)
|
||||||
|
@ -84,8 +80,7 @@ func doInit(fd uintptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
fmt.Printf("fortify-init: cannot start %q: %v", payload.Argv0, err)
|
fmsg.Fatalf("cannot start %q: %v", payload.Argv0, err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sig := make(chan os.Signal, 2)
|
sig := make(chan os.Signal, 2)
|
||||||
|
@ -121,7 +116,7 @@ func doInit(fd uintptr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !errors.Is(err, syscall.ECHILD) {
|
if !errors.Is(err, syscall.ECHILD) {
|
||||||
fmt.Println("fortify-init: unexpected wait4 response:", err)
|
fmsg.Println("unexpected wait4 response:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
close(done)
|
close(done)
|
||||||
|
@ -133,7 +128,7 @@ func doInit(fd uintptr) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case s := <-sig:
|
case s := <-sig:
|
||||||
verbose.Println("received", s.String())
|
fmsg.VPrintln("received", s.String())
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
case w := <-info:
|
case w := <-info:
|
||||||
if w.wpid == cmd.Process.Pid {
|
if w.wpid == cmd.Process.Pid {
|
||||||
|
@ -154,7 +149,7 @@ func doInit(fd uintptr) {
|
||||||
case <-done:
|
case <-done:
|
||||||
os.Exit(r)
|
os.Exit(r)
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
fmt.Println("fortify-init: timeout exceeded waiting for lingering processes")
|
fmsg.Println("timeout exceeded waiting for lingering processes")
|
||||||
os.Exit(r)
|
os.Exit(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,8 +164,7 @@ func Try() {
|
||||||
if args := flag.Args(); len(args) == 1 && args[0] == "init" {
|
if args := flag.Args(); len(args) == 1 && args[0] == "init" {
|
||||||
if s, ok := os.LookupEnv(EnvInit); ok {
|
if s, ok := os.LookupEnv(EnvInit); ok {
|
||||||
if fd, err := strconv.Atoi(s); err != nil {
|
if fd, err := strconv.Atoi(s); err != nil {
|
||||||
fmt.Printf("fortify-init: cannot parse %q: %v", s, err)
|
fmsg.Fatalf("cannot parse %q: %v", s, err)
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
} else {
|
||||||
doInit(uintptr(fd))
|
doInit(uintptr(fd))
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
@ -12,29 +11,29 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/helper"
|
"git.ophivana.moe/security/fortify/helper"
|
||||||
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
init0 "git.ophivana.moe/security/fortify/internal/init"
|
init0 "git.ophivana.moe/security/fortify/internal/init"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// everything beyond this point runs as target user
|
// everything beyond this point runs as target user
|
||||||
// proceed with caution!
|
// proceed with caution!
|
||||||
|
|
||||||
func doShim(socket string) {
|
func doShim(socket string) {
|
||||||
|
fmsg.SetPrefix("shim")
|
||||||
|
|
||||||
// re-exec
|
// re-exec
|
||||||
if len(os.Args) > 0 && os.Args[0] != "fortify" && path.IsAbs(os.Args[0]) {
|
if len(os.Args) > 0 && os.Args[0] != "fortify" && path.IsAbs(os.Args[0]) {
|
||||||
if err := syscall.Exec(os.Args[0], []string{"fortify", "shim"}, os.Environ()); err != nil {
|
if err := syscall.Exec(os.Args[0], []string{"fortify", "shim"}, os.Environ()); err != nil {
|
||||||
fmt.Println("fortify-shim: cannot re-exec self:", err)
|
fmsg.Println("cannot re-exec self:", err)
|
||||||
// continue anyway
|
// continue anyway
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
verbose.Prefix = "fortify-shim:"
|
|
||||||
|
|
||||||
// dial setup socket
|
// dial setup socket
|
||||||
var conn *net.UnixConn
|
var conn *net.UnixConn
|
||||||
if c, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: socket, Net: "unix"}); err != nil {
|
if c, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: socket, Net: "unix"}); err != nil {
|
||||||
fmt.Println("fortify-shim: cannot dial setup socket:", err)
|
fmsg.Fatal("cannot dial setup socket:", err)
|
||||||
os.Exit(1)
|
panic("unreachable")
|
||||||
} else {
|
} else {
|
||||||
conn = c
|
conn = c
|
||||||
}
|
}
|
||||||
|
@ -42,25 +41,22 @@ func doShim(socket string) {
|
||||||
// decode payload gob stream
|
// decode payload gob stream
|
||||||
var payload Payload
|
var payload Payload
|
||||||
if err := gob.NewDecoder(conn).Decode(&payload); err != nil {
|
if err := gob.NewDecoder(conn).Decode(&payload); err != nil {
|
||||||
fmt.Println("fortify-shim: cannot decode shim payload:", err)
|
fmsg.Fatal("cannot decode shim payload:", err)
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
} else {
|
||||||
// sharing stdout with parent
|
// sharing stdout with parent
|
||||||
// USE WITH CAUTION
|
// USE WITH CAUTION
|
||||||
verbose.Set(payload.Verbose)
|
fmsg.SetVerbose(payload.Verbose)
|
||||||
}
|
}
|
||||||
|
|
||||||
if payload.Bwrap == nil {
|
if payload.Bwrap == nil {
|
||||||
fmt.Println("fortify-shim: bwrap config not supplied")
|
fmsg.Fatal("bwrap config not supplied")
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// receive wayland fd over socket
|
// receive wayland fd over socket
|
||||||
wfd := -1
|
wfd := -1
|
||||||
if payload.WL {
|
if payload.WL {
|
||||||
if fd, err := receiveWLfd(conn); err != nil {
|
if fd, err := receiveWLfd(conn); err != nil {
|
||||||
fmt.Println("fortify-shim: cannot receive wayland fd:", err)
|
fmsg.Fatal("cannot receive wayland fd:", err)
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
} else {
|
||||||
wfd = fd
|
wfd = fd
|
||||||
}
|
}
|
||||||
|
@ -68,7 +64,7 @@ func doShim(socket string) {
|
||||||
|
|
||||||
// close setup socket
|
// close setup socket
|
||||||
if err := conn.Close(); err != nil {
|
if err := conn.Close(); err != nil {
|
||||||
fmt.Println("fortify-shim: cannot close setup socket:", err)
|
fmsg.Println("cannot close setup socket:", err)
|
||||||
// not fatal
|
// not fatal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,8 +79,7 @@ func doShim(socket string) {
|
||||||
// no argv, look up shell instead
|
// no argv, look up shell instead
|
||||||
var ok bool
|
var ok bool
|
||||||
if ic.Argv0, ok = os.LookupEnv("SHELL"); !ok {
|
if ic.Argv0, ok = os.LookupEnv("SHELL"); !ok {
|
||||||
fmt.Println("fortify-shim: no command was specified and $SHELL was unset")
|
fmsg.Fatal("no command was specified and $SHELL was unset")
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ic.Argv = []string{ic.Argv0}
|
ic.Argv = []string{ic.Argv0}
|
||||||
|
@ -106,41 +101,37 @@ func doShim(socket string) {
|
||||||
|
|
||||||
// share config pipe
|
// share config pipe
|
||||||
if r, w, err := os.Pipe(); err != nil {
|
if r, w, err := os.Pipe(); err != nil {
|
||||||
fmt.Println("fortify-shim: cannot pipe:", err)
|
fmsg.Fatal("cannot pipe:", err)
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
} else {
|
||||||
conf.SetEnv[init0.EnvInit] = strconv.Itoa(3 + len(extraFiles))
|
conf.SetEnv[init0.EnvInit] = strconv.Itoa(3 + len(extraFiles))
|
||||||
extraFiles = append(extraFiles, r)
|
extraFiles = append(extraFiles, r)
|
||||||
|
|
||||||
verbose.Println("transmitting config to init")
|
fmsg.VPrintln("transmitting config to init")
|
||||||
go func() {
|
go func() {
|
||||||
// stream config to pipe
|
// stream config to pipe
|
||||||
if err = gob.NewEncoder(w).Encode(&ic); err != nil {
|
if err = gob.NewEncoder(w).Encode(&ic); err != nil {
|
||||||
fmt.Println("fortify-shim: cannot transmit init config:", err)
|
fmsg.Fatal("cannot transmit init config:", err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
helper.BubblewrapName = payload.Exec[1] // resolved bwrap path by parent
|
helper.BubblewrapName = payload.Exec[1] // resolved bwrap path by parent
|
||||||
if b, err := helper.NewBwrap(conf, nil, payload.Exec[0], func(int, int) []string { return []string{"init"} }); err != nil {
|
if b, err := helper.NewBwrap(conf, nil, payload.Exec[0], func(int, int) []string { return []string{"init"} }); err != nil {
|
||||||
fmt.Println("fortify-shim: malformed sandbox config:", err)
|
fmsg.Fatal("malformed sandbox config:", err)
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
} else {
|
||||||
cmd := b.Unwrap()
|
cmd := b.Unwrap()
|
||||||
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
|
||||||
cmd.ExtraFiles = extraFiles
|
cmd.ExtraFiles = extraFiles
|
||||||
|
|
||||||
if verbose.Get() {
|
if fmsg.Verbose() {
|
||||||
verbose.Println("bwrap args:", conf.Args())
|
fmsg.VPrintln("bwrap args:", conf.Args())
|
||||||
}
|
}
|
||||||
|
|
||||||
// run and pass through exit code
|
// run and pass through exit code
|
||||||
if err = b.Start(); err != nil {
|
if err = b.Start(); err != nil {
|
||||||
fmt.Println("fortify-shim: cannot start target process:", err)
|
fmsg.Fatal("cannot start target process:", err)
|
||||||
os.Exit(1)
|
|
||||||
} else if err = b.Wait(); err != nil {
|
} else if err = b.Wait(); err != nil {
|
||||||
verbose.Println("wait:", err)
|
fmsg.VPrintln("wait:", err)
|
||||||
}
|
}
|
||||||
if b.Unwrap().ProcessState != nil {
|
if b.Unwrap().ProcessState != nil {
|
||||||
os.Exit(b.Unwrap().ProcessState.ExitCode())
|
os.Exit(b.Unwrap().ProcessState.ExitCode())
|
||||||
|
|
|
@ -3,13 +3,12 @@ package shim
|
||||||
import (
|
import (
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/acl"
|
"git.ophivana.moe/security/fortify/acl"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
)
|
)
|
||||||
|
|
||||||
// called in the parent process
|
// called in the parent process
|
||||||
|
@ -19,7 +18,7 @@ func ServeConfig(socket string, uid int, payload *Payload, wl *Wayland) error {
|
||||||
if f, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: wl.Path, Net: "unix"}); err != nil {
|
if f, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: wl.Path, Net: "unix"}); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
verbose.Println("connected to wayland at", wl)
|
fmsg.VPrintf("connected to wayland at %q", wl.Path)
|
||||||
wl.UnixConn = f
|
wl.UnixConn = f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,18 +26,18 @@ func ServeConfig(socket string, uid int, payload *Payload, wl *Wayland) error {
|
||||||
if c, err := net.ListenUnix("unix", &net.UnixAddr{Name: socket, Net: "unix"}); err != nil {
|
if c, err := net.ListenUnix("unix", &net.UnixAddr{Name: socket, Net: "unix"}); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
verbose.Println("configuring shim on socket", socket)
|
fmsg.VPrintf("configuring shim on socket %q", socket)
|
||||||
if err = acl.UpdatePerm(socket, uid, acl.Read, acl.Write, acl.Execute); err != nil {
|
if err = acl.UpdatePerm(socket, uid, acl.Read, acl.Write, acl.Execute); err != nil {
|
||||||
fmt.Println("fortify: cannot change permissions of shim setup socket:", err)
|
fmsg.Println("cannot change permissions of shim setup socket:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
var conn *net.UnixConn
|
var conn *net.UnixConn
|
||||||
if conn, err = c.AcceptUnix(); err != nil {
|
if conn, err = c.AcceptUnix(); err != nil {
|
||||||
fmt.Println("fortify: cannot accept connection from shim:", err)
|
fmsg.Println("cannot accept connection from shim:", err)
|
||||||
} else {
|
} else {
|
||||||
if err = gob.NewEncoder(conn).Encode(*payload); err != nil {
|
if err = gob.NewEncoder(conn).Encode(*payload); err != nil {
|
||||||
fmt.Println("fortify: cannot stream shim payload:", err)
|
fmsg.Println("cannot stream shim payload:", err)
|
||||||
_ = os.Remove(socket)
|
_ = os.Remove(socket)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -47,23 +46,23 @@ func ServeConfig(socket string, uid int, payload *Payload, wl *Wayland) error {
|
||||||
// get raw connection
|
// get raw connection
|
||||||
var rc syscall.RawConn
|
var rc syscall.RawConn
|
||||||
if rc, err = wl.SyscallConn(); err != nil {
|
if rc, err = wl.SyscallConn(); err != nil {
|
||||||
fmt.Println("fortify: cannot obtain raw wayland connection:", err)
|
fmsg.Println("cannot obtain raw wayland connection:", err)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
go func() {
|
go func() {
|
||||||
// pass wayland socket fd
|
// pass wayland socket fd
|
||||||
if err = rc.Control(func(fd uintptr) {
|
if err = rc.Control(func(fd uintptr) {
|
||||||
if _, _, err = conn.WriteMsgUnix(nil, syscall.UnixRights(int(fd)), nil); err != nil {
|
if _, _, err = conn.WriteMsgUnix(nil, syscall.UnixRights(int(fd)), nil); err != nil {
|
||||||
fmt.Println("fortify: cannot pass wayland connection to shim:", err)
|
fmsg.Println("cannot pass wayland connection to shim:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = conn.Close()
|
_ = conn.Close()
|
||||||
|
|
||||||
// block until shim exits
|
// block until shim exits
|
||||||
<-wl.done
|
<-wl.done
|
||||||
verbose.Println("releasing wayland connection")
|
fmsg.VPrintln("releasing wayland connection")
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
fmt.Println("fortify: cannot obtain wayland connection fd:", err)
|
fmsg.Println("cannot obtain wayland connection fd:", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -72,10 +71,10 @@ func ServeConfig(socket string, uid int, payload *Payload, wl *Wayland) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err = c.Close(); err != nil {
|
if err = c.Close(); err != nil {
|
||||||
fmt.Println("fortify: cannot close shim socket:", err)
|
fmsg.Println("cannot close shim socket:", err)
|
||||||
}
|
}
|
||||||
if err = os.Remove(socket); err != nil && !errors.Is(err, os.ErrNotExist) {
|
if err = os.Remove(socket); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
fmt.Println("fortify: cannot remove dangling shim socket:", err)
|
fmsg.Println("cannot remove dangling shim socket:", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -10,8 +10,8 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
"git.ophivana.moe/security/fortify/internal/system"
|
"git.ophivana.moe/security/fortify/internal/system"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MustPrintLauncherStateSimpleGlobal prints active launcher states of all simple stores
|
// MustPrintLauncherStateSimpleGlobal prints active launcher states of all simple stores
|
||||||
|
@ -21,19 +21,19 @@ func MustPrintLauncherStateSimpleGlobal(w **tabwriter.Writer, runDir string) {
|
||||||
|
|
||||||
// read runtime directory to get all UIDs
|
// read runtime directory to get all UIDs
|
||||||
if dirs, err := os.ReadDir(path.Join(runDir, "state")); err != nil && !errors.Is(err, os.ErrNotExist) {
|
if dirs, err := os.ReadDir(path.Join(runDir, "state")); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
fmt.Println("cannot read runtime directory:", err)
|
fmsg.Println("cannot read runtime directory:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
} else {
|
} else {
|
||||||
for _, e := range dirs {
|
for _, e := range dirs {
|
||||||
// skip non-directories
|
// skip non-directories
|
||||||
if !e.IsDir() {
|
if !e.IsDir() {
|
||||||
verbose.Println("skipped non-directory entry", e.Name())
|
fmsg.VPrintf("skipped non-directory entry %q", e.Name())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip non-numerical names
|
// skip non-numerical names
|
||||||
if _, err = strconv.Atoi(e.Name()); err != nil {
|
if _, err = strconv.Atoi(e.Name()); err != nil {
|
||||||
verbose.Println("skipped non-uid entry", e.Name())
|
fmsg.VPrintf("skipped non-uid entry %q", e.Name())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ func MustPrintLauncherStateSimpleGlobal(w **tabwriter.Writer, runDir string) {
|
||||||
|
|
||||||
// mustPrintLauncherState causes store activity so store needs to be closed
|
// mustPrintLauncherState causes store activity so store needs to be closed
|
||||||
if err = s.Close(); err != nil {
|
if err = s.Close(); err != nil {
|
||||||
fmt.Printf("warn: error closing store for user %s: %s\n", e.Name(), err)
|
fmsg.Printf("cannot close store for user %q: %s", e.Name(), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ func (s *simpleStore) mustPrintLauncherState(w **tabwriter.Writer, now time.Time
|
||||||
*w = tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', 0)
|
*w = tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', 0)
|
||||||
|
|
||||||
// write header when initialising
|
// write header when initialising
|
||||||
if !verbose.Get() {
|
if !fmsg.Verbose() {
|
||||||
_, _ = fmt.Fprintln(*w, "\tUID\tPID\tUptime\tEnablements\tMethod\tCommand")
|
_, _ = fmt.Fprintln(*w, "\tUID\tPID\tUptime\tEnablements\tMethod\tCommand")
|
||||||
} else {
|
} else {
|
||||||
// argv is emitted in body when verbose
|
// argv is emitted in body when verbose
|
||||||
|
@ -96,7 +96,7 @@ func (s *simpleStore) mustPrintLauncherState(w **tabwriter.Writer, now time.Time
|
||||||
ets.WriteString("(No enablements)")
|
ets.WriteString("(No enablements)")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !verbose.Get() {
|
if !fmsg.Verbose() {
|
||||||
_, _ = fmt.Fprintf(*w, "\t%s\t%d\t%s\t%s\t%s\t%s\n",
|
_, _ = fmt.Fprintf(*w, "\t%s\t%d\t%s\t%s\t%s\t%s\n",
|
||||||
s.path[len(s.path)-1], state.PID, now.Sub(state.Time).Round(time.Second).String(), strings.TrimPrefix(ets.String(), ", "), state.Method,
|
s.path[len(s.path)-1], state.PID, now.Sub(state.Time).Round(time.Second).String(), strings.TrimPrefix(ets.String(), ", "), state.Method,
|
||||||
state.Command)
|
state.Command)
|
||||||
|
@ -110,15 +110,15 @@ func (s *simpleStore) mustPrintLauncherState(w **tabwriter.Writer, now time.Time
|
||||||
return nil
|
return nil
|
||||||
}()
|
}()
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
fmt.Printf("cannot perform action on store '%s': %s\n", path.Join(s.path...), err)
|
fmsg.Printf("cannot perform action on store %q: %s", path.Join(s.path...), err)
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Println("warn: store faulted before printing")
|
fmsg.Println("store faulted before printing")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if innerErr != nil {
|
if innerErr != nil {
|
||||||
fmt.Printf("cannot print launcher state for store '%s': %s\n", path.Join(s.path...), innerErr)
|
fmsg.Printf("cannot print launcher state for store %q: %s", path.Join(s.path...), innerErr)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/acl"
|
"git.ophivana.moe/security/fortify/acl"
|
||||||
"git.ophivana.moe/security/fortify/internal/fmsg"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UpdatePerm appends an ephemeral acl update Op.
|
// UpdatePerm appends an ephemeral acl update Op.
|
||||||
|
@ -33,18 +32,20 @@ func (a *ACL) Type() Enablement {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ACL) apply(sys *I) error {
|
func (a *ACL) apply(sys *I) error {
|
||||||
verbose.Println("applying ACL", a, "uid:", sys.uid, "type:", TypeString(a.et), "path:", a.path)
|
fmsg.VPrintf("applying ACL %s uid: %d type: %s path: %q",
|
||||||
|
a, sys.uid, TypeString(a.et), a.path)
|
||||||
return fmsg.WrapErrorSuffix(acl.UpdatePerm(a.path, sys.uid, a.perms...),
|
return fmsg.WrapErrorSuffix(acl.UpdatePerm(a.path, sys.uid, a.perms...),
|
||||||
fmt.Sprintf("cannot apply ACL entry to %q:", a.path))
|
fmt.Sprintf("cannot apply ACL entry to %q:", a.path))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ACL) revert(sys *I, ec *Criteria) error {
|
func (a *ACL) revert(sys *I, ec *Criteria) error {
|
||||||
if ec.hasType(a) {
|
if ec.hasType(a) {
|
||||||
verbose.Println("stripping ACL", a, "uid:", sys.uid, "type:", TypeString(a.et), "path:", a.path)
|
fmsg.VPrintf("stripping ACL %s uid: %d type: %s path: %q",
|
||||||
|
a, sys.uid, TypeString(a.et), a.path)
|
||||||
return fmsg.WrapErrorSuffix(acl.UpdatePerm(a.path, sys.uid),
|
return fmsg.WrapErrorSuffix(acl.UpdatePerm(a.path, sys.uid),
|
||||||
fmt.Sprintf("cannot strip ACL entry from %q:", a.path))
|
fmt.Sprintf("cannot strip ACL entry from %q:", a.path))
|
||||||
} else {
|
} else {
|
||||||
verbose.Println("skipping ACL", a, "uid:", sys.uid, "tag:", TypeString(a.et), "path:", a.path)
|
fmsg.VPrintln("skipping ACL", a, "uid:", sys.uid, "tag:", TypeString(a.et), "path:", a.path)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,10 @@ package system
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/dbus"
|
"git.ophivana.moe/security/fortify/dbus"
|
||||||
"git.ophivana.moe/security/fortify/internal/fmsg"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -42,12 +40,12 @@ func (sys *I) ProxyDBus(session, system *dbus.Config, sessionPath, systemPath st
|
||||||
d.proxy = dbus.New(sessionBus, systemBus)
|
d.proxy = dbus.New(sessionBus, systemBus)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if verbose.Get() && d.proxy.Sealed() {
|
if fmsg.Verbose() && d.proxy.Sealed() {
|
||||||
verbose.Println("sealed session proxy", session.Args(sessionBus))
|
fmsg.VPrintln("sealed session proxy", session.Args(sessionBus))
|
||||||
if system != nil {
|
if system != nil {
|
||||||
verbose.Println("sealed system proxy", system.Args(systemBus))
|
fmsg.VPrintln("sealed system proxy", system.Args(systemBus))
|
||||||
}
|
}
|
||||||
verbose.Println("message bus proxy final args:", d.proxy)
|
fmsg.VPrintln("message bus proxy final args:", d.proxy)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -73,9 +71,9 @@ func (d *DBus) Type() Enablement {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DBus) apply(_ *I) error {
|
func (d *DBus) apply(_ *I) error {
|
||||||
verbose.Printf("session bus proxy on %q for upstream %q\n", d.proxy.Session()[1], d.proxy.Session()[0])
|
fmsg.VPrintf("session bus proxy on %q for upstream %q", d.proxy.Session()[1], d.proxy.Session()[0])
|
||||||
if d.system {
|
if d.system {
|
||||||
verbose.Printf("system bus proxy on %q for upstream %q\n", d.proxy.System()[1], d.proxy.System()[0])
|
fmsg.VPrintf("system bus proxy on %q for upstream %q", d.proxy.System()[1], d.proxy.System()[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// ready channel passed to dbus package
|
// ready channel passed to dbus package
|
||||||
|
@ -86,27 +84,27 @@ func (d *DBus) apply(_ *I) error {
|
||||||
return fmsg.WrapErrorSuffix(err,
|
return fmsg.WrapErrorSuffix(err,
|
||||||
"cannot start message bus proxy:")
|
"cannot start message bus proxy:")
|
||||||
}
|
}
|
||||||
verbose.Println("starting message bus proxy:", d.proxy)
|
fmsg.VPrintln("starting message bus proxy:", d.proxy)
|
||||||
if verbose.Get() { // save the extra bwrap arg build when verbose logging is off
|
if fmsg.Verbose() { // save the extra bwrap arg build when verbose logging is off
|
||||||
verbose.Println("message bus proxy bwrap args:", d.proxy.Bwrap())
|
fmsg.VPrintln("message bus proxy bwrap args:", d.proxy.Bwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
// background wait for proxy instance and notify completion
|
// background wait for proxy instance and notify completion
|
||||||
go func() {
|
go func() {
|
||||||
if err := d.proxy.Wait(); err != nil {
|
if err := d.proxy.Wait(); err != nil {
|
||||||
fmt.Println("fortify: message bus proxy exited with error:", err)
|
fmsg.Println("message bus proxy exited with error:", err)
|
||||||
go func() { ready <- err }()
|
go func() { ready <- err }()
|
||||||
} else {
|
} else {
|
||||||
verbose.Println("message bus proxy exit")
|
fmsg.VPrintln("message bus proxy exit")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure socket removal so ephemeral directory is empty at revert
|
// ensure socket removal so ephemeral directory is empty at revert
|
||||||
if err := os.Remove(d.proxy.Session()[1]); err != nil && !errors.Is(err, os.ErrNotExist) {
|
if err := os.Remove(d.proxy.Session()[1]); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
fmt.Println("fortify: cannot remove dangling session bus socket:", err)
|
fmsg.Println("cannot remove dangling session bus socket:", err)
|
||||||
}
|
}
|
||||||
if d.system {
|
if d.system {
|
||||||
if err := os.Remove(d.proxy.System()[1]); err != nil && !errors.Is(err, os.ErrNotExist) {
|
if err := os.Remove(d.proxy.System()[1]); err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
fmt.Println("fortify: cannot remove dangling system bus socket:", err)
|
fmsg.Println("cannot remove dangling system bus socket:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,14 +118,14 @@ func (d *DBus) apply(_ *I) error {
|
||||||
return fmsg.WrapErrorSuffix(err,
|
return fmsg.WrapErrorSuffix(err,
|
||||||
"message bus proxy fault after start:")
|
"message bus proxy fault after start:")
|
||||||
}
|
}
|
||||||
verbose.Println("message bus proxy ready")
|
fmsg.VPrintln("message bus proxy ready")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DBus) revert(_ *I, _ *Criteria) error {
|
func (d *DBus) revert(_ *I, _ *Criteria) error {
|
||||||
// criteria ignored here since dbus is always process-scoped
|
// criteria ignored here since dbus is always process-scoped
|
||||||
verbose.Println("terminating message bus proxy")
|
fmsg.VPrintln("terminating message bus proxy")
|
||||||
|
|
||||||
if err := d.proxy.Close(); err != nil {
|
if err := d.proxy.Close(); err != nil {
|
||||||
if errors.Is(err, os.ErrClosed) {
|
if errors.Is(err, os.ErrClosed) {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal/fmsg"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ensure the existence and mode of a directory.
|
// Ensure the existence and mode of a directory.
|
||||||
|
@ -37,7 +36,7 @@ func (m *Mkdir) Type() Enablement {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mkdir) apply(_ *I) error {
|
func (m *Mkdir) apply(_ *I) error {
|
||||||
verbose.Println("ensuring directory", m)
|
fmsg.VPrintln("ensuring directory", m)
|
||||||
|
|
||||||
// create directory
|
// create directory
|
||||||
err := os.Mkdir(m.path, m.perm)
|
err := os.Mkdir(m.path, m.perm)
|
||||||
|
@ -58,11 +57,11 @@ func (m *Mkdir) revert(_ *I, ec *Criteria) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ec.hasType(m) {
|
if ec.hasType(m) {
|
||||||
verbose.Println("destroying ephemeral directory", m)
|
fmsg.VPrintln("destroying ephemeral directory", m)
|
||||||
return fmsg.WrapErrorSuffix(os.Remove(m.path),
|
return fmsg.WrapErrorSuffix(os.Remove(m.path),
|
||||||
fmt.Sprintf("cannot remove ephemeral directory %q:", m.path))
|
fmt.Sprintf("cannot remove ephemeral directory %q:", m.path))
|
||||||
} else {
|
} else {
|
||||||
verbose.Println("skipping ephemeral directory", m)
|
fmsg.VPrintln("skipping ephemeral directory", m)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,9 @@ package system
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -80,7 +81,7 @@ func (sys *I) Commit() error {
|
||||||
if sp != nil {
|
if sp != nil {
|
||||||
// rollback partial commit
|
// rollback partial commit
|
||||||
if err := sp.Revert(&Criteria{nil}); err != nil {
|
if err := sp.Revert(&Criteria{nil}); err != nil {
|
||||||
fmt.Println("fortify: errors returned reverting partial commit:", err)
|
fmsg.Println("errors returned reverting partial commit:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/acl"
|
"git.ophivana.moe/security/fortify/acl"
|
||||||
"git.ophivana.moe/security/fortify/internal/fmsg"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CopyFile registers an Op that copies path dst from src.
|
// CopyFile registers an Op that copies path dst from src.
|
||||||
|
@ -72,15 +71,15 @@ func (t *Tmpfile) Type() Enablement {
|
||||||
func (t *Tmpfile) apply(_ *I) error {
|
func (t *Tmpfile) apply(_ *I) error {
|
||||||
switch t.method {
|
switch t.method {
|
||||||
case tmpfileCopy:
|
case tmpfileCopy:
|
||||||
verbose.Printf("publishing tmpfile %s\n", t)
|
fmsg.VPrintln("publishing tmpfile", t)
|
||||||
return fmsg.WrapErrorSuffix(copyFile(t.dst, t.src),
|
return fmsg.WrapErrorSuffix(copyFile(t.dst, t.src),
|
||||||
fmt.Sprintf("cannot copy tmpfile %q:", t.dst))
|
fmt.Sprintf("cannot copy tmpfile %q:", t.dst))
|
||||||
case tmpfileLink:
|
case tmpfileLink:
|
||||||
verbose.Printf("linking tmpfile %s\n", t)
|
fmsg.VPrintln("linking tmpfile", t)
|
||||||
return fmsg.WrapErrorSuffix(os.Link(t.src, t.dst),
|
return fmsg.WrapErrorSuffix(os.Link(t.src, t.dst),
|
||||||
fmt.Sprintf("cannot link tmpfile %q:", t.dst))
|
fmt.Sprintf("cannot link tmpfile %q:", t.dst))
|
||||||
case tmpfileWrite:
|
case tmpfileWrite:
|
||||||
verbose.Printf("writing %s\n", t)
|
fmsg.VPrintln("writing", t)
|
||||||
return fmsg.WrapErrorSuffix(os.WriteFile(t.dst, []byte(t.src), 0600),
|
return fmsg.WrapErrorSuffix(os.WriteFile(t.dst, []byte(t.src), 0600),
|
||||||
fmt.Sprintf("cannot write tmpfile %q:", t.dst))
|
fmt.Sprintf("cannot write tmpfile %q:", t.dst))
|
||||||
default:
|
default:
|
||||||
|
@ -90,11 +89,11 @@ func (t *Tmpfile) apply(_ *I) error {
|
||||||
|
|
||||||
func (t *Tmpfile) revert(_ *I, ec *Criteria) error {
|
func (t *Tmpfile) revert(_ *I, ec *Criteria) error {
|
||||||
if ec.hasType(t) {
|
if ec.hasType(t) {
|
||||||
verbose.Printf("removing tmpfile %q\n", t.dst)
|
fmsg.VPrintf("removing tmpfile %q", t.dst)
|
||||||
return fmsg.WrapErrorSuffix(os.Remove(t.dst),
|
return fmsg.WrapErrorSuffix(os.Remove(t.dst),
|
||||||
fmt.Sprintf("cannot remove tmpfile %q:", t.dst))
|
fmt.Sprintf("cannot remove tmpfile %q:", t.dst))
|
||||||
} else {
|
} else {
|
||||||
verbose.Printf("skipping tmpfile %q\n", t.dst)
|
fmsg.VPrintf("skipping tmpfile %q", t.dst)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal/fmsg"
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
"git.ophivana.moe/security/fortify/xcb"
|
"git.ophivana.moe/security/fortify/xcb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,18 +22,18 @@ func (x XHost) Type() Enablement {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x XHost) apply(_ *I) error {
|
func (x XHost) apply(_ *I) error {
|
||||||
verbose.Printf("inserting entry %s to X11\n", x)
|
fmsg.VPrintf("inserting entry %s to X11", x)
|
||||||
return fmsg.WrapErrorSuffix(xcb.ChangeHosts(xcb.HostModeInsert, xcb.FamilyServerInterpreted, "localuser\x00"+string(x)),
|
return fmsg.WrapErrorSuffix(xcb.ChangeHosts(xcb.HostModeInsert, xcb.FamilyServerInterpreted, "localuser\x00"+string(x)),
|
||||||
fmt.Sprintf("cannot insert entry %s to X11:", x))
|
fmt.Sprintf("cannot insert entry %s to X11:", x))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x XHost) revert(_ *I, ec *Criteria) error {
|
func (x XHost) revert(_ *I, ec *Criteria) error {
|
||||||
if ec.hasType(x) {
|
if ec.hasType(x) {
|
||||||
verbose.Printf("deleting entry %s from X11\n", x)
|
fmsg.VPrintf("deleting entry %s from X11", x)
|
||||||
return fmsg.WrapErrorSuffix(xcb.ChangeHosts(xcb.HostModeDelete, xcb.FamilyServerInterpreted, "localuser\x00"+string(x)),
|
return fmsg.WrapErrorSuffix(xcb.ChangeHosts(xcb.HostModeDelete, xcb.FamilyServerInterpreted, "localuser\x00"+string(x)),
|
||||||
fmt.Sprintf("cannot delete entry %s from X11:", x))
|
fmt.Sprintf("cannot delete entry %s from X11:", x))
|
||||||
} else {
|
} else {
|
||||||
verbose.Printf("skipping entry %s in X11\n", x)
|
fmsg.VPrintf("skipping entry %s in X11", x)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package verbose
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Prefix = "fortify:"
|
|
||||||
|
|
||||||
func Println(a ...any) {
|
|
||||||
if verbose.Load() {
|
|
||||||
fmt.Println(append([]any{Prefix}, a...)...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Printf(format string, a ...any) {
|
|
||||||
if verbose.Load() {
|
|
||||||
fmt.Printf(Prefix+" "+format, a...)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
package verbose_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
testVerbose = "GO_TEST_VERBOSE"
|
|
||||||
wantStdout = "fortify: println\nfortify: printf"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPrinter(t *testing.T) {
|
|
||||||
switch os.Getenv(testVerbose) {
|
|
||||||
case "0":
|
|
||||||
verbose.Set(false)
|
|
||||||
case "1":
|
|
||||||
verbose.Set(true)
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
verbose.Println("println")
|
|
||||||
verbose.Printf("%s", "printf")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrintf_Println(t *testing.T) {
|
|
||||||
testPrintfPrintln(t, false)
|
|
||||||
testPrintfPrintln(t, true)
|
|
||||||
|
|
||||||
// make -cover happy
|
|
||||||
stdout := os.Stdout
|
|
||||||
t.Cleanup(func() {
|
|
||||||
os.Stdout = stdout
|
|
||||||
})
|
|
||||||
os.Stdout = nil
|
|
||||||
verbose.Set(true)
|
|
||||||
verbose.Printf("")
|
|
||||||
verbose.Println()
|
|
||||||
}
|
|
||||||
|
|
||||||
func testPrintfPrintln(t *testing.T, v bool) {
|
|
||||||
t.Run("start verbose printer with verbose "+strconv.FormatBool(v), func(t *testing.T) {
|
|
||||||
stdout, stderr := new(strings.Builder), new(strings.Builder)
|
|
||||||
stdout.Grow(len(wantStdout))
|
|
||||||
cmd := exec.Command(os.Args[0], "-test.run=TestPrinter")
|
|
||||||
cmd.Stdout, cmd.Stderr = stdout, stderr
|
|
||||||
if v {
|
|
||||||
cmd.Env = append(cmd.Env, testVerbose+"=1")
|
|
||||||
} else {
|
|
||||||
cmd.Env = append(cmd.Env, testVerbose+"=0")
|
|
||||||
}
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
panic("cannot run printer process: " + err.Error() + " stderr: " + stderr.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if got := stdout.String(); strings.Contains(got, wantStdout) != v {
|
|
||||||
t.Errorf("Print: got %v; want %t",
|
|
||||||
got, v)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
package verbose
|
|
||||||
|
|
||||||
import "sync/atomic"
|
|
||||||
|
|
||||||
var verbose = new(atomic.Bool)
|
|
||||||
|
|
||||||
func Get() bool {
|
|
||||||
return verbose.Load()
|
|
||||||
}
|
|
||||||
|
|
||||||
func Set(v bool) {
|
|
||||||
verbose.Store(v)
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
package verbose_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetSet(t *testing.T) {
|
|
||||||
verbose.Set(false)
|
|
||||||
if verbose.Get() {
|
|
||||||
t.Errorf("Get() = true, want false")
|
|
||||||
}
|
|
||||||
|
|
||||||
verbose.Set(true)
|
|
||||||
if !verbose.Get() {
|
|
||||||
t.Errorf("Get() = false, want true")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
15
main.go
15
main.go
|
@ -2,15 +2,14 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal"
|
"git.ophivana.moe/security/fortify/internal"
|
||||||
"git.ophivana.moe/security/fortify/internal/app"
|
"git.ophivana.moe/security/fortify/internal/app"
|
||||||
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
init0 "git.ophivana.moe/security/fortify/internal/init"
|
init0 "git.ophivana.moe/security/fortify/internal/init"
|
||||||
"git.ophivana.moe/security/fortify/internal/shim"
|
"git.ophivana.moe/security/fortify/internal/shim"
|
||||||
"git.ophivana.moe/security/fortify/internal/verbose"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -24,14 +23,14 @@ func init() {
|
||||||
func main() {
|
func main() {
|
||||||
// linux/sched/coredump.h
|
// linux/sched/coredump.h
|
||||||
if _, _, errno := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_DUMPABLE, 0, 0); errno != 0 {
|
if _, _, errno := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_SET_DUMPABLE, 0, 0); errno != 0 {
|
||||||
fmt.Printf("fortify: cannot set SUID_DUMP_DISABLE: %s", errno.Error())
|
fmsg.Printf("fortify: cannot set SUID_DUMP_DISABLE: %s", errno.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
verbose.Set(flagVerbose)
|
fmsg.SetVerbose(flagVerbose)
|
||||||
|
|
||||||
if internal.SdBootedV {
|
if internal.SdBootedV {
|
||||||
verbose.Println("system booted with systemd as init system")
|
fmsg.VPrintln("system booted with systemd as init system")
|
||||||
}
|
}
|
||||||
|
|
||||||
// shim/init early exit
|
// shim/init early exit
|
||||||
|
@ -40,7 +39,7 @@ func main() {
|
||||||
|
|
||||||
// root check
|
// root check
|
||||||
if os.Getuid() == 0 {
|
if os.Getuid() == 0 {
|
||||||
fmt.Println("fortify: this program must not run as root")
|
fmsg.Println("this program must not run as root")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +55,7 @@ func main() {
|
||||||
r := 1
|
r := 1
|
||||||
a, err := app.New()
|
a, err := app.New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("cannot create app: %s\n", err)
|
fmsg.Fatalf("cannot create app: %s\n", err)
|
||||||
} else if err = a.Seal(loadConfig()); err != nil {
|
} else if err = a.Seal(loadConfig()); err != nil {
|
||||||
logBaseError(err, "fortify: cannot seal app:")
|
logBaseError(err, "fortify: cannot seal app:")
|
||||||
} else if err = a.Start(); err != nil {
|
} else if err = a.Start(); err != nil {
|
||||||
|
@ -68,7 +67,7 @@ func main() {
|
||||||
logWaitError(err)
|
logWaitError(err)
|
||||||
}
|
}
|
||||||
if err = a.WaitErr(); err != nil {
|
if err = a.WaitErr(); err != nil {
|
||||||
fmt.Println("fortify: inner wait failed:", err)
|
fmsg.Println("inner wait failed:", err)
|
||||||
}
|
}
|
||||||
os.Exit(r)
|
os.Exit(r)
|
||||||
}
|
}
|
||||||
|
|
3
state.go
3
state.go
|
@ -7,6 +7,7 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"git.ophivana.moe/security/fortify/internal"
|
"git.ophivana.moe/security/fortify/internal"
|
||||||
|
"git.ophivana.moe/security/fortify/internal/fmsg"
|
||||||
"git.ophivana.moe/security/fortify/internal/state"
|
"git.ophivana.moe/security/fortify/internal/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ func tryState() {
|
||||||
state.MustPrintLauncherStateSimpleGlobal(&w, internal.GetSC().RunDirPath)
|
state.MustPrintLauncherStateSimpleGlobal(&w, internal.GetSC().RunDirPath)
|
||||||
if w != nil {
|
if w != nil {
|
||||||
if err := w.Flush(); err != nil {
|
if err := w.Flush(); err != nil {
|
||||||
fmt.Println("warn: error formatting output:", err)
|
fmsg.Println("cannot format output:", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("No information available")
|
fmt.Println("No information available")
|
||||||
|
|
Loading…
Reference in New Issue