fmsg: produce all output through fmsg
All checks were successful
test / test (push) Successful in 17s

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:
2024-10-21 20:47:02 +09:00
parent 380d1f4585
commit 42e0b168e3
26 changed files with 194 additions and 280 deletions

View File

@@ -4,7 +4,6 @@ import (
"encoding/gob"
"errors"
"flag"
"fmt"
"net"
"os"
"path"
@@ -12,29 +11,29 @@ import (
"syscall"
"git.ophivana.moe/security/fortify/helper"
"git.ophivana.moe/security/fortify/internal/fmsg"
init0 "git.ophivana.moe/security/fortify/internal/init"
"git.ophivana.moe/security/fortify/internal/verbose"
)
// everything beyond this point runs as target user
// proceed with caution!
func doShim(socket string) {
fmsg.SetPrefix("shim")
// re-exec
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 {
fmt.Println("fortify-shim: cannot re-exec self:", err)
fmsg.Println("cannot re-exec self:", err)
// continue anyway
}
}
verbose.Prefix = "fortify-shim:"
// dial setup socket
var conn *net.UnixConn
if c, err := net.DialUnix("unix", nil, &net.UnixAddr{Name: socket, Net: "unix"}); err != nil {
fmt.Println("fortify-shim: cannot dial setup socket:", err)
os.Exit(1)
fmsg.Fatal("cannot dial setup socket:", err)
panic("unreachable")
} else {
conn = c
}
@@ -42,25 +41,22 @@ func doShim(socket string) {
// decode payload gob stream
var payload Payload
if err := gob.NewDecoder(conn).Decode(&payload); err != nil {
fmt.Println("fortify-shim: cannot decode shim payload:", err)
os.Exit(1)
fmsg.Fatal("cannot decode shim payload:", err)
} else {
// sharing stdout with parent
// USE WITH CAUTION
verbose.Set(payload.Verbose)
fmsg.SetVerbose(payload.Verbose)
}
if payload.Bwrap == nil {
fmt.Println("fortify-shim: bwrap config not supplied")
os.Exit(1)
fmsg.Fatal("bwrap config not supplied")
}
// receive wayland fd over socket
wfd := -1
if payload.WL {
if fd, err := receiveWLfd(conn); err != nil {
fmt.Println("fortify-shim: cannot receive wayland fd:", err)
os.Exit(1)
fmsg.Fatal("cannot receive wayland fd:", err)
} else {
wfd = fd
}
@@ -68,7 +64,7 @@ func doShim(socket string) {
// close setup socket
if err := conn.Close(); err != nil {
fmt.Println("fortify-shim: cannot close setup socket:", err)
fmsg.Println("cannot close setup socket:", err)
// not fatal
}
@@ -83,8 +79,7 @@ func doShim(socket string) {
// no argv, look up shell instead
var ok bool
if ic.Argv0, ok = os.LookupEnv("SHELL"); !ok {
fmt.Println("fortify-shim: no command was specified and $SHELL was unset")
os.Exit(1)
fmsg.Fatal("no command was specified and $SHELL was unset")
}
ic.Argv = []string{ic.Argv0}
@@ -106,41 +101,37 @@ func doShim(socket string) {
// share config pipe
if r, w, err := os.Pipe(); err != nil {
fmt.Println("fortify-shim: cannot pipe:", err)
os.Exit(1)
fmsg.Fatal("cannot pipe:", err)
} else {
conf.SetEnv[init0.EnvInit] = strconv.Itoa(3 + len(extraFiles))
extraFiles = append(extraFiles, r)
verbose.Println("transmitting config to init")
fmsg.VPrintln("transmitting config to init")
go func() {
// stream config to pipe
if err = gob.NewEncoder(w).Encode(&ic); err != nil {
fmt.Println("fortify-shim: cannot transmit init config:", err)
os.Exit(1)
fmsg.Fatal("cannot transmit init config:", err)
}
}()
}
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 {
fmt.Println("fortify-shim: malformed sandbox config:", err)
os.Exit(1)
fmsg.Fatal("malformed sandbox config:", err)
} else {
cmd := b.Unwrap()
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
cmd.ExtraFiles = extraFiles
if verbose.Get() {
verbose.Println("bwrap args:", conf.Args())
if fmsg.Verbose() {
fmsg.VPrintln("bwrap args:", conf.Args())
}
// run and pass through exit code
if err = b.Start(); err != nil {
fmt.Println("fortify-shim: cannot start target process:", err)
os.Exit(1)
fmsg.Fatal("cannot start target process:", err)
} else if err = b.Wait(); err != nil {
verbose.Println("wait:", err)
fmsg.VPrintln("wait:", err)
}
if b.Unwrap().ProcessState != nil {
os.Exit(b.Unwrap().ProcessState.ExitCode())

View File

@@ -3,13 +3,12 @@ package shim
import (
"encoding/gob"
"errors"
"fmt"
"net"
"os"
"syscall"
"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
@@ -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 {
return err
} else {
verbose.Println("connected to wayland at", wl)
fmsg.VPrintf("connected to wayland at %q", wl.Path)
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 {
return err
} 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 {
fmt.Println("fortify: cannot change permissions of shim setup socket:", err)
fmsg.Println("cannot change permissions of shim setup socket:", err)
}
go func() {
var conn *net.UnixConn
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 {
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)
return
}
@@ -47,23 +46,23 @@ func ServeConfig(socket string, uid int, payload *Payload, wl *Wayland) error {
// get raw connection
var rc syscall.RawConn
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
} else {
go func() {
// pass wayland socket fd
if err = rc.Control(func(fd uintptr) {
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
}
_ = conn.Close()
// block until shim exits
<-wl.done
verbose.Println("releasing wayland connection")
fmsg.VPrintln("releasing wayland connection")
}); 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 {
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) {
fmt.Println("fortify: cannot remove dangling shim socket:", err)
fmsg.Println("cannot remove dangling shim socket:", err)
}
}()
return nil