package main import ( "encoding/json" "flag" "os" "path" "git.gensokyo.uk/security/fortify/fst" "git.gensokyo.uk/security/fortify/internal/fmsg" ) func actionStart(args []string) { set := flag.NewFlagSet("start", flag.ExitOnError) var dropShell bool set.BoolVar(&dropShell, "s", false, "Drop to a shell on activation") // Ignore errors; set is set for ExitOnError. _ = set.Parse(args) args = set.Args() if len(args) < 1 { fmsg.Fatal("invalid argument") } name := args[0] if !path.IsAbs(name) { if dir, err := os.Getwd(); err != nil { fmsg.Fatalf("cannot get current directory: %v", err) } else { name = path.Join(dir, name) } } bundle := new(bundleInfo) if f, err := os.Open(path.Join(name, "bundle.json")); err != nil { fmsg.Fatalf("cannot open bundle: %v", err) } else if err = json.NewDecoder(f).Decode(&bundle); err != nil { fmsg.Fatalf("cannot parse bundle metadata: %v", err) } else if err = f.Close(); err != nil { fmsg.Printf("cannot close bundle metadata: %v", err) } command := make([]string, 1, len(args)) if !dropShell { command[0] = bundle.Launcher } else { command[0] = shell } command = append(command, args[1:]...) baseDir := path.Join(dataHome, bundle.ID) homeDir := path.Join(baseDir, "files") config := &fst.Config{ ID: bundle.ID, Command: command, Confinement: fst.ConfinementConfig{ AppID: bundle.AppID, Groups: bundle.Groups, Username: "fortify", Inner: path.Join("/data/data", bundle.ID), Outer: homeDir, Sandbox: &fst.SandboxConfig{ Hostname: formatHostname(bundle.Name), UserNS: bundle.UserNS, Net: bundle.Net, Dev: bundle.Dev, NoNewSession: bundle.NoNewSession || dropShell, MapRealUID: bundle.MapRealUID, DirectWayland: bundle.DirectWayland, Filesystem: []*fst.FilesystemConfig{ {Src: path.Join(name, "nix"), Dst: "/nix", Must: true}, {Src: "/etc/resolv.conf"}, {Src: "/sys/block"}, {Src: "/sys/bus"}, {Src: "/sys/class"}, {Src: "/sys/dev"}, {Src: "/sys/devices"}, }, Link: [][2]string{ {bundle.CurrentSystem, "/run/current-system"}, {"/run/current-system/sw/bin", "/bin"}, {"/run/current-system/sw/bin", "/usr/bin"}, }, Etc: path.Join(name, "etc"), AutoEtc: true, }, ExtraPerms: []*fst.ExtraPermConfig{ {Path: dataHome, Execute: true}, {Ensure: true, Path: baseDir, Read: true, Write: true, Execute: true}, }, SystemBus: bundle.SystemBus, SessionBus: bundle.SessionBus, Enablements: bundle.Enablements, }, } if bundle.GPU { config.Confinement.Sandbox.Filesystem = append(config.Confinement.Sandbox.Filesystem, &fst.FilesystemConfig{Src: "/dev/dri", Device: true}) } fortifyApp(config, func() {}) fmsg.Exit(0) } func formatHostname(name string) string { if h, err := os.Hostname(); err != nil { fmsg.Printf("cannot get hostname: %v", err) return "fortify-" + name } else { return h + "-" + name } }