2024-09-08 02:24:01 +09:00
|
|
|
package app
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"strings"
|
|
|
|
|
2024-09-17 13:48:42 +09:00
|
|
|
"git.ophivana.moe/cat/fortify/internal"
|
2024-09-08 02:24:01 +09:00
|
|
|
"git.ophivana.moe/cat/fortify/internal/state"
|
|
|
|
"git.ophivana.moe/cat/fortify/internal/util"
|
2024-09-12 21:07:05 +09:00
|
|
|
"git.ophivana.moe/cat/fortify/internal/verbose"
|
2024-09-08 02:24:01 +09:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
term = "TERM"
|
|
|
|
sudoAskPass = "SUDO_ASKPASS"
|
|
|
|
)
|
|
|
|
const (
|
2024-09-12 20:53:33 +09:00
|
|
|
LaunchMethodSudo uint8 = iota
|
|
|
|
LaunchMethodBwrap
|
2024-09-08 02:24:01 +09:00
|
|
|
LaunchMethodMachineCtl
|
|
|
|
)
|
|
|
|
|
|
|
|
func (a *App) Run() {
|
|
|
|
// pass $TERM to launcher
|
|
|
|
if t, ok := os.LookupEnv(term); ok {
|
|
|
|
a.AppendEnv(term, t)
|
|
|
|
}
|
|
|
|
|
2024-09-12 20:53:33 +09:00
|
|
|
var commandBuilder func() (args []string)
|
|
|
|
|
|
|
|
switch a.launchOption {
|
|
|
|
case LaunchMethodSudo:
|
|
|
|
commandBuilder = a.commandBuilderSudo
|
|
|
|
case LaunchMethodBwrap:
|
|
|
|
commandBuilder = a.commandBuilderBwrap
|
|
|
|
case LaunchMethodMachineCtl:
|
|
|
|
commandBuilder = a.commandBuilderMachineCtl
|
|
|
|
default:
|
|
|
|
panic("unreachable")
|
2024-09-08 02:24:01 +09:00
|
|
|
}
|
|
|
|
|
2024-09-12 20:53:33 +09:00
|
|
|
cmd := exec.Command(a.toolPath, commandBuilder()...)
|
2024-09-09 22:24:58 +09:00
|
|
|
cmd.Env = []string{}
|
2024-09-08 02:24:01 +09:00
|
|
|
cmd.Stdin = os.Stdin
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
cmd.Stderr = os.Stderr
|
2024-09-16 20:31:15 +09:00
|
|
|
cmd.Dir = a.runDirPath
|
2024-09-08 02:24:01 +09:00
|
|
|
|
2024-09-12 21:07:05 +09:00
|
|
|
verbose.Println("Executing:", cmd)
|
2024-09-08 02:24:01 +09:00
|
|
|
|
|
|
|
if err := cmd.Start(); err != nil {
|
2024-09-17 13:48:42 +09:00
|
|
|
internal.Fatal("Error starting process:", err)
|
2024-09-08 02:24:01 +09:00
|
|
|
}
|
|
|
|
|
2024-09-17 13:48:42 +09:00
|
|
|
a.exit.SealEnablements(a.enablements)
|
2024-09-08 02:24:01 +09:00
|
|
|
|
2024-09-16 20:31:15 +09:00
|
|
|
if statePath, err := state.SaveProcess(a.Uid, cmd, a.runDirPath, a.command, a.enablements); err != nil {
|
2024-09-08 02:24:01 +09:00
|
|
|
// process already started, shouldn't be fatal
|
|
|
|
fmt.Println("Error registering process:", err)
|
2024-09-16 20:31:15 +09:00
|
|
|
} else {
|
2024-09-17 13:48:42 +09:00
|
|
|
a.exit.SealStatePath(statePath)
|
2024-09-08 02:24:01 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
var r int
|
|
|
|
if err := cmd.Wait(); err != nil {
|
|
|
|
var exitError *exec.ExitError
|
|
|
|
if !errors.As(err, &exitError) {
|
2024-09-17 13:48:42 +09:00
|
|
|
internal.Fatal("Error running process:", err)
|
2024-09-08 02:24:01 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-12 21:07:05 +09:00
|
|
|
verbose.Println("Process exited with exit code", r)
|
2024-09-17 13:48:42 +09:00
|
|
|
internal.BeforeExit()
|
2024-09-08 02:24:01 +09:00
|
|
|
os.Exit(r)
|
|
|
|
}
|
|
|
|
|
2024-09-09 00:32:17 +09:00
|
|
|
func (a *App) commandBuilderSudo() (args []string) {
|
2024-09-08 02:24:01 +09:00
|
|
|
args = make([]string, 0, 4+len(a.env)+len(a.command))
|
|
|
|
|
|
|
|
// -Hiu $USER
|
|
|
|
args = append(args, "-Hiu", a.Username)
|
|
|
|
|
|
|
|
// -A?
|
|
|
|
if _, ok := os.LookupEnv(sudoAskPass); ok {
|
2024-09-12 21:07:05 +09:00
|
|
|
verbose.Printf("%s set, adding askpass flag\n", sudoAskPass)
|
2024-09-08 02:24:01 +09:00
|
|
|
args = append(args, "-A")
|
|
|
|
}
|
|
|
|
|
|
|
|
// environ
|
|
|
|
args = append(args, a.env...)
|
|
|
|
|
|
|
|
// -- $@
|
|
|
|
args = append(args, "--")
|
|
|
|
args = append(args, a.command...)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-09-12 20:53:33 +09:00
|
|
|
func (a *App) commandBuilderBwrap() (args []string) {
|
|
|
|
// TODO: build bwrap command
|
2024-09-17 13:48:42 +09:00
|
|
|
internal.Fatal("bwrap")
|
2024-09-12 20:53:33 +09:00
|
|
|
panic("unreachable")
|
|
|
|
}
|
|
|
|
|
2024-09-09 00:32:17 +09:00
|
|
|
func (a *App) commandBuilderMachineCtl() (args []string) {
|
2024-09-08 02:24:01 +09:00
|
|
|
args = make([]string, 0, 9+len(a.env))
|
|
|
|
|
|
|
|
// shell --uid=$USER
|
|
|
|
args = append(args, "shell", "--uid="+a.Username)
|
|
|
|
|
|
|
|
// --quiet
|
2024-09-12 21:07:05 +09:00
|
|
|
if !verbose.Get() {
|
2024-09-08 02:24:01 +09:00
|
|
|
args = append(args, "--quiet")
|
|
|
|
}
|
|
|
|
|
|
|
|
// environ
|
|
|
|
envQ := make([]string, len(a.env)+1)
|
|
|
|
for i, e := range a.env {
|
|
|
|
envQ[i] = "-E" + e
|
|
|
|
}
|
|
|
|
envQ[len(a.env)] = "-E" + a.launcherPayloadEnv()
|
|
|
|
args = append(args, envQ...)
|
|
|
|
|
|
|
|
// -- .host
|
|
|
|
args = append(args, "--", ".host")
|
|
|
|
|
|
|
|
// /bin/sh -c
|
|
|
|
if sh, ok := util.Which("sh"); !ok {
|
2024-09-17 13:48:42 +09:00
|
|
|
internal.Fatal("Did not find 'sh' in PATH")
|
2024-09-08 02:24:01 +09:00
|
|
|
} else {
|
|
|
|
args = append(args, sh, "-c")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(a.command) == 0 { // execute shell if command is not provided
|
|
|
|
a.command = []string{"$SHELL"}
|
|
|
|
}
|
|
|
|
|
|
|
|
innerCommand := strings.Builder{}
|
|
|
|
|
2024-09-09 00:32:17 +09:00
|
|
|
innerCommand.WriteString("dbus-update-activation-environment --systemd")
|
|
|
|
for _, e := range a.env {
|
|
|
|
innerCommand.WriteString(" " + strings.SplitN(e, "=", 2)[0])
|
2024-09-08 02:24:01 +09:00
|
|
|
}
|
2024-09-09 00:32:17 +09:00
|
|
|
innerCommand.WriteString("; ")
|
2024-09-08 02:24:01 +09:00
|
|
|
|
|
|
|
if executable, err := os.Executable(); err != nil {
|
2024-09-17 13:48:42 +09:00
|
|
|
internal.Fatal("Error reading executable path:", err)
|
2024-09-08 02:24:01 +09:00
|
|
|
} else {
|
2024-09-17 13:48:42 +09:00
|
|
|
if a.enablements.Has(internal.EnableDBus) {
|
2024-09-09 21:19:12 +09:00
|
|
|
innerCommand.WriteString(dbusSessionBusAddress + "=" + "'" + dbusAddress[0] + "' ")
|
|
|
|
if dbusSystem {
|
|
|
|
innerCommand.WriteString(dbusSystemBusAddress + "=" + "'" + dbusAddress[1] + "' ")
|
|
|
|
}
|
2024-09-09 03:16:54 +09:00
|
|
|
}
|
2024-09-08 02:24:01 +09:00
|
|
|
innerCommand.WriteString("exec " + executable + " -V")
|
|
|
|
}
|
|
|
|
args = append(args, innerCommand.String())
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|