Compare commits
No commits in common. "e2489059c103800ab62250351db895415e0cdfed" and "c4d6651cae0fb1869ee65da0b66baae3828d73a2" have entirely different histories.
e2489059c1
...
c4d6651cae
@ -141,12 +141,6 @@ func (s *SandboxConfig) Bwrap(os linux.System) (*bwrap.Config, error) {
|
|||||||
Hostname: s.Hostname,
|
Hostname: s.Hostname,
|
||||||
Clearenv: true,
|
Clearenv: true,
|
||||||
SetEnv: s.Env,
|
SetEnv: s.Env,
|
||||||
|
|
||||||
/* this is only 4 KiB of memory on a 64-bit system,
|
|
||||||
permissive defaults on NixOS results in around 100 entries
|
|
||||||
so this capacity should eliminate copies for most setups */
|
|
||||||
Filesystem: make([]bwrap.FSBuilder, 0, 256),
|
|
||||||
|
|
||||||
NewSession: !s.NoNewSession,
|
NewSession: !s.NoNewSession,
|
||||||
DieWithParent: true,
|
DieWithParent: true,
|
||||||
AsInit: true,
|
AsInit: true,
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
package fst
|
|
||||||
|
|
||||||
type Info struct {
|
|
||||||
User int `json:"user"`
|
|
||||||
}
|
|
@ -4,20 +4,10 @@ const (
|
|||||||
Tmpfs = iota
|
Tmpfs = iota
|
||||||
Dir
|
Dir
|
||||||
Symlink
|
Symlink
|
||||||
|
|
||||||
OverlaySrc
|
|
||||||
Overlay
|
|
||||||
TmpOverlay
|
|
||||||
ROOverlay
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var awkwardArgs = [...]string{
|
var awkwardArgs = [...]string{
|
||||||
Tmpfs: "--tmpfs",
|
Tmpfs: "--tmpfs",
|
||||||
Dir: "--dir",
|
Dir: "--dir",
|
||||||
Symlink: "--symlink",
|
Symlink: "--symlink",
|
||||||
|
|
||||||
OverlaySrc: "--overlay-src",
|
|
||||||
Overlay: "--overlay",
|
|
||||||
TmpOverlay: "--tmp-overlay",
|
|
||||||
ROOverlay: "--ro-overlay",
|
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ type Config struct {
|
|||||||
LockFile []string `json:"lock_file,omitempty"`
|
LockFile []string `json:"lock_file,omitempty"`
|
||||||
|
|
||||||
// ordered filesystem args
|
// ordered filesystem args
|
||||||
Filesystem []FSBuilder `json:"filesystem,omitempty"`
|
Filesystem []FSBuilder
|
||||||
|
|
||||||
// change permissions (must already exist)
|
// change permissions (must already exist)
|
||||||
// (--chmod OCTAL PATH)
|
// (--chmod OCTAL PATH)
|
||||||
@ -78,8 +78,6 @@ type Config struct {
|
|||||||
--userns FD Use this user namespace (cannot combine with --unshare-user)
|
--userns FD Use this user namespace (cannot combine with --unshare-user)
|
||||||
--userns2 FD After setup switch to this user namespace, only useful with --userns
|
--userns2 FD After setup switch to this user namespace, only useful with --userns
|
||||||
--pidns FD Use this pid namespace (as parent namespace if using --unshare-pid)
|
--pidns FD Use this pid namespace (as parent namespace if using --unshare-pid)
|
||||||
--bind-fd FD DEST Bind open directory or path fd on DEST
|
|
||||||
--ro-bind-fd FD DEST Bind open directory or path fd read-only on DEST
|
|
||||||
--exec-label LABEL Exec label for the sandbox
|
--exec-label LABEL Exec label for the sandbox
|
||||||
--file-label LABEL File label for temporary sandbox content
|
--file-label LABEL File label for temporary sandbox content
|
||||||
--file FD DEST Copy from FD to destination DEST
|
--file FD DEST Copy from FD to destination DEST
|
||||||
@ -180,74 +178,6 @@ func (t *TmpfsConfig) Append(args *[]string) {
|
|||||||
*args = append(*args, awkwardArgs[Tmpfs], t.Dir)
|
*args = append(*args, awkwardArgs[Tmpfs], t.Dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
type OverlayConfig struct {
|
|
||||||
/*
|
|
||||||
read files from SRC in the following overlay
|
|
||||||
(--overlay-src SRC)
|
|
||||||
*/
|
|
||||||
Src []string `json:"src,omitempty"`
|
|
||||||
|
|
||||||
/*
|
|
||||||
mount overlayfs on DEST, with RWSRC as the host path for writes and
|
|
||||||
WORKDIR an empty directory on the same filesystem as RWSRC
|
|
||||||
(--overlay RWSRC WORKDIR DEST)
|
|
||||||
|
|
||||||
if nil, mount overlayfs on DEST, with writes going to an invisible tmpfs
|
|
||||||
(--tmp-overlay DEST)
|
|
||||||
|
|
||||||
if either strings are empty, mount overlayfs read-only on DEST
|
|
||||||
(--ro-overlay DEST)
|
|
||||||
*/
|
|
||||||
Persist *[2]string `json:"persist,omitempty"`
|
|
||||||
|
|
||||||
/*
|
|
||||||
--overlay RWSRC WORKDIR DEST
|
|
||||||
|
|
||||||
--tmp-overlay DEST
|
|
||||||
|
|
||||||
--ro-overlay DEST
|
|
||||||
*/
|
|
||||||
Dest string `json:"dest"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *OverlayConfig) Path() string {
|
|
||||||
return o.Dest
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *OverlayConfig) Len() int {
|
|
||||||
// (--tmp-overlay DEST) or (--ro-overlay DEST)
|
|
||||||
p := 2
|
|
||||||
// (--overlay RWSRC WORKDIR DEST)
|
|
||||||
if o.Persist != nil && o.Persist[0] != "" && o.Persist[1] != "" {
|
|
||||||
p = 4
|
|
||||||
}
|
|
||||||
|
|
||||||
return p + len(o.Src)*2
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *OverlayConfig) Append(args *[]string) {
|
|
||||||
// --overlay-src SRC
|
|
||||||
for _, src := range o.Src {
|
|
||||||
*args = append(*args, awkwardArgs[OverlaySrc], src)
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.Persist != nil {
|
|
||||||
if o.Persist[0] != "" && o.Persist[1] != "" {
|
|
||||||
// --overlay RWSRC WORKDIR
|
|
||||||
*args = append(*args, awkwardArgs[Overlay], o.Persist[0], o.Persist[1])
|
|
||||||
} else {
|
|
||||||
// --ro-overlay
|
|
||||||
*args = append(*args, awkwardArgs[ROOverlay])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// --tmp-overlay
|
|
||||||
*args = append(*args, awkwardArgs[TmpOverlay])
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEST
|
|
||||||
*args = append(*args, o.Dest)
|
|
||||||
}
|
|
||||||
|
|
||||||
type SymlinkConfig [2]string
|
type SymlinkConfig [2]string
|
||||||
|
|
||||||
func (s SymlinkConfig) Path() string {
|
func (s SymlinkConfig) Path() string {
|
||||||
|
@ -96,31 +96,6 @@ func (c *Config) Tmpfs(dest string, size int, perm ...os.FileMode) *Config {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overlay mount overlayfs on DEST, with writes going to an invisible tmpfs
|
|
||||||
// (--tmp-overlay DEST)
|
|
||||||
func (c *Config) Overlay(dest string, src ...string) *Config {
|
|
||||||
c.Filesystem = append(c.Filesystem, &OverlayConfig{Src: src, Dest: dest})
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join mount overlayfs read-only on DEST
|
|
||||||
// (--ro-overlay DEST)
|
|
||||||
func (c *Config) Join(dest string, src ...string) *Config {
|
|
||||||
c.Filesystem = append(c.Filesystem, &OverlayConfig{Src: src, Dest: dest, Persist: new([2]string)})
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Persist mount overlayfs on DEST, with RWSRC as the host path for writes and
|
|
||||||
// WORKDIR an empty directory on the same filesystem as RWSRC
|
|
||||||
// (--overlay RWSRC WORKDIR DEST)
|
|
||||||
func (c *Config) Persist(dest, rwsrc, workdir string, src ...string) *Config {
|
|
||||||
if rwsrc == "" || workdir == "" {
|
|
||||||
panic("persist called without required paths")
|
|
||||||
}
|
|
||||||
c.Filesystem = append(c.Filesystem, &OverlayConfig{Src: src, Dest: dest, Persist: &[2]string{rwsrc, workdir}})
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mqueue mount new mqueue in sandbox
|
// Mqueue mount new mqueue in sandbox
|
||||||
// (--mqueue DEST)
|
// (--mqueue DEST)
|
||||||
func (c *Config) Mqueue(dest string) *Config {
|
func (c *Config) Mqueue(dest string) *Config {
|
||||||
|
@ -1,40 +1,19 @@
|
|||||||
package bwrap_test
|
package bwrap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/helper/bwrap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConfig_Args(t *testing.T) {
|
func TestConfig_Args(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
conf *bwrap.Config
|
conf *Config
|
||||||
want []string
|
want []string
|
||||||
}{
|
}{
|
||||||
{
|
|
||||||
name: "overlayfs",
|
|
||||||
conf: (new(bwrap.Config)).
|
|
||||||
Overlay("/etc", "/etc").
|
|
||||||
Join("/.fortify/bin", "/bin", "/usr/bin", "/usr/local/bin").
|
|
||||||
Persist("/nix", "/data/data/org.chromium.Chromium/overlay/rwsrc", "/data/data/org.chromium.Chromium/workdir", "/data/app/org.chromium.Chromium/nix"),
|
|
||||||
want: []string{
|
|
||||||
"--unshare-all", "--unshare-user",
|
|
||||||
"--disable-userns", "--assert-userns-disabled",
|
|
||||||
// Overlay("/etc", "/etc")
|
|
||||||
"--overlay-src", "/etc", "--tmp-overlay", "/etc",
|
|
||||||
// Join("/.fortify/bin", "/bin", "/usr/bin", "/usr/local/bin")
|
|
||||||
"--overlay-src", "/bin", "--overlay-src", "/usr/bin",
|
|
||||||
"--overlay-src", "/usr/local/bin", "--ro-overlay", "/.fortify/bin",
|
|
||||||
// Persist("/nix", "/data/data/org.chromium.Chromium/overlay/rwsrc", "/data/data/org.chromium.Chromium/workdir", "/data/app/org.chromium.Chromium/nix")
|
|
||||||
"--overlay-src", "/data/app/org.chromium.Chromium/nix",
|
|
||||||
"--overlay", "/data/data/org.chromium.Chromium/overlay/rwsrc", "/data/data/org.chromium.Chromium/workdir", "/nix",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "xdg-dbus-proxy constraint sample",
|
name: "xdg-dbus-proxy constraint sample",
|
||||||
conf: (&bwrap.Config{
|
conf: (&Config{
|
||||||
Unshare: nil,
|
Unshare: nil,
|
||||||
UserNS: false,
|
UserNS: false,
|
||||||
Clearenv: true,
|
Clearenv: true,
|
||||||
@ -92,7 +71,7 @@ func TestConfig_Args(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "fortify permissive default nixos",
|
name: "fortify permissive default nixos",
|
||||||
conf: (&bwrap.Config{
|
conf: (&Config{
|
||||||
Unshare: nil,
|
Unshare: nil,
|
||||||
Net: true,
|
Net: true,
|
||||||
UserNS: true,
|
UserNS: true,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package linux
|
package linux
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
@ -9,7 +8,6 @@ import (
|
|||||||
"os/user"
|
"os/user"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/internal"
|
"git.gensokyo.uk/security/fortify/internal"
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
@ -81,15 +79,9 @@ func (s *Std) Uid(aid int) (int, error) {
|
|||||||
cmd.Stderr = os.Stderr // pass through fatal messages
|
cmd.Stderr = os.Stderr // pass through fatal messages
|
||||||
cmd.Env = []string{"FORTIFY_APP_ID=" + strconv.Itoa(aid)}
|
cmd.Env = []string{"FORTIFY_APP_ID=" + strconv.Itoa(aid)}
|
||||||
cmd.Dir = "/"
|
cmd.Dir = "/"
|
||||||
var (
|
var p []byte
|
||||||
p []byte
|
|
||||||
exitError *exec.ExitError
|
|
||||||
)
|
|
||||||
|
|
||||||
if p, u.err = cmd.Output(); u.err == nil {
|
if p, u.err = cmd.Output(); u.err == nil {
|
||||||
u.uid, u.err = strconv.Atoi(string(p))
|
u.uid, u.err = strconv.Atoi(string(p))
|
||||||
} else if errors.As(u.err, &exitError) && exitError != nil && exitError.ExitCode() == 1 {
|
|
||||||
u.err = syscall.EACCES
|
|
||||||
}
|
}
|
||||||
return u.uid, u.err
|
return u.uid, u.err
|
||||||
}
|
}
|
||||||
|
34
main.go
34
main.go
@ -4,7 +4,6 @@ import (
|
|||||||
_ "embed"
|
_ "embed"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"os/user"
|
"os/user"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -17,6 +16,7 @@ import (
|
|||||||
"git.gensokyo.uk/security/fortify/internal/app"
|
"git.gensokyo.uk/security/fortify/internal/app"
|
||||||
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
"git.gensokyo.uk/security/fortify/internal/fmsg"
|
||||||
"git.gensokyo.uk/security/fortify/internal/linux"
|
"git.gensokyo.uk/security/fortify/internal/linux"
|
||||||
|
"git.gensokyo.uk/security/fortify/internal/state"
|
||||||
"git.gensokyo.uk/security/fortify/internal/system"
|
"git.gensokyo.uk/security/fortify/internal/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ func init() {
|
|||||||
flag.BoolVar(&flagJSON, "json", false, "Format output in JSON when applicable")
|
flag.BoolVar(&flagJSON, "json", false, "Format output in JSON when applicable")
|
||||||
}
|
}
|
||||||
|
|
||||||
var sys linux.System = new(linux.Std)
|
var os = new(linux.Std)
|
||||||
|
|
||||||
type gl []string
|
type gl []string
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ func main() {
|
|||||||
fmt.Println("Usage:\tfortify [-v] [--json] COMMAND [OPTIONS]")
|
fmt.Println("Usage:\tfortify [-v] [--json] COMMAND [OPTIONS]")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println("Commands:")
|
fmt.Println("Commands:")
|
||||||
w := tabwriter.NewWriter(os.Stdout, 0, 1, 4, ' ', 0)
|
w := tabwriter.NewWriter(os.Stdout(), 0, 1, 4, ' ', 0)
|
||||||
commands := [][2]string{
|
commands := [][2]string{
|
||||||
{"app", "Launch app defined by the specified config file"},
|
{"app", "Launch app defined by the specified config file"},
|
||||||
{"run", "Configure and start a permissive default sandbox"},
|
{"run", "Configure and start a permissive default sandbox"},
|
||||||
@ -128,20 +128,24 @@ func main() {
|
|||||||
// Ignore errors; set is set for ExitOnError.
|
// Ignore errors; set is set for ExitOnError.
|
||||||
_ = set.Parse(args[1:])
|
_ = set.Parse(args[1:])
|
||||||
|
|
||||||
switch len(set.Args()) {
|
var (
|
||||||
case 0: // system
|
config *fst.Config
|
||||||
printShowSystem(short)
|
instance *state.State
|
||||||
case 1: // instance
|
name string
|
||||||
name := set.Args()[0]
|
)
|
||||||
config, instance := tryShort(name)
|
|
||||||
|
if len(set.Args()) != 1 {
|
||||||
|
fmsg.Fatal("show requires 1 argument")
|
||||||
|
} else {
|
||||||
|
name = set.Args()[0]
|
||||||
|
config, instance = tryShort(name)
|
||||||
|
}
|
||||||
|
|
||||||
if config == nil {
|
if config == nil {
|
||||||
config = tryPath(name)
|
config = tryPath(name)
|
||||||
}
|
}
|
||||||
printShowInstance(instance, config, short)
|
|
||||||
default:
|
|
||||||
fmsg.Fatal("show requires 1 argument")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
printShow(instance, config, short)
|
||||||
fmsg.Exit(0)
|
fmsg.Exit(0)
|
||||||
case "app": // launch app from configuration file
|
case "app": // launch app from configuration file
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
@ -207,7 +211,7 @@ func main() {
|
|||||||
passwdOnce sync.Once
|
passwdOnce sync.Once
|
||||||
passwdFunc = func() {
|
passwdFunc = func() {
|
||||||
var us string
|
var us string
|
||||||
if uid, err := sys.Uid(aid); err != nil {
|
if uid, err := os.Uid(aid); err != nil {
|
||||||
fmsg.Fatalf("cannot obtain uid from fsu: %v", err)
|
fmsg.Fatalf("cannot obtain uid from fsu: %v", err)
|
||||||
} else {
|
} else {
|
||||||
us = strconv.Itoa(uid)
|
us = strconv.Itoa(uid)
|
||||||
@ -288,7 +292,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runApp(config *fst.Config) {
|
func runApp(config *fst.Config) {
|
||||||
a, err := app.New(sys)
|
a, err := app.New(os)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmsg.Fatalf("cannot create app: %s\n", err)
|
fmsg.Fatalf("cannot create app: %s\n", err)
|
||||||
} else if err = a.Seal(config); err != nil {
|
} else if err = a.Seal(config); err != nil {
|
||||||
|
8
parse.go
8
parse.go
@ -4,7 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
direct "os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -38,7 +38,7 @@ func tryPath(name string) (config *fst.Config) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r = os.Stdin
|
r = direct.Stdin
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.NewDecoder(r).Decode(&config); err != nil {
|
if err := json.NewDecoder(r).Decode(&config); err != nil {
|
||||||
@ -61,7 +61,7 @@ func tryFd(name string) io.ReadCloser {
|
|||||||
}
|
}
|
||||||
fmsg.Fatalf("cannot get fd %d: %v", fd, errno)
|
fmsg.Fatalf("cannot get fd %d: %v", fd, errno)
|
||||||
}
|
}
|
||||||
return os.NewFile(fd, strconv.Itoa(v))
|
return direct.NewFile(fd, strconv.Itoa(v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ func tryShort(name string) (config *fst.Config, instance *state.State) {
|
|||||||
if likePrefix && len(name) >= 8 {
|
if likePrefix && len(name) >= 8 {
|
||||||
fmsg.VPrintln("argument looks like prefix")
|
fmsg.VPrintln("argument looks like prefix")
|
||||||
|
|
||||||
s := state.NewMulti(sys.Paths().RunDirPath)
|
s := state.NewMulti(os.Paths().RunDirPath)
|
||||||
if entries, err := state.Join(s); err != nil {
|
if entries, err := state.Join(s); err != nil {
|
||||||
fmsg.Printf("cannot join store: %v", err)
|
fmsg.Printf("cannot join store: %v", err)
|
||||||
// drop to fetch from file
|
// drop to fetch from file
|
||||||
|
35
print.go
35
print.go
@ -16,37 +16,14 @@ import (
|
|||||||
"git.gensokyo.uk/security/fortify/internal/state"
|
"git.gensokyo.uk/security/fortify/internal/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
func printShowSystem(short bool) {
|
func printShow(instance *state.State, config *fst.Config, short bool) {
|
||||||
info := new(fst.Info)
|
|
||||||
|
|
||||||
// get fid by querying uid of aid 0
|
|
||||||
if uid, err := sys.Uid(0); err != nil {
|
|
||||||
fmsg.Fatalf("cannot obtain uid from fsu: %v", err)
|
|
||||||
} else {
|
|
||||||
info.User = (uid / 10000) - 100
|
|
||||||
}
|
|
||||||
|
|
||||||
if flagJSON {
|
|
||||||
printJSON(info)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w := tabwriter.NewWriter(direct.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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printShowInstance(instance *state.State, config *fst.Config, short bool) {
|
|
||||||
if flagJSON {
|
if flagJSON {
|
||||||
|
v := any(config)
|
||||||
if instance != nil {
|
if instance != nil {
|
||||||
printJSON(instance)
|
v = instance
|
||||||
} else {
|
|
||||||
printJSON(config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printJSON(v)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +171,7 @@ func printPs(short bool) {
|
|||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
|
|
||||||
var entries state.Entries
|
var entries state.Entries
|
||||||
s := state.NewMulti(sys.Paths().RunDirPath)
|
s := state.NewMulti(os.Paths().RunDirPath)
|
||||||
if e, err := state.Join(s); err != nil {
|
if e, err := state.Join(s); err != nil {
|
||||||
fmsg.Fatalf("cannot join store: %v", err)
|
fmsg.Fatalf("cannot join store: %v", err)
|
||||||
} else {
|
} else {
|
||||||
|
13
test.nix
13
test.nix
@ -19,20 +19,12 @@ nixosTest {
|
|||||||
nodes.machine =
|
nodes.machine =
|
||||||
{ lib, pkgs, ... }:
|
{ lib, pkgs, ... }:
|
||||||
{
|
{
|
||||||
users.users = {
|
users.users.alice = {
|
||||||
alice = {
|
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
description = "Alice Foobar";
|
description = "Alice Foobar";
|
||||||
password = "foobar";
|
password = "foobar";
|
||||||
uid = 1000;
|
uid = 1000;
|
||||||
};
|
};
|
||||||
untrusted = {
|
|
||||||
isNormalUser = true;
|
|
||||||
description = "Untrusted user";
|
|
||||||
password = "foobar";
|
|
||||||
uid = 1001;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
home-manager.users.alice.home.stateVersion = "24.11";
|
home-manager.users.alice.home.stateVersion = "24.11";
|
||||||
|
|
||||||
@ -206,9 +198,6 @@ nixosTest {
|
|||||||
machine.wait_for_file("/run/user/1000/wayland-1")
|
machine.wait_for_file("/run/user/1000/wayland-1")
|
||||||
machine.wait_for_file("/tmp/sway-ipc.sock")
|
machine.wait_for_file("/tmp/sway-ipc.sock")
|
||||||
|
|
||||||
# Deny unmapped uid:
|
|
||||||
print(machine.fail("sudo -u untrusted -i ${self.packages.${system}.fortify}/bin/fortify -v run"))
|
|
||||||
|
|
||||||
# Create fortify uid 0 state directory:
|
# Create fortify uid 0 state directory:
|
||||||
machine.succeed("install -dm 0755 -o u0_a0 -g users /var/lib/fortify/u0")
|
machine.succeed("install -dm 0755 -o u0_a0 -g users /var/lib/fortify/u0")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user