fortify: check print behaviour
These output are supposed to be deterministic, so checking them is a good way to catch regressions. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
1f74b636d3
commit
aaebb8f3ab
10
main.go
10
main.go
@ -13,6 +13,7 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/dbus"
|
||||
"git.gensokyo.uk/security/fortify/fst"
|
||||
@ -23,6 +24,7 @@ import (
|
||||
"git.gensokyo.uk/security/fortify/internal/linux"
|
||||
init0 "git.gensokyo.uk/security/fortify/internal/priv/init"
|
||||
"git.gensokyo.uk/security/fortify/internal/priv/shim"
|
||||
"git.gensokyo.uk/security/fortify/internal/state"
|
||||
"git.gensokyo.uk/security/fortify/internal/system"
|
||||
)
|
||||
|
||||
@ -114,7 +116,7 @@ func main() {
|
||||
fmt.Println(license)
|
||||
fmsg.Exit(0)
|
||||
case "template": // print full template configuration
|
||||
printJSON(fst.Template())
|
||||
printJSON(os.Stdout, false, fst.Template())
|
||||
fmsg.Exit(0)
|
||||
case "help": // print help message
|
||||
flag.CommandLine.Usage()
|
||||
@ -127,7 +129,7 @@ func main() {
|
||||
// Ignore errors; set is set for ExitOnError.
|
||||
_ = set.Parse(args[1:])
|
||||
|
||||
printPs(short)
|
||||
printPs(os.Stdout, time.Now().UTC(), state.NewMulti(sys.Paths().RunDirPath), short)
|
||||
fmsg.Exit(0)
|
||||
case "show": // pretty-print app info
|
||||
set := flag.NewFlagSet("show", flag.ExitOnError)
|
||||
@ -139,14 +141,14 @@ func main() {
|
||||
|
||||
switch len(set.Args()) {
|
||||
case 0: // system
|
||||
printShowSystem(short)
|
||||
printShowSystem(os.Stdout, short)
|
||||
case 1: // instance
|
||||
name := set.Args()[0]
|
||||
config, instance := tryShort(name)
|
||||
if config == nil {
|
||||
config = tryPath(name)
|
||||
}
|
||||
printShowInstance(instance, config, short)
|
||||
printShowInstance(os.Stdout, time.Now().UTC(), instance, config, short)
|
||||
default:
|
||||
fmsg.Fatal("show requires 1 argument")
|
||||
}
|
||||
|
196
print.go
196
print.go
@ -3,7 +3,7 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"io"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -16,7 +16,10 @@ import (
|
||||
"git.gensokyo.uk/security/fortify/internal/state"
|
||||
)
|
||||
|
||||
func printShowSystem(short bool) {
|
||||
func printShowSystem(output io.Writer, short bool) {
|
||||
t := newPrinter(output)
|
||||
defer t.MustFlush()
|
||||
|
||||
info := new(fst.Info)
|
||||
|
||||
// get fid by querying uid of aid 0
|
||||
@ -27,58 +30,55 @@ func printShowSystem(short bool) {
|
||||
}
|
||||
|
||||
if flagJSON {
|
||||
printJSON(info)
|
||||
printJSON(output, short, info)
|
||||
return
|
||||
}
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', 0)
|
||||
|
||||
fmt.Fprintf(w, "User:\t%d\n", info.User)
|
||||
|
||||
if err := w.Flush(); err != nil {
|
||||
fmsg.Fatalf("cannot flush tabwriter: %v", err)
|
||||
}
|
||||
t.Printf("User:\t%d\n", info.User)
|
||||
}
|
||||
|
||||
func printShowInstance(instance *state.State, config *fst.Config, short bool) {
|
||||
func printShowInstance(
|
||||
output io.Writer, now time.Time,
|
||||
instance *state.State, config *fst.Config,
|
||||
short bool) {
|
||||
if flagJSON {
|
||||
if instance != nil {
|
||||
printJSON(instance)
|
||||
printJSON(output, short, instance)
|
||||
} else {
|
||||
printJSON(config)
|
||||
printJSON(output, short, config)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', 0)
|
||||
t := newPrinter(output)
|
||||
defer t.MustFlush()
|
||||
|
||||
if config.Confinement.Sandbox == nil {
|
||||
fmt.Print("Warning: this configuration uses permissive defaults!\n\n")
|
||||
mustPrint(output, "Warning: this configuration uses permissive defaults!\n\n")
|
||||
}
|
||||
|
||||
if instance != nil {
|
||||
fmt.Fprintf(w, "State\n")
|
||||
fmt.Fprintf(w, " Instance:\t%s (%d)\n", instance.ID.String(), instance.PID)
|
||||
fmt.Fprintf(w, " Uptime:\t%s\n", now.Sub(instance.Time).Round(time.Second).String())
|
||||
fmt.Fprintf(w, "\n")
|
||||
t.Printf("State\n")
|
||||
t.Printf(" Instance:\t%s (%d)\n", instance.ID.String(), instance.PID)
|
||||
t.Printf(" Uptime:\t%s\n", now.Sub(instance.Time).Round(time.Second).String())
|
||||
t.Printf("\n")
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "App\n")
|
||||
t.Printf("App\n")
|
||||
if config.ID != "" {
|
||||
fmt.Fprintf(w, " ID:\t%d (%s)\n", config.Confinement.AppID, config.ID)
|
||||
t.Printf(" ID:\t%d (%s)\n", config.Confinement.AppID, config.ID)
|
||||
} else {
|
||||
fmt.Fprintf(w, " ID:\t%d\n", config.Confinement.AppID)
|
||||
t.Printf(" ID:\t%d\n", config.Confinement.AppID)
|
||||
}
|
||||
fmt.Fprintf(w, " Enablements:\t%s\n", config.Confinement.Enablements.String())
|
||||
t.Printf(" Enablements:\t%s\n", config.Confinement.Enablements.String())
|
||||
if len(config.Confinement.Groups) > 0 {
|
||||
fmt.Fprintf(w, " Groups:\t%q\n", config.Confinement.Groups)
|
||||
t.Printf(" Groups:\t%q\n", config.Confinement.Groups)
|
||||
}
|
||||
fmt.Fprintf(w, " Directory:\t%s\n", config.Confinement.Outer)
|
||||
t.Printf(" Directory:\t%s\n", config.Confinement.Outer)
|
||||
if config.Confinement.Sandbox != nil {
|
||||
sandbox := config.Confinement.Sandbox
|
||||
if sandbox.Hostname != "" {
|
||||
fmt.Fprintf(w, " Hostname:\t%q\n", sandbox.Hostname)
|
||||
t.Printf(" Hostname:\t%q\n", sandbox.Hostname)
|
||||
}
|
||||
flags := make([]string, 0, 7)
|
||||
writeFlag := func(name string, value bool) {
|
||||
@ -96,27 +96,27 @@ func printShowInstance(instance *state.State, config *fst.Config, short bool) {
|
||||
if len(flags) == 0 {
|
||||
flags = append(flags, "none")
|
||||
}
|
||||
fmt.Fprintf(w, " Flags:\t%s\n", strings.Join(flags, " "))
|
||||
t.Printf(" Flags:\t%s\n", strings.Join(flags, " "))
|
||||
|
||||
etc := sandbox.Etc
|
||||
if etc == "" {
|
||||
etc = "/etc"
|
||||
}
|
||||
fmt.Fprintf(w, " Etc:\t%s\n", etc)
|
||||
t.Printf(" Etc:\t%s\n", etc)
|
||||
|
||||
if len(sandbox.Override) > 0 {
|
||||
fmt.Fprintf(w, " Overrides:\t%s\n", strings.Join(sandbox.Override, " "))
|
||||
t.Printf(" Overrides:\t%s\n", strings.Join(sandbox.Override, " "))
|
||||
}
|
||||
|
||||
// Env map[string]string `json:"env"`
|
||||
// Link [][2]string `json:"symlink"`
|
||||
}
|
||||
fmt.Fprintf(w, " Command:\t%s\n", strings.Join(config.Command, " "))
|
||||
fmt.Fprintf(w, "\n")
|
||||
t.Printf(" Command:\t%s\n", strings.Join(config.Command, " "))
|
||||
t.Printf("\n")
|
||||
|
||||
if !short {
|
||||
if config.Confinement.Sandbox != nil && len(config.Confinement.Sandbox.Filesystem) > 0 {
|
||||
fmt.Fprintf(w, "Filesystem\n")
|
||||
t.Printf("Filesystem\n")
|
||||
for _, f := range config.Confinement.Sandbox.Filesystem {
|
||||
if f == nil {
|
||||
continue
|
||||
@ -141,61 +141,54 @@ func printShowInstance(instance *state.State, config *fst.Config, short bool) {
|
||||
if f.Dst != "" {
|
||||
expr.WriteString(":" + f.Dst)
|
||||
}
|
||||
fmt.Fprintf(w, "%s\n", expr.String())
|
||||
t.Printf("%s\n", expr.String())
|
||||
}
|
||||
fmt.Fprintf(w, "\n")
|
||||
t.Printf("\n")
|
||||
}
|
||||
if len(config.Confinement.ExtraPerms) > 0 {
|
||||
fmt.Fprintf(w, "Extra ACL\n")
|
||||
t.Printf("Extra ACL\n")
|
||||
for _, p := range config.Confinement.ExtraPerms {
|
||||
if p == nil {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, " %s\n", p.String())
|
||||
t.Printf(" %s\n", p.String())
|
||||
}
|
||||
fmt.Fprintf(w, "\n")
|
||||
t.Printf("\n")
|
||||
}
|
||||
}
|
||||
|
||||
printDBus := func(c *dbus.Config) {
|
||||
fmt.Fprintf(w, " Filter:\t%v\n", c.Filter)
|
||||
t.Printf(" Filter:\t%v\n", c.Filter)
|
||||
if len(c.See) > 0 {
|
||||
fmt.Fprintf(w, " See:\t%q\n", c.See)
|
||||
t.Printf(" See:\t%q\n", c.See)
|
||||
}
|
||||
if len(c.Talk) > 0 {
|
||||
fmt.Fprintf(w, " Talk:\t%q\n", c.Talk)
|
||||
t.Printf(" Talk:\t%q\n", c.Talk)
|
||||
}
|
||||
if len(c.Own) > 0 {
|
||||
fmt.Fprintf(w, " Own:\t%q\n", c.Own)
|
||||
t.Printf(" Own:\t%q\n", c.Own)
|
||||
}
|
||||
if len(c.Call) > 0 {
|
||||
fmt.Fprintf(w, " Call:\t%q\n", c.Call)
|
||||
t.Printf(" Call:\t%q\n", c.Call)
|
||||
}
|
||||
if len(c.Broadcast) > 0 {
|
||||
fmt.Fprintf(w, " Broadcast:\t%q\n", c.Broadcast)
|
||||
t.Printf(" Broadcast:\t%q\n", c.Broadcast)
|
||||
}
|
||||
}
|
||||
if config.Confinement.SessionBus != nil {
|
||||
fmt.Fprintf(w, "Session bus\n")
|
||||
t.Printf("Session bus\n")
|
||||
printDBus(config.Confinement.SessionBus)
|
||||
fmt.Fprintf(w, "\n")
|
||||
t.Printf("\n")
|
||||
}
|
||||
if config.Confinement.SystemBus != nil {
|
||||
fmt.Fprintf(w, "System bus\n")
|
||||
t.Printf("System bus\n")
|
||||
printDBus(config.Confinement.SystemBus)
|
||||
fmt.Fprintf(w, "\n")
|
||||
}
|
||||
|
||||
if err := w.Flush(); err != nil {
|
||||
fmsg.Fatalf("cannot flush tabwriter: %v", err)
|
||||
t.Printf("\n")
|
||||
}
|
||||
}
|
||||
|
||||
func printPs(short bool) {
|
||||
now := time.Now().UTC()
|
||||
|
||||
func printPs(output io.Writer, now time.Time, s state.Store, short bool) {
|
||||
var entries state.Entries
|
||||
s := state.NewMulti(sys.Paths().RunDirPath)
|
||||
if e, err := state.Join(s); err != nil {
|
||||
fmsg.Fatalf("cannot join store: %v", err)
|
||||
} else {
|
||||
@ -205,12 +198,12 @@ func printPs(short bool) {
|
||||
fmsg.Printf("cannot close store: %v", err)
|
||||
}
|
||||
|
||||
if flagJSON {
|
||||
if !short && flagJSON {
|
||||
es := make(map[string]*state.State, len(entries))
|
||||
for id, instance := range entries {
|
||||
es[id.String()] = instance
|
||||
}
|
||||
printJSON(es)
|
||||
printJSON(output, short, es)
|
||||
return
|
||||
}
|
||||
|
||||
@ -225,7 +218,7 @@ func printPs(short bool) {
|
||||
|
||||
// gracefully skip inconsistent states
|
||||
if id != instance.ID {
|
||||
fmt.Printf("possible store corruption: entry %s has id %s",
|
||||
fmsg.Printf("possible store corruption: entry %s has id %s",
|
||||
id.String(), instance.ID.String())
|
||||
continue
|
||||
}
|
||||
@ -239,25 +232,34 @@ func printPs(short bool) {
|
||||
for i, e := range exp {
|
||||
v[i] = e.s
|
||||
}
|
||||
printJSON(v)
|
||||
printJSON(output, short, v)
|
||||
} else {
|
||||
for _, e := range exp {
|
||||
fmt.Println(e.s[:8])
|
||||
mustPrintln(output, e.s[:8])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// buffer output to reduce terminal activity
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', 0)
|
||||
fmt.Fprintln(w, "\tInstance\tPID\tApp\tUptime\tEnablements\tCommand")
|
||||
t := newPrinter(output)
|
||||
defer t.MustFlush()
|
||||
|
||||
t.Println("\tInstance\tPID\tApp\tUptime\tEnablements\tCommand")
|
||||
for _, e := range exp {
|
||||
printInstance(w, e, now)
|
||||
}
|
||||
fmt.Fprintln(w)
|
||||
if err := w.Flush(); err != nil {
|
||||
fmsg.Fatalf("cannot flush tabwriter: %v", err)
|
||||
var (
|
||||
es = "(No confinement information)"
|
||||
cs = "(No command information)"
|
||||
as = "(No configuration information)"
|
||||
)
|
||||
if e.Config != nil {
|
||||
es = e.Config.Confinement.Enablements.String()
|
||||
cs = fmt.Sprintf("%q", e.Config.Command)
|
||||
as = strconv.Itoa(e.Config.Confinement.AppID)
|
||||
}
|
||||
t.Printf("\t%s\t%d\t%s\t%s\t%s\t%s\n",
|
||||
e.s[:8], e.PID, as, now.Sub(e.Time).Round(time.Second).String(), strings.TrimPrefix(es, ", "), cs)
|
||||
}
|
||||
t.Println()
|
||||
}
|
||||
|
||||
type expandedStateEntry struct {
|
||||
@ -265,26 +267,48 @@ type expandedStateEntry struct {
|
||||
*state.State
|
||||
}
|
||||
|
||||
func printInstance(w *tabwriter.Writer, e *expandedStateEntry, now time.Time) {
|
||||
var (
|
||||
es = "(No confinement information)"
|
||||
cs = "(No command information)"
|
||||
as = "(No configuration information)"
|
||||
)
|
||||
if e.Config != nil {
|
||||
es = e.Config.Confinement.Enablements.String()
|
||||
cs = fmt.Sprintf("%q", e.Config.Command)
|
||||
as = strconv.Itoa(e.Config.Confinement.AppID)
|
||||
func printJSON(output io.Writer, short bool, v any) {
|
||||
encoder := json.NewEncoder(output)
|
||||
if !short {
|
||||
encoder.SetIndent("", " ")
|
||||
}
|
||||
fmt.Fprintf(w, "\t%s\t%d\t%s\t%s\t%s\t%s\n",
|
||||
e.s[:8], e.PID, as, now.Sub(e.Time).Round(time.Second).String(), strings.TrimPrefix(es, ", "), cs)
|
||||
}
|
||||
|
||||
func printJSON(v any) {
|
||||
encoder := json.NewEncoder(os.Stdout)
|
||||
encoder.SetIndent("", " ")
|
||||
if err := encoder.Encode(v); err != nil {
|
||||
fmsg.Fatalf("cannot serialise: %v", err)
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
func newPrinter(output io.Writer) *tp { return &tp{tabwriter.NewWriter(output, 0, 1, 4, ' ', 0)} }
|
||||
|
||||
type tp struct{ *tabwriter.Writer }
|
||||
|
||||
func (p *tp) Printf(format string, a ...any) {
|
||||
if _, err := fmt.Fprintf(p, format, a...); err != nil {
|
||||
fmsg.Fatalf("cannot write to tabwriter: %v", err)
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
func (p *tp) Println(a ...any) {
|
||||
if _, err := fmt.Fprintln(p, a...); err != nil {
|
||||
fmsg.Fatalf("cannot write to tabwriter: %v", err)
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
func (p *tp) MustFlush() {
|
||||
if err := p.Writer.Flush(); err != nil {
|
||||
fmsg.Fatalf("cannot flush tabwriter: %v", err)
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
func mustPrint(output io.Writer, a ...any) {
|
||||
if _, err := fmt.Fprint(output, a...); err != nil {
|
||||
fmsg.Fatalf("cannot print: %v", err)
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
func mustPrintln(output io.Writer, a ...any) {
|
||||
if _, err := fmt.Fprintln(output, a...); err != nil {
|
||||
fmsg.Fatalf("cannot print: %v", err)
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
671
print_test.go
Normal file
671
print_test.go
Normal file
@ -0,0 +1,671 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.gensokyo.uk/security/fortify/dbus"
|
||||
"git.gensokyo.uk/security/fortify/fst"
|
||||
"git.gensokyo.uk/security/fortify/internal/state"
|
||||
)
|
||||
|
||||
var (
|
||||
testID = fst.ID{
|
||||
0x8e, 0x2c, 0x76, 0xb0,
|
||||
0x66, 0xda, 0xbe, 0x57,
|
||||
0x4c, 0xf0, 0x73, 0xbd,
|
||||
0xb4, 0x6e, 0xb5, 0xc1,
|
||||
}
|
||||
testState = &state.State{
|
||||
ID: testID,
|
||||
PID: 0xDEADBEEF,
|
||||
Config: fst.Template(),
|
||||
Time: testAppTime,
|
||||
}
|
||||
testTime = time.Unix(3752, 1).UTC()
|
||||
testAppTime = time.Unix(0, 9).UTC()
|
||||
)
|
||||
|
||||
func Test_printShowInstance(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
instance *state.State
|
||||
config *fst.Config
|
||||
short, json bool
|
||||
want string
|
||||
}{
|
||||
{"config", nil, fst.Template(), false, false, `App
|
||||
ID: 9 (org.chromium.Chromium)
|
||||
Enablements: Wayland, D-Bus, PulseAudio
|
||||
Groups: ["video"]
|
||||
Directory: /var/lib/persist/home/org.chromium.Chromium
|
||||
Hostname: "localhost"
|
||||
Flags: userns net dev tty mapuid autoetc
|
||||
Etc: /etc
|
||||
Overrides: /var/run/nscd
|
||||
Command: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
|
||||
|
||||
Filesystem
|
||||
+/nix/store
|
||||
+/run/current-system
|
||||
+/run/opengl-driver
|
||||
+/var/db/nix-channels
|
||||
w*/var/lib/fortify/u0/org.chromium.Chromium:/data/data/org.chromium.Chromium
|
||||
d+/dev/dri
|
||||
|
||||
Extra ACL
|
||||
--x+:/var/lib/fortify/u0
|
||||
rwx:/var/lib/fortify/u0/org.chromium.Chromium
|
||||
|
||||
Session bus
|
||||
Filter: true
|
||||
Talk: ["org.freedesktop.Notifications" "org.freedesktop.FileManager1" "org.freedesktop.ScreenSaver" "org.freedesktop.secrets" "org.kde.kwalletd5" "org.kde.kwalletd6" "org.gnome.SessionManager"]
|
||||
Own: ["org.chromium.Chromium.*" "org.mpris.MediaPlayer2.org.chromium.Chromium.*" "org.mpris.MediaPlayer2.chromium.*"]
|
||||
Call: map["org.freedesktop.portal.*":"*"]
|
||||
Broadcast: map["org.freedesktop.portal.*":"@/org/freedesktop/portal/*"]
|
||||
|
||||
System bus
|
||||
Filter: true
|
||||
Talk: ["org.bluez" "org.freedesktop.Avahi" "org.freedesktop.UPower"]
|
||||
|
||||
`},
|
||||
{"config pd", nil, new(fst.Config), false, false, `Warning: this configuration uses permissive defaults!
|
||||
|
||||
App
|
||||
ID: 0
|
||||
Enablements: (No enablements)
|
||||
Directory:
|
||||
Command:
|
||||
|
||||
`},
|
||||
{"config flag none", nil, &fst.Config{Confinement: fst.ConfinementConfig{Sandbox: new(fst.SandboxConfig)}}, false, false, `App
|
||||
ID: 0
|
||||
Enablements: (No enablements)
|
||||
Directory:
|
||||
Flags: none
|
||||
Etc: /etc
|
||||
Command:
|
||||
|
||||
`},
|
||||
{"config nil entries", nil, &fst.Config{Confinement: fst.ConfinementConfig{Sandbox: &fst.SandboxConfig{Filesystem: make([]*fst.FilesystemConfig, 1)}, ExtraPerms: make([]*fst.ExtraPermConfig, 1)}}, false, false, `App
|
||||
ID: 0
|
||||
Enablements: (No enablements)
|
||||
Directory:
|
||||
Flags: none
|
||||
Etc: /etc
|
||||
Command:
|
||||
|
||||
Filesystem
|
||||
|
||||
Extra ACL
|
||||
|
||||
`},
|
||||
{"config pd dbus see", nil, &fst.Config{Confinement: fst.ConfinementConfig{SessionBus: &dbus.Config{See: []string{"org.example.test"}}}}, false, false, `Warning: this configuration uses permissive defaults!
|
||||
|
||||
App
|
||||
ID: 0
|
||||
Enablements: (No enablements)
|
||||
Directory:
|
||||
Command:
|
||||
|
||||
Session bus
|
||||
Filter: false
|
||||
See: ["org.example.test"]
|
||||
|
||||
`},
|
||||
|
||||
{"instance", testState, fst.Template(), false, false, `State
|
||||
Instance: 8e2c76b066dabe574cf073bdb46eb5c1 (3735928559)
|
||||
Uptime: 1h2m32s
|
||||
|
||||
App
|
||||
ID: 9 (org.chromium.Chromium)
|
||||
Enablements: Wayland, D-Bus, PulseAudio
|
||||
Groups: ["video"]
|
||||
Directory: /var/lib/persist/home/org.chromium.Chromium
|
||||
Hostname: "localhost"
|
||||
Flags: userns net dev tty mapuid autoetc
|
||||
Etc: /etc
|
||||
Overrides: /var/run/nscd
|
||||
Command: chromium --ignore-gpu-blocklist --disable-smooth-scrolling --enable-features=UseOzonePlatform --ozone-platform=wayland
|
||||
|
||||
Filesystem
|
||||
+/nix/store
|
||||
+/run/current-system
|
||||
+/run/opengl-driver
|
||||
+/var/db/nix-channels
|
||||
w*/var/lib/fortify/u0/org.chromium.Chromium:/data/data/org.chromium.Chromium
|
||||
d+/dev/dri
|
||||
|
||||
Extra ACL
|
||||
--x+:/var/lib/fortify/u0
|
||||
rwx:/var/lib/fortify/u0/org.chromium.Chromium
|
||||
|
||||
Session bus
|
||||
Filter: true
|
||||
Talk: ["org.freedesktop.Notifications" "org.freedesktop.FileManager1" "org.freedesktop.ScreenSaver" "org.freedesktop.secrets" "org.kde.kwalletd5" "org.kde.kwalletd6" "org.gnome.SessionManager"]
|
||||
Own: ["org.chromium.Chromium.*" "org.mpris.MediaPlayer2.org.chromium.Chromium.*" "org.mpris.MediaPlayer2.chromium.*"]
|
||||
Call: map["org.freedesktop.portal.*":"*"]
|
||||
Broadcast: map["org.freedesktop.portal.*":"@/org/freedesktop/portal/*"]
|
||||
|
||||
System bus
|
||||
Filter: true
|
||||
Talk: ["org.bluez" "org.freedesktop.Avahi" "org.freedesktop.UPower"]
|
||||
|
||||
`},
|
||||
{"instance pd", testState, new(fst.Config), false, false, `Warning: this configuration uses permissive defaults!
|
||||
|
||||
State
|
||||
Instance: 8e2c76b066dabe574cf073bdb46eb5c1 (3735928559)
|
||||
Uptime: 1h2m32s
|
||||
|
||||
App
|
||||
ID: 0
|
||||
Enablements: (No enablements)
|
||||
Directory:
|
||||
Command:
|
||||
|
||||
`},
|
||||
|
||||
{"json nil", nil, nil, false, true, `null
|
||||
`},
|
||||
{"json instance", testState, nil, false, true, `{
|
||||
"instance": [
|
||||
142,
|
||||
44,
|
||||
118,
|
||||
176,
|
||||
102,
|
||||
218,
|
||||
190,
|
||||
87,
|
||||
76,
|
||||
240,
|
||||
115,
|
||||
189,
|
||||
180,
|
||||
110,
|
||||
181,
|
||||
193
|
||||
],
|
||||
"pid": 3735928559,
|
||||
"config": {
|
||||
"id": "org.chromium.Chromium",
|
||||
"command": [
|
||||
"chromium",
|
||||
"--ignore-gpu-blocklist",
|
||||
"--disable-smooth-scrolling",
|
||||
"--enable-features=UseOzonePlatform",
|
||||
"--ozone-platform=wayland"
|
||||
],
|
||||
"confinement": {
|
||||
"app_id": 9,
|
||||
"groups": [
|
||||
"video"
|
||||
],
|
||||
"username": "chronos",
|
||||
"home_inner": "/var/lib/fortify",
|
||||
"home": "/var/lib/persist/home/org.chromium.Chromium",
|
||||
"sandbox": {
|
||||
"hostname": "localhost",
|
||||
"userns": true,
|
||||
"net": true,
|
||||
"dev": true,
|
||||
"syscall": {
|
||||
"compat": false,
|
||||
"deny_devel": true,
|
||||
"multiarch": true,
|
||||
"linux32": false,
|
||||
"can": false,
|
||||
"bluetooth": false
|
||||
},
|
||||
"no_new_session": true,
|
||||
"map_real_uid": true,
|
||||
"env": {
|
||||
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
||||
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
||||
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
||||
},
|
||||
"filesystem": [
|
||||
{
|
||||
"src": "/nix/store"
|
||||
},
|
||||
{
|
||||
"src": "/run/current-system"
|
||||
},
|
||||
{
|
||||
"src": "/run/opengl-driver"
|
||||
},
|
||||
{
|
||||
"src": "/var/db/nix-channels"
|
||||
},
|
||||
{
|
||||
"dst": "/data/data/org.chromium.Chromium",
|
||||
"src": "/var/lib/fortify/u0/org.chromium.Chromium",
|
||||
"write": true,
|
||||
"require": true
|
||||
},
|
||||
{
|
||||
"src": "/dev/dri",
|
||||
"dev": true
|
||||
}
|
||||
],
|
||||
"symlink": [
|
||||
[
|
||||
"/run/user/65534",
|
||||
"/run/user/150"
|
||||
]
|
||||
],
|
||||
"etc": "/etc",
|
||||
"auto_etc": true,
|
||||
"override": [
|
||||
"/var/run/nscd"
|
||||
]
|
||||
},
|
||||
"extra_perms": [
|
||||
{
|
||||
"ensure": true,
|
||||
"path": "/var/lib/fortify/u0",
|
||||
"x": true
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/fortify/u0/org.chromium.Chromium",
|
||||
"r": true,
|
||||
"w": true,
|
||||
"x": true
|
||||
}
|
||||
],
|
||||
"system_bus": {
|
||||
"see": null,
|
||||
"talk": [
|
||||
"org.bluez",
|
||||
"org.freedesktop.Avahi",
|
||||
"org.freedesktop.UPower"
|
||||
],
|
||||
"own": null,
|
||||
"call": null,
|
||||
"broadcast": null,
|
||||
"filter": true
|
||||
},
|
||||
"session_bus": {
|
||||
"see": null,
|
||||
"talk": [
|
||||
"org.freedesktop.Notifications",
|
||||
"org.freedesktop.FileManager1",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"org.freedesktop.secrets",
|
||||
"org.kde.kwalletd5",
|
||||
"org.kde.kwalletd6",
|
||||
"org.gnome.SessionManager"
|
||||
],
|
||||
"own": [
|
||||
"org.chromium.Chromium.*",
|
||||
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
||||
"org.mpris.MediaPlayer2.chromium.*"
|
||||
],
|
||||
"call": {
|
||||
"org.freedesktop.portal.*": "*"
|
||||
},
|
||||
"broadcast": {
|
||||
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*"
|
||||
},
|
||||
"filter": true
|
||||
},
|
||||
"enablements": 13
|
||||
}
|
||||
},
|
||||
"time": "1970-01-01T00:00:00.000000009Z"
|
||||
}
|
||||
`},
|
||||
{"json config", nil, fst.Template(), false, true, `{
|
||||
"id": "org.chromium.Chromium",
|
||||
"command": [
|
||||
"chromium",
|
||||
"--ignore-gpu-blocklist",
|
||||
"--disable-smooth-scrolling",
|
||||
"--enable-features=UseOzonePlatform",
|
||||
"--ozone-platform=wayland"
|
||||
],
|
||||
"confinement": {
|
||||
"app_id": 9,
|
||||
"groups": [
|
||||
"video"
|
||||
],
|
||||
"username": "chronos",
|
||||
"home_inner": "/var/lib/fortify",
|
||||
"home": "/var/lib/persist/home/org.chromium.Chromium",
|
||||
"sandbox": {
|
||||
"hostname": "localhost",
|
||||
"userns": true,
|
||||
"net": true,
|
||||
"dev": true,
|
||||
"syscall": {
|
||||
"compat": false,
|
||||
"deny_devel": true,
|
||||
"multiarch": true,
|
||||
"linux32": false,
|
||||
"can": false,
|
||||
"bluetooth": false
|
||||
},
|
||||
"no_new_session": true,
|
||||
"map_real_uid": true,
|
||||
"env": {
|
||||
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
||||
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
||||
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
||||
},
|
||||
"filesystem": [
|
||||
{
|
||||
"src": "/nix/store"
|
||||
},
|
||||
{
|
||||
"src": "/run/current-system"
|
||||
},
|
||||
{
|
||||
"src": "/run/opengl-driver"
|
||||
},
|
||||
{
|
||||
"src": "/var/db/nix-channels"
|
||||
},
|
||||
{
|
||||
"dst": "/data/data/org.chromium.Chromium",
|
||||
"src": "/var/lib/fortify/u0/org.chromium.Chromium",
|
||||
"write": true,
|
||||
"require": true
|
||||
},
|
||||
{
|
||||
"src": "/dev/dri",
|
||||
"dev": true
|
||||
}
|
||||
],
|
||||
"symlink": [
|
||||
[
|
||||
"/run/user/65534",
|
||||
"/run/user/150"
|
||||
]
|
||||
],
|
||||
"etc": "/etc",
|
||||
"auto_etc": true,
|
||||
"override": [
|
||||
"/var/run/nscd"
|
||||
]
|
||||
},
|
||||
"extra_perms": [
|
||||
{
|
||||
"ensure": true,
|
||||
"path": "/var/lib/fortify/u0",
|
||||
"x": true
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/fortify/u0/org.chromium.Chromium",
|
||||
"r": true,
|
||||
"w": true,
|
||||
"x": true
|
||||
}
|
||||
],
|
||||
"system_bus": {
|
||||
"see": null,
|
||||
"talk": [
|
||||
"org.bluez",
|
||||
"org.freedesktop.Avahi",
|
||||
"org.freedesktop.UPower"
|
||||
],
|
||||
"own": null,
|
||||
"call": null,
|
||||
"broadcast": null,
|
||||
"filter": true
|
||||
},
|
||||
"session_bus": {
|
||||
"see": null,
|
||||
"talk": [
|
||||
"org.freedesktop.Notifications",
|
||||
"org.freedesktop.FileManager1",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"org.freedesktop.secrets",
|
||||
"org.kde.kwalletd5",
|
||||
"org.kde.kwalletd6",
|
||||
"org.gnome.SessionManager"
|
||||
],
|
||||
"own": [
|
||||
"org.chromium.Chromium.*",
|
||||
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
||||
"org.mpris.MediaPlayer2.chromium.*"
|
||||
],
|
||||
"call": {
|
||||
"org.freedesktop.portal.*": "*"
|
||||
},
|
||||
"broadcast": {
|
||||
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*"
|
||||
},
|
||||
"filter": true
|
||||
},
|
||||
"enablements": 13
|
||||
}
|
||||
}
|
||||
`},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
{
|
||||
v := flagJSON
|
||||
t.Cleanup(func() { flagJSON = v })
|
||||
flagJSON = tc.json
|
||||
}
|
||||
|
||||
output := new(strings.Builder)
|
||||
printShowInstance(output, testTime, tc.instance, tc.config, tc.short)
|
||||
if got := output.String(); got != tc.want {
|
||||
t.Errorf("printShowInstance: got\n%s\nwant\n%s",
|
||||
got, tc.want)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_printPs(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
entries state.Entries
|
||||
short, json bool
|
||||
want string
|
||||
}{
|
||||
{"no entries", make(state.Entries), false, false, ` Instance PID App Uptime Enablements Command
|
||||
|
||||
`},
|
||||
{"no entries short", make(state.Entries), true, false, ``},
|
||||
{"nil instance", state.Entries{testID: nil}, false, false, ` Instance PID App Uptime Enablements Command
|
||||
|
||||
`},
|
||||
{"state corruption", state.Entries{fst.ID{}: testState}, false, false, ` Instance PID App Uptime Enablements Command
|
||||
|
||||
`},
|
||||
|
||||
{"valid", state.Entries{testID: testState}, false, false, ` Instance PID App Uptime Enablements Command
|
||||
8e2c76b0 3735928559 9 1h2m32s Wayland, D-Bus, PulseAudio ["chromium" "--ignore-gpu-blocklist" "--disable-smooth-scrolling" "--enable-features=UseOzonePlatform" "--ozone-platform=wayland"]
|
||||
|
||||
`},
|
||||
{"valid short", state.Entries{testID: testState}, true, false, `8e2c76b0
|
||||
`},
|
||||
{"valid json", state.Entries{testID: testState}, false, true, `{
|
||||
"8e2c76b066dabe574cf073bdb46eb5c1": {
|
||||
"instance": [
|
||||
142,
|
||||
44,
|
||||
118,
|
||||
176,
|
||||
102,
|
||||
218,
|
||||
190,
|
||||
87,
|
||||
76,
|
||||
240,
|
||||
115,
|
||||
189,
|
||||
180,
|
||||
110,
|
||||
181,
|
||||
193
|
||||
],
|
||||
"pid": 3735928559,
|
||||
"config": {
|
||||
"id": "org.chromium.Chromium",
|
||||
"command": [
|
||||
"chromium",
|
||||
"--ignore-gpu-blocklist",
|
||||
"--disable-smooth-scrolling",
|
||||
"--enable-features=UseOzonePlatform",
|
||||
"--ozone-platform=wayland"
|
||||
],
|
||||
"confinement": {
|
||||
"app_id": 9,
|
||||
"groups": [
|
||||
"video"
|
||||
],
|
||||
"username": "chronos",
|
||||
"home_inner": "/var/lib/fortify",
|
||||
"home": "/var/lib/persist/home/org.chromium.Chromium",
|
||||
"sandbox": {
|
||||
"hostname": "localhost",
|
||||
"userns": true,
|
||||
"net": true,
|
||||
"dev": true,
|
||||
"syscall": {
|
||||
"compat": false,
|
||||
"deny_devel": true,
|
||||
"multiarch": true,
|
||||
"linux32": false,
|
||||
"can": false,
|
||||
"bluetooth": false
|
||||
},
|
||||
"no_new_session": true,
|
||||
"map_real_uid": true,
|
||||
"env": {
|
||||
"GOOGLE_API_KEY": "AIzaSyBHDrl33hwRp4rMQY0ziRbj8K9LPA6vUCY",
|
||||
"GOOGLE_DEFAULT_CLIENT_ID": "77185425430.apps.googleusercontent.com",
|
||||
"GOOGLE_DEFAULT_CLIENT_SECRET": "OTJgUOQcT7lO7GsGZq2G4IlT"
|
||||
},
|
||||
"filesystem": [
|
||||
{
|
||||
"src": "/nix/store"
|
||||
},
|
||||
{
|
||||
"src": "/run/current-system"
|
||||
},
|
||||
{
|
||||
"src": "/run/opengl-driver"
|
||||
},
|
||||
{
|
||||
"src": "/var/db/nix-channels"
|
||||
},
|
||||
{
|
||||
"dst": "/data/data/org.chromium.Chromium",
|
||||
"src": "/var/lib/fortify/u0/org.chromium.Chromium",
|
||||
"write": true,
|
||||
"require": true
|
||||
},
|
||||
{
|
||||
"src": "/dev/dri",
|
||||
"dev": true
|
||||
}
|
||||
],
|
||||
"symlink": [
|
||||
[
|
||||
"/run/user/65534",
|
||||
"/run/user/150"
|
||||
]
|
||||
],
|
||||
"etc": "/etc",
|
||||
"auto_etc": true,
|
||||
"override": [
|
||||
"/var/run/nscd"
|
||||
]
|
||||
},
|
||||
"extra_perms": [
|
||||
{
|
||||
"ensure": true,
|
||||
"path": "/var/lib/fortify/u0",
|
||||
"x": true
|
||||
},
|
||||
{
|
||||
"path": "/var/lib/fortify/u0/org.chromium.Chromium",
|
||||
"r": true,
|
||||
"w": true,
|
||||
"x": true
|
||||
}
|
||||
],
|
||||
"system_bus": {
|
||||
"see": null,
|
||||
"talk": [
|
||||
"org.bluez",
|
||||
"org.freedesktop.Avahi",
|
||||
"org.freedesktop.UPower"
|
||||
],
|
||||
"own": null,
|
||||
"call": null,
|
||||
"broadcast": null,
|
||||
"filter": true
|
||||
},
|
||||
"session_bus": {
|
||||
"see": null,
|
||||
"talk": [
|
||||
"org.freedesktop.Notifications",
|
||||
"org.freedesktop.FileManager1",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"org.freedesktop.secrets",
|
||||
"org.kde.kwalletd5",
|
||||
"org.kde.kwalletd6",
|
||||
"org.gnome.SessionManager"
|
||||
],
|
||||
"own": [
|
||||
"org.chromium.Chromium.*",
|
||||
"org.mpris.MediaPlayer2.org.chromium.Chromium.*",
|
||||
"org.mpris.MediaPlayer2.chromium.*"
|
||||
],
|
||||
"call": {
|
||||
"org.freedesktop.portal.*": "*"
|
||||
},
|
||||
"broadcast": {
|
||||
"org.freedesktop.portal.*": "@/org/freedesktop/portal/*"
|
||||
},
|
||||
"filter": true
|
||||
},
|
||||
"enablements": 13
|
||||
}
|
||||
},
|
||||
"time": "1970-01-01T00:00:00.000000009Z"
|
||||
}
|
||||
}
|
||||
`},
|
||||
{"valid short json", state.Entries{testID: testState}, true, true, `["8e2c76b066dabe574cf073bdb46eb5c1"]
|
||||
`},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
{
|
||||
v := flagJSON
|
||||
t.Cleanup(func() { flagJSON = v })
|
||||
flagJSON = tc.json
|
||||
}
|
||||
|
||||
output := new(strings.Builder)
|
||||
printPs(output, testTime, stubStore(tc.entries), tc.short)
|
||||
if got := output.String(); got != tc.want {
|
||||
t.Errorf("printPs: got\n%s\nwant\n%s",
|
||||
got, tc.want)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// stubStore implements [state.Store] and returns test samples via [state.Joiner].
|
||||
type stubStore state.Entries
|
||||
|
||||
func (s stubStore) Join() (state.Entries, error) { return state.Entries(s), nil }
|
||||
func (s stubStore) Do(int, func(c state.Cursor)) (bool, error) { panic("unreachable") }
|
||||
func (s stubStore) List() ([]int, error) { panic("unreachable") }
|
||||
func (s stubStore) Close() error { return nil }
|
Loading…
Reference in New Issue
Block a user