//go:build testsuite // The sharefs test program checks cli behaviour and exercises the filesystem // implemented by cmd/sharefs using fs_mark. package main import ( "errors" "log" "os" "os/exec" "strings" "syscall" "hakurei.app/internal/testsuite" ) // checkBadOpts invokes cmd/sharefs with the specified options and compares // the resulting error message. func checkBadOpts(cred *syscall.Credential, opts, want string) { var buf strings.Builder buf.Grow(len(want)) cmd := exec.Command( "sharefs", "-f", "-o", "source=/etc,"+opts, "/mnt", ) cmd.SysProcAttr = &syscall.SysProcAttr{ Pdeathsig: syscall.SIGKILL, Credential: cred, } cmd.Stderr = &buf err := cmd.Run() if err == nil { log.Fatalf("opts=%q, unexpected success", opts) } if e, ok := errors.AsType[*exec.ExitError](err); !ok { log.Fatal(err) } else if !e.Exited() { log.Fatal(e) } if got := buf.String(); got != want { log.Fatalf("opts=%q\n\t got:%q\n\twant:%q", opts, got, want) } } func main() { go testsuite.ReceiveSignals() cred := syscall.Credential{Uid: 1000, Gid: 100} if err := os.Mkdir("result", 0755); err != nil { log.Fatal(err) } done := make(chan struct{}) go func() { defer close(done) testsuite.MustRun( nil, nil, "fs_mark", "-v", "-d", "/sdcard/fs_mark", "-l", "result/fs_mark.log", ) }() log.Println("checking malformed setuid/setgid representation") checkBadOpts(&cred, "setuid=ff", "sharefs: invalid value for option setuid\n") checkBadOpts(&cred, "setgid=ff", "sharefs: invalid value for option setgid\n") log.Println("checking bounds check for setuid/setgid") checkBadOpts(&cred, "setuid=0", "sharefs: invalid value for option setuid\n") checkBadOpts(&cred, "setgid=0", "sharefs: invalid value for option setgid\n") checkBadOpts(&cred, "setuid=-1", "sharefs: invalid value for option setuid\n") checkBadOpts(&cred, "setgid=-1", "sharefs: invalid value for option setgid\n") log.Println("checking non-root setuid/setgid") checkBadOpts(&cred, "setuid=1023", "sharefs: setuid and setgid has no effect when not starting as root\n") checkBadOpts(&cred, "setgid=1023", "sharefs: setuid and setgid has no effect when not starting as root\n") checkBadOpts(&cred, "setuid=1023,setgid=1023", "sharefs: setuid and setgid has no effect when not starting as root\n") checkBadOpts(&cred, "mkdir", "sharefs: mkdir has no effect when not starting as root\n") log.Println("checking root without setuid/setgid") checkBadOpts(nil, "allow_other", "sharefs: setuid and setgid must not be 0\n") checkBadOpts(nil, "setuid=1023", "sharefs: setuid and setgid must not be 0\n") checkBadOpts(nil, "setgid=1023", "sharefs: setuid and setgid must not be 0\n") log.Println("verifying mount point") if err := os.Remove("/mnt"); err != nil { log.Fatal(err) } log.Println("checking unprivileged mount/unmount") testsuite.MustRun(&cred, nil, "mkdir", "/tmp/sdcard", "/tmp/persistent") testsuite.MustRun(&cred, nil, "sharefs", "-o", "source=/tmp/persistent", "/tmp/sdcard") testsuite.MustRun(&cred, nil, "touch", "/tmp/sdcard/check") testsuite.MustRun(&cred, nil, "umount", "/tmp/sdcard") testsuite.MustRun(&cred, nil, "rm", "/tmp/persistent/check") testsuite.MustRun(&cred, nil, "rmdir", "/tmp/sdcard", "/tmp/persistent") log.Println("waiting for fs_mark to complete") <-done const backingDir = "/var/lib/sdcard" sharefsCred := syscall.Credential{Uid: 1023, Gid: 1023} log.Println("checking permissions") testsuite.MustRun(&sharefsCred, nil, "touch", backingDir+"/fs_mark/.check") testsuite.MustRun(&sharefsCred, nil, "rm", backingDir+"/fs_mark/.check") testsuite.MustRun(&cred, nil, "rm", "-rf", "/sdcard/fs_mark") if _, err := os.ReadDir(backingDir + "/fs_mark"); err == nil { log.Fatal("fs_mark directory was not removed") } else if !errors.Is(err, os.ErrNotExist) { log.Fatal(err) } }