aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/sharefs
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2026-10-06 22:23:20 +0900
committerOphestra <cat@gensokyo.uk>2026-10-06 23:09:19 +0900
commita9e2749f6654d0aa07b274a45c9177d10323f80a (patch)
tree291f5b23a67af036cbe5d374b3d3fb0240fc438c /test/sharefs
parent19f36491f2e2a5029ac396c10408d653cad6c81b (diff)
internal/testsuite: move from test
This structure is a lot less clumsy than the old nix-centric layout. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'test/sharefs')
-rw-r--r--test/sharefs/main.go119
-rw-r--r--test/sharefs/raceattr.go122
2 files changed, 0 insertions, 241 deletions
diff --git a/test/sharefs/main.go b/test/sharefs/main.go
deleted file mode 100644
index 80e6ab09..00000000
--- a/test/sharefs/main.go
+++ /dev/null
@@ -1,119 +0,0 @@
-//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/test/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)
- }
-}
diff --git a/test/sharefs/raceattr.go b/test/sharefs/raceattr.go
deleted file mode 100644
index 412cb2b3..00000000
--- a/test/sharefs/raceattr.go
+++ /dev/null
@@ -1,122 +0,0 @@
-//go:build raceattr
-
-// The raceattr program reproduces vfs inode file attribute race.
-//
-// Even though libfuse high-level API presents the address of a struct stat
-// alongside struct fuse_context, file attributes are actually inherent to the
-// inode, instead of the specific call from userspace. The kernel implementation
-// in fs/fuse/xattr.c appears to make stale data in the inode (set by a previous
-// call) impossible or very unlikely to reach userspace via the stat family of
-// syscalls. However, when using default_permissions to have the VFS check
-// permissions, this race still happens, despite the resulting struct stat being
-// correct when overriding the check via capabilities otherwise.
-//
-// This program reproduces the failure, but because of its continuous nature, it
-// is provided independent of the vm integration test suite.
-package main
-
-import (
- "context"
- "flag"
- "log"
- "os"
- "os/signal"
- "runtime"
- "sync"
- "sync/atomic"
- "syscall"
-)
-
-func newStatAs(
- ctx context.Context, cancel context.CancelFunc,
- n *atomic.Uint64, ok *atomic.Bool,
- uid uint32, pathname string,
- continuous bool,
-) func() {
- return func() {
- runtime.LockOSThread()
- defer cancel()
-
- if _, _, errno := syscall.Syscall(
- syscall.SYS_SETUID, uintptr(uid),
- 0, 0,
- ); errno != 0 {
- cancel()
- log.Printf("cannot set uid to %d: %s", uid, errno)
- }
-
- var stat syscall.Stat_t
- for {
- if ctx.Err() != nil {
- return
- }
-
- if err := syscall.Lstat(pathname, &stat); err != nil {
- // SHAREFS_PERM_DIR not world executable, or
- // SHAREFS_PERM_REG not world readable
- if !continuous {
- cancel()
- }
- ok.Store(true)
- log.Printf("uid %d: %v", uid, err)
- } else if stat.Uid != uid {
- // appears to be unreachable
- if !continuous {
- cancel()
- }
- ok.Store(true)
- log.Printf("got uid %d instead of %d", stat.Uid, uid)
- }
- n.Add(1)
- }
- }
-}
-
-func main() {
- log.SetFlags(0)
- log.SetPrefix("raceattr: ")
-
- p := flag.String("target", "/sdcard/raceattr", "pathname of test file")
- u0 := flag.Int("uid0", 1<<10-1, "first uid")
- u1 := flag.Int("uid1", 1<<10-2, "second uid")
- count := flag.Int("count", 1, "threads per uid")
- continuous := flag.Bool("continuous", false, "keep running even after reproduce")
- flag.Parse()
-
- if os.Geteuid() != 0 {
- log.Fatal("this program must run as root")
- }
-
- ctx, cancel := signal.NotifyContext(
- context.Background(),
- syscall.SIGINT,
- syscall.SIGTERM,
- syscall.SIGHUP,
- )
-
- if err := os.WriteFile(*p, nil, 0); err != nil {
- log.Fatal(err)
- }
-
- var (
- wg sync.WaitGroup
-
- n atomic.Uint64
- ok atomic.Bool
- )
-
- if *count < 1 {
- *count = 1
- }
- for range *count {
- wg.Go(newStatAs(ctx, cancel, &n, &ok, uint32(*u0), *p, *continuous))
- if *u1 >= 0 {
- wg.Go(newStatAs(ctx, cancel, &n, &ok, uint32(*u1), *p, *continuous))
- }
- }
-
- wg.Wait()
- if !*continuous && ok.Load() {
- log.Printf("reproduced after %d calls", n.Load())
- }
-}