Compare commits
No commits in common. "ea853e21d9adc86ad3ce0c9f0c752d987d721abd" and "d8e9d71f87db912d73345fec2f9fcb61b25231cf" have entirely different histories.
ea853e21d9
...
d8e9d71f87
@ -70,7 +70,7 @@
|
|||||||
echo 'output Virtual-1 res 1680x1050') > ~/.config/sway/config
|
echo 'output Virtual-1 res 1680x1050') > ~/.config/sway/config
|
||||||
|
|
||||||
sway --validate
|
sway --validate
|
||||||
systemd-cat --identifier=session sway && touch /tmp/sway-exit-ok
|
systemd-cat --identifier=sway sway && touch /tmp/sway-exit-ok
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
@ -2,30 +2,17 @@ package sandbox
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/fs"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
assert = log.New(os.Stderr, "sandbox: ", 0)
|
assert = log.New(os.Stderr, "sandbox: ", 0)
|
||||||
printfFunc = assert.Printf
|
|
||||||
fatalfFunc = assert.Fatalf
|
fatalfFunc = assert.Fatalf
|
||||||
)
|
)
|
||||||
|
|
||||||
func printf(format string, v ...any) { printfFunc(format, v...) }
|
|
||||||
func fatalf(format string, v ...any) { fatalfFunc(format, v...) }
|
func fatalf(format string, v ...any) { fatalfFunc(format, v...) }
|
||||||
|
|
||||||
func mustDecode(wantFile string, v any) {
|
|
||||||
if f, err := os.Open(wantFile); err != nil {
|
|
||||||
fatalf("cannot open %q: %v", wantFile, err)
|
|
||||||
} else if err = json.NewDecoder(f).Decode(v); err != nil {
|
|
||||||
fatalf("cannot decode %q: %v", wantFile, err)
|
|
||||||
} else if err = f.Close(); err != nil {
|
|
||||||
fatalf("cannot close %q: %v", wantFile, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func MustAssertMounts(name, hostMountsFile, wantFile string) {
|
func MustAssertMounts(name, hostMountsFile, wantFile string) {
|
||||||
hostMounts := make([]*Mntent, 0, 128)
|
hostMounts := make([]*Mntent, 0, 128)
|
||||||
if err := IterMounts(hostMountsFile, func(e *Mntent) {
|
if err := IterMounts(hostMountsFile, func(e *Mntent) {
|
||||||
@ -35,7 +22,13 @@ func MustAssertMounts(name, hostMountsFile, wantFile string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var want []Mntent
|
var want []Mntent
|
||||||
mustDecode(wantFile, &want)
|
if f, err := os.Open(wantFile); err != nil {
|
||||||
|
fatalf("cannot open %q: %v", wantFile, err)
|
||||||
|
} else if err = json.NewDecoder(f).Decode(&want); err != nil {
|
||||||
|
fatalf("cannot decode %q: %v", wantFile, err)
|
||||||
|
} else if err = f.Close(); err != nil {
|
||||||
|
fatalf("cannot close %q: %v", wantFile, err)
|
||||||
|
}
|
||||||
|
|
||||||
for i := range want {
|
for i := range want {
|
||||||
if want[i].Opts == "host_passthrough" {
|
if want[i].Opts == "host_passthrough" {
|
||||||
@ -60,21 +53,9 @@ func MustAssertMounts(name, hostMountsFile, wantFile string) {
|
|||||||
e, &want[i])
|
e, &want[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%s", e)
|
assert.Printf("%s", e)
|
||||||
i++
|
i++
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
fatalf("cannot iterate mounts: %v", err)
|
fatalf("cannot iterate mounts: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MustAssertFS(e fs.FS, wantFile string) {
|
|
||||||
var want *FS
|
|
||||||
mustDecode(wantFile, &want)
|
|
||||||
if want == nil {
|
|
||||||
fatalf("invalid payload")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := want.Compare(".", e); err != nil {
|
|
||||||
fatalf("%v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,32 +1,3 @@
|
|||||||
package sandbox
|
package sandbox
|
||||||
|
|
||||||
import (
|
func ReplaceFatal(f func(format string, v ...any)) { fatalfFunc = f }
|
||||||
"encoding/json"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type F func(format string, v ...any)
|
|
||||||
|
|
||||||
func SwapPrint(f F) (old F) { old = printfFunc; printfFunc = f; return }
|
|
||||||
func SwapFatal(f F) (old F) { old = fatalfFunc; fatalfFunc = f; return }
|
|
||||||
|
|
||||||
func MustWantFile(t *testing.T, v any) (wantFile string) {
|
|
||||||
wantFile = path.Join(t.TempDir(), "want.json")
|
|
||||||
if f, err := os.OpenFile(wantFile, os.O_CREATE|os.O_WRONLY, 0400); err != nil {
|
|
||||||
t.Fatalf("cannot create %q: %v", wantFile, err)
|
|
||||||
} else if err = json.NewEncoder(f).Encode(v); err != nil {
|
|
||||||
t.Fatalf("cannot encode to %q: %v", wantFile, err)
|
|
||||||
} else if err = f.Close(); err != nil {
|
|
||||||
t.Fatalf("cannot close %q: %v", wantFile, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Cleanup(func() {
|
|
||||||
if err := os.Remove(wantFile); err != nil {
|
|
||||||
t.Fatalf("cannot remove %q: %v", wantFile, err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
writeShellScript "check-sandbox" ''
|
writeShellScript "check-sandbox" ''
|
||||||
set -e
|
set -e
|
||||||
${callPackage ./mount.nix { inherit version; }}/bin/test
|
${callPackage ./mount.nix { inherit version; }}/bin/test
|
||||||
${callPackage ./fs.nix { inherit version; }}/bin/test
|
|
||||||
|
|
||||||
touch /tmp/sandbox-ok
|
touch /tmp/sandbox-ok
|
||||||
''
|
''
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
package sandbox
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrFSBadLength = errors.New("bad dir length")
|
|
||||||
ErrFSBadData = errors.New("data differs")
|
|
||||||
ErrFSBadMode = errors.New("mode differs")
|
|
||||||
ErrFSInvalidEnt = errors.New("invalid entry condition")
|
|
||||||
)
|
|
||||||
|
|
||||||
type FS struct {
|
|
||||||
Mode fs.FileMode `json:"mode"`
|
|
||||||
Dir map[string]*FS `json:"dir"`
|
|
||||||
Data *string `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func printDir(prefix string, dir []fs.DirEntry) {
|
|
||||||
names := make([]string, len(dir))
|
|
||||||
for i, ent := range dir {
|
|
||||||
name := ent.Name()
|
|
||||||
if ent.IsDir() {
|
|
||||||
name += "/"
|
|
||||||
}
|
|
||||||
names[i] = fmt.Sprintf("%q", name)
|
|
||||||
}
|
|
||||||
printf("[FAIL] d %q: %s", prefix, strings.Join(names, " "))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *FS) Compare(prefix string, e fs.FS) error {
|
|
||||||
if s.Data != nil {
|
|
||||||
if s.Dir != nil {
|
|
||||||
panic("invalid state")
|
|
||||||
}
|
|
||||||
panic("invalid compare call")
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.Dir == nil {
|
|
||||||
printf("[ OK ] s %s", prefix)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var dir []fs.DirEntry
|
|
||||||
if d, err := fs.ReadDir(e, prefix); err != nil {
|
|
||||||
return err
|
|
||||||
} else if len(d) != len(s.Dir) {
|
|
||||||
printDir(prefix, d)
|
|
||||||
return ErrFSBadLength
|
|
||||||
} else {
|
|
||||||
dir = d
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, got := range dir {
|
|
||||||
name := got.Name()
|
|
||||||
|
|
||||||
if want, ok := s.Dir[name]; !ok {
|
|
||||||
printDir(prefix, dir)
|
|
||||||
return fs.ErrNotExist
|
|
||||||
} else if want.Dir != nil && !got.IsDir() {
|
|
||||||
printDir(prefix, dir)
|
|
||||||
return ErrFSInvalidEnt
|
|
||||||
} else {
|
|
||||||
name = path.Join(prefix, name)
|
|
||||||
|
|
||||||
if fi, err := got.Info(); err != nil {
|
|
||||||
return err
|
|
||||||
} else if fi.Mode() != want.Mode {
|
|
||||||
printf("[FAIL] m %q: %x, want %x",
|
|
||||||
name, uint32(fi.Mode()), uint32(want.Mode))
|
|
||||||
return ErrFSBadMode
|
|
||||||
}
|
|
||||||
|
|
||||||
if want.Data != nil {
|
|
||||||
if want.Dir != nil {
|
|
||||||
panic("invalid state")
|
|
||||||
}
|
|
||||||
if v, err := fs.ReadFile(e, name); err != nil {
|
|
||||||
return err
|
|
||||||
} else if string(v) != *want.Data {
|
|
||||||
printf("[FAIL] f %s", name)
|
|
||||||
return ErrFSBadData
|
|
||||||
}
|
|
||||||
printf("[ OK ] f %s", name)
|
|
||||||
} else if err := want.Compare(name, e); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("[ OK ] d %s", prefix)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,214 +0,0 @@
|
|||||||
{
|
|
||||||
lib,
|
|
||||||
writeText,
|
|
||||||
buildGoModule,
|
|
||||||
|
|
||||||
version,
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
wantFS =
|
|
||||||
let
|
|
||||||
fs = mode: dir: data: {
|
|
||||||
mode = lib.fromHexString mode;
|
|
||||||
inherit
|
|
||||||
dir
|
|
||||||
data
|
|
||||||
;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
fs "dead" {
|
|
||||||
".fortify" = fs "800001ed" {
|
|
||||||
etc = fs "800001ed" null null;
|
|
||||||
sbin = fs "800001c0" {
|
|
||||||
fortify = fs "16d" null null;
|
|
||||||
init = fs "80001ff" null null;
|
|
||||||
} null;
|
|
||||||
host-mounts = fs "124" null null;
|
|
||||||
} null;
|
|
||||||
bin = fs "800001ed" { sh = fs "80001ff" null null; } null;
|
|
||||||
dev = fs "800001ed" {
|
|
||||||
core = fs "80001ff" null null;
|
|
||||||
dri = fs "800001ed" {
|
|
||||||
by-path = fs "800001ed" {
|
|
||||||
"pci-0000:00:09.0-card" = fs "80001ff" null null;
|
|
||||||
"pci-0000:00:09.0-render" = fs "80001ff" null null;
|
|
||||||
} null;
|
|
||||||
card0 = fs "42001b0" null null;
|
|
||||||
renderD128 = fs "42001b6" null null;
|
|
||||||
} null;
|
|
||||||
fd = fs "80001ff" null null;
|
|
||||||
full = fs "42001b6" null null;
|
|
||||||
mqueue = fs "801001ff" { } null;
|
|
||||||
null = fs "42001b6" null "";
|
|
||||||
ptmx = fs "80001ff" null null;
|
|
||||||
pts = fs "800001ed" { ptmx = fs "42001b6" null null; } null;
|
|
||||||
random = fs "42001b6" null null;
|
|
||||||
shm = fs "800001ed" { } null;
|
|
||||||
stderr = fs "80001ff" null null;
|
|
||||||
stdin = fs "80001ff" null null;
|
|
||||||
stdout = fs "80001ff" null null;
|
|
||||||
tty = fs "42001b6" null null;
|
|
||||||
urandom = fs "42001b6" null null;
|
|
||||||
zero = fs "42001b6" null null;
|
|
||||||
} null;
|
|
||||||
etc = fs "800001c0" {
|
|
||||||
".clean" = fs "80001ff" null null;
|
|
||||||
".updated" = fs "80001ff" null null;
|
|
||||||
"NIXOS" = fs "80001ff" null null;
|
|
||||||
"X11" = fs "80001ff" null null;
|
|
||||||
"alsa" = fs "80001ff" null null;
|
|
||||||
"bashrc" = fs "80001ff" null null;
|
|
||||||
"binfmt.d" = fs "80001ff" null null;
|
|
||||||
"dbus-1" = fs "80001ff" null null;
|
|
||||||
"default" = fs "80001ff" null null;
|
|
||||||
"dhcpcd.exit-hook" = fs "80001ff" null null;
|
|
||||||
"fonts" = fs "80001ff" null null;
|
|
||||||
"fstab" = fs "80001ff" null null;
|
|
||||||
"fsurc" = fs "80001ff" null null;
|
|
||||||
"fuse.conf" = fs "80001ff" null null;
|
|
||||||
"group" = fs "180" null "fortify:x:65534:\n";
|
|
||||||
"host.conf" = fs "80001ff" null null;
|
|
||||||
"hostname" = fs "80001ff" null null;
|
|
||||||
"hosts" = fs "80001ff" null null;
|
|
||||||
"inputrc" = fs "80001ff" null null;
|
|
||||||
"issue" = fs "80001ff" null null;
|
|
||||||
"kbd" = fs "80001ff" null null;
|
|
||||||
"locale.conf" = fs "80001ff" null null;
|
|
||||||
"login.defs" = fs "80001ff" null null;
|
|
||||||
"lsb-release" = fs "80001ff" null null;
|
|
||||||
"lvm" = fs "80001ff" null null;
|
|
||||||
"machine-id" = fs "80001ff" null null;
|
|
||||||
"man_db.conf" = fs "80001ff" null null;
|
|
||||||
"modprobe.d" = fs "80001ff" null null;
|
|
||||||
"modules-load.d" = fs "80001ff" null null;
|
|
||||||
"mtab" = fs "80001ff" null null;
|
|
||||||
"nanorc" = fs "80001ff" null null;
|
|
||||||
"netgroup" = fs "80001ff" null null;
|
|
||||||
"nix" = fs "80001ff" null null;
|
|
||||||
"nixos" = fs "80001ff" null null;
|
|
||||||
"nscd.conf" = fs "80001ff" null null;
|
|
||||||
"nsswitch.conf" = fs "80001ff" null null;
|
|
||||||
"os-release" = fs "80001ff" null null;
|
|
||||||
"pam" = fs "80001ff" null null;
|
|
||||||
"pam.d" = fs "80001ff" null null;
|
|
||||||
"passwd" = fs "180" null "u0_a1:x:65534:65534:Fortify:/var/lib/fortify/u0/a1:/run/current-system/sw/bin/bash\n";
|
|
||||||
"pipewire" = fs "80001ff" null null;
|
|
||||||
"pki" = fs "80001ff" null null;
|
|
||||||
"polkit-1" = fs "80001ff" null null;
|
|
||||||
"profile" = fs "80001ff" null null;
|
|
||||||
"profiles" = fs "80001ff" null null;
|
|
||||||
"protocols" = fs "80001ff" null null;
|
|
||||||
"resolv.conf" = fs "80001ff" null null;
|
|
||||||
"resolvconf.conf" = fs "80001ff" null null;
|
|
||||||
"rpc" = fs "80001ff" null null;
|
|
||||||
"services" = fs "80001ff" null null;
|
|
||||||
"set-environment" = fs "80001ff" null null;
|
|
||||||
"shadow" = fs "80001ff" null null;
|
|
||||||
"shells" = fs "80001ff" null null;
|
|
||||||
"ssh" = fs "80001ff" null null;
|
|
||||||
"ssl" = fs "80001ff" null null;
|
|
||||||
"static" = fs "80001ff" null null;
|
|
||||||
"subgid" = fs "80001ff" null null;
|
|
||||||
"subuid" = fs "80001ff" null null;
|
|
||||||
"sudoers" = fs "80001ff" null null;
|
|
||||||
"sway" = fs "80001ff" null null;
|
|
||||||
"sysctl.d" = fs "80001ff" null null;
|
|
||||||
"systemd" = fs "80001ff" null null;
|
|
||||||
"terminfo" = fs "80001ff" null null;
|
|
||||||
"tmpfiles.d" = fs "80001ff" null null;
|
|
||||||
"udev" = fs "80001ff" null null;
|
|
||||||
"vconsole.conf" = fs "80001ff" null null;
|
|
||||||
"xdg" = fs "80001ff" null null;
|
|
||||||
"zoneinfo" = fs "80001ff" null null;
|
|
||||||
} null;
|
|
||||||
nix = fs "800001c0" { store = fs "801001fd" null null; } null;
|
|
||||||
proc = fs "8000016d" null null;
|
|
||||||
run = fs "800001c0" {
|
|
||||||
current-system = fs "8000016d" null null;
|
|
||||||
opengl-driver = fs "8000016d" null null;
|
|
||||||
user = fs "800001ed" {
|
|
||||||
"65534" = fs "800001ed" {
|
|
||||||
bus = fs "10001fd" null null;
|
|
||||||
pulse = fs "800001c0" { native = fs "10001b6" null null; } null;
|
|
||||||
wayland-0 = fs "1000038" null null;
|
|
||||||
} null;
|
|
||||||
} null;
|
|
||||||
} null;
|
|
||||||
sys = fs "800001c0" {
|
|
||||||
block = fs "800001ed" {
|
|
||||||
fd0 = fs "80001ff" null null;
|
|
||||||
loop0 = fs "80001ff" null null;
|
|
||||||
loop1 = fs "80001ff" null null;
|
|
||||||
loop2 = fs "80001ff" null null;
|
|
||||||
loop3 = fs "80001ff" null null;
|
|
||||||
loop4 = fs "80001ff" null null;
|
|
||||||
loop5 = fs "80001ff" null null;
|
|
||||||
loop6 = fs "80001ff" null null;
|
|
||||||
loop7 = fs "80001ff" null null;
|
|
||||||
sr0 = fs "80001ff" null null;
|
|
||||||
vda = fs "80001ff" null null;
|
|
||||||
} null;
|
|
||||||
bus = fs "800001ed" null null;
|
|
||||||
class = fs "800001ed" null null;
|
|
||||||
dev = fs "800001ed" {
|
|
||||||
block = fs "800001ed" null null;
|
|
||||||
char = fs "800001ed" null null;
|
|
||||||
} null;
|
|
||||||
devices = fs "800001ed" null null;
|
|
||||||
} null;
|
|
||||||
tmp = fs "800001f8" { } null;
|
|
||||||
usr = fs "800001c0" { bin = fs "800001ed" { env = fs "80001ff" null null; } null; } null;
|
|
||||||
var = fs "800001c0" {
|
|
||||||
lib = fs "800001c0" {
|
|
||||||
fortify = fs "800001c0" {
|
|
||||||
u0 = fs "800001c0" {
|
|
||||||
a1 = fs "800001c0" {
|
|
||||||
".cache" = fs "800001ed" { ".keep" = fs "80001ff" null ""; } null;
|
|
||||||
".config" = fs "800001ed" { "environment.d" = fs "800001ed" { "10-home-manager.conf" = fs "80001ff" null null; } null; } null;
|
|
||||||
".local" = fs "800001ed" {
|
|
||||||
state = fs "800001ed" {
|
|
||||||
home-manager = fs "800001ed" { gcroots = fs "800001ed" { current-home = fs "80001ff" null null; } null; } null;
|
|
||||||
nix = fs "800001ed" {
|
|
||||||
profiles = fs "800001ed" {
|
|
||||||
home-manager = fs "80001ff" null null;
|
|
||||||
home-manager-1-link = fs "80001ff" null null;
|
|
||||||
profile = fs "80001ff" null null;
|
|
||||||
profile-1-link = fs "80001ff" null null;
|
|
||||||
} null;
|
|
||||||
} null;
|
|
||||||
} null;
|
|
||||||
} null;
|
|
||||||
".nix-defexpr" = fs "800001ed" {
|
|
||||||
channels = fs "80001ff" null null;
|
|
||||||
channels_root = fs "80001ff" null null;
|
|
||||||
} null;
|
|
||||||
".nix-profile" = fs "80001ff" null null;
|
|
||||||
} null;
|
|
||||||
} null;
|
|
||||||
} null;
|
|
||||||
} null;
|
|
||||||
run = fs "800001ed" { nscd = fs "800001ed" { } null; } null;
|
|
||||||
} null;
|
|
||||||
} null;
|
|
||||||
|
|
||||||
mainFile = writeText "main.go" ''
|
|
||||||
package main
|
|
||||||
|
|
||||||
import "os"
|
|
||||||
import "git.gensokyo.uk/security/fortify/test/sandbox"
|
|
||||||
|
|
||||||
func main() { sandbox.MustAssertFS(os.DirFS("/"), "${writeText "want-fs.json" (builtins.toJSON wantFS)}") }
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
buildGoModule {
|
|
||||||
pname = "check-fs";
|
|
||||||
inherit version;
|
|
||||||
|
|
||||||
src = ../.;
|
|
||||||
vendorHash = null;
|
|
||||||
|
|
||||||
preBuild = ''
|
|
||||||
go mod init git.gensokyo.uk/security/fortify/test >& /dev/null
|
|
||||||
cp ${mainFile} main.go
|
|
||||||
'';
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package sandbox_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"testing/fstest"
|
|
||||||
|
|
||||||
"git.gensokyo.uk/security/fortify/test/sandbox"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
fsPasswdSample = "u0_a20:x:65534:65534:Fortify:/var/lib/persist/module/fortify/u0/a20:/run/current-system/sw/bin/zsh"
|
|
||||||
fsGroupSample = "fortify:x:65534:"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCompare(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
|
|
||||||
sample fstest.MapFS
|
|
||||||
want *sandbox.FS
|
|
||||||
wantOut string
|
|
||||||
wantErr error
|
|
||||||
}{
|
|
||||||
{"skip", fstest.MapFS{}, &sandbox.FS{}, "[ OK ] s .\x00", nil},
|
|
||||||
{"simple pass", fstest.MapFS{".fortify": {Mode: 0x800001ed}},
|
|
||||||
&sandbox.FS{Dir: map[string]*sandbox.FS{".fortify": {Mode: 0x800001ed}}},
|
|
||||||
"[ OK ] s .fortify\x00[ OK ] d .\x00", nil},
|
|
||||||
{"bad length", fstest.MapFS{".fortify": {Mode: 0x800001ed}},
|
|
||||||
&sandbox.FS{Dir: make(map[string]*sandbox.FS)},
|
|
||||||
"[FAIL] d \".\": \".fortify/\"\x00", sandbox.ErrFSBadLength},
|
|
||||||
{"top level bad mode", fstest.MapFS{".fortify": {Mode: 0x800001ed}},
|
|
||||||
&sandbox.FS{Dir: map[string]*sandbox.FS{".fortify": {Mode: 0xdeadbeef}}},
|
|
||||||
"[FAIL] m \".fortify\": 800001ed, want deadbeef\x00", sandbox.ErrFSBadMode},
|
|
||||||
{"invalid entry condition", fstest.MapFS{"test": {Data: []byte{'0'}, Mode: 0644}},
|
|
||||||
&sandbox.FS{Dir: map[string]*sandbox.FS{"test": {Dir: make(map[string]*sandbox.FS)}}},
|
|
||||||
"[FAIL] d \".\": \"test\"\x00", sandbox.ErrFSInvalidEnt},
|
|
||||||
{"nonexistent", fstest.MapFS{"test": {Data: []byte{'0'}, Mode: 0644}},
|
|
||||||
&sandbox.FS{Dir: map[string]*sandbox.FS{".test": {}}},
|
|
||||||
"[FAIL] d \".\": \"test\"\x00", fs.ErrNotExist},
|
|
||||||
{"file", fstest.MapFS{"etc": {Mode: 0x800001c0},
|
|
||||||
"etc/passwd": {Data: []byte(fsPasswdSample), Mode: 0644},
|
|
||||||
"etc/group": {Data: []byte(fsGroupSample), Mode: 0644},
|
|
||||||
}, &sandbox.FS{Dir: map[string]*sandbox.FS{"etc": {Mode: 0x800001c0, Dir: map[string]*sandbox.FS{
|
|
||||||
"passwd": {Mode: 0x1a4, Data: &fsPasswdSample},
|
|
||||||
"group": {Mode: 0x1a4, Data: &fsGroupSample},
|
|
||||||
}}}}, "[ OK ] f etc/group\x00[ OK ] f etc/passwd\x00[ OK ] d etc\x00[ OK ] d .\x00", nil},
|
|
||||||
{"file differ", fstest.MapFS{"etc": {Mode: 0x800001c0},
|
|
||||||
"etc/passwd": {Data: []byte(fsPasswdSample), Mode: 0644},
|
|
||||||
"etc/group": {Data: []byte(fsGroupSample), Mode: 0644},
|
|
||||||
}, &sandbox.FS{Dir: map[string]*sandbox.FS{"etc": {Mode: 0x800001c0, Dir: map[string]*sandbox.FS{
|
|
||||||
"passwd": {Mode: 0x1a4, Data: &fsGroupSample},
|
|
||||||
"group": {Mode: 0x1a4, Data: &fsGroupSample},
|
|
||||||
}}}}, "[ OK ] f etc/group\x00[FAIL] f etc/passwd\x00", sandbox.ErrFSBadData},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
gotOut := new(strings.Builder)
|
|
||||||
oldPrint := sandbox.SwapPrint(func(format string, v ...any) { _, _ = fmt.Fprintf(gotOut, format+"\x00", v...) })
|
|
||||||
t.Cleanup(func() { sandbox.SwapPrint(oldPrint) })
|
|
||||||
|
|
||||||
err := tc.want.Compare(".", tc.sample)
|
|
||||||
if !errors.Is(err, tc.wantErr) {
|
|
||||||
t.Errorf("Compare: error = %v; wantErr %v",
|
|
||||||
err, tc.wantErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if gotOut.String() != tc.wantOut {
|
|
||||||
t.Errorf("Compare: output %q; want %q",
|
|
||||||
gotOut, tc.wantOut)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run("assert", func(t *testing.T) {
|
|
||||||
oldFatal := sandbox.SwapFatal(t.Fatalf)
|
|
||||||
t.Cleanup(func() { sandbox.SwapFatal(oldFatal) })
|
|
||||||
sandbox.MustAssertFS(make(fstest.MapFS), sandbox.MustWantFile(t, &sandbox.FS{Mode: 0xDEADBEEF}))
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
package sandbox_test
|
package sandbox_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
@ -110,9 +111,22 @@ overlay /.fortify/sbin/fortify overlay ro,nosuid,nodev,relatime,lowerdir=/mnt-ro
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run(tc.name+" assert", func(t *testing.T) {
|
t.Run(tc.name+" assert", func(t *testing.T) {
|
||||||
oldFatal := sandbox.SwapFatal(t.Fatalf)
|
sandbox.ReplaceFatal(t.Fatalf)
|
||||||
t.Cleanup(func() { sandbox.SwapFatal(oldFatal) })
|
|
||||||
sandbox.MustAssertMounts(name, name, sandbox.MustWantFile(t, tc.want))
|
wantFile := path.Join(t.TempDir(), "want.json")
|
||||||
|
if f, err := os.OpenFile(wantFile, os.O_CREATE|os.O_WRONLY, 0400); err != nil {
|
||||||
|
t.Fatalf("cannot create %q: %v", wantFile, err)
|
||||||
|
} else if err = json.NewEncoder(f).Encode(tc.want); err != nil {
|
||||||
|
t.Fatalf("cannot encode to %q: %v", wantFile, err)
|
||||||
|
} else if err = f.Close(); err != nil {
|
||||||
|
t.Fatalf("cannot close %q: %v", wantFile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sandbox.MustAssertMounts(name, name, wantFile)
|
||||||
|
|
||||||
|
if err := os.Remove(wantFile); err != nil {
|
||||||
|
t.Fatalf("cannot remove %q: %v", wantFile, err)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := os.Remove(name); err != nil {
|
if err := os.Remove(name); err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user