Skip to content

Commit

Permalink
tests/root_test: add TestConcurrentUserOps and TestAsUserSleep
Browse files Browse the repository at this point in the history
Both work with

	golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a

but break with

	golang.org/x/sys v0.30.0

#893
#892
  • Loading branch information
rfjakob committed Feb 23, 2025
1 parent 3c82930 commit 178f570
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 2 deletions.
99 changes: 99 additions & 0 deletions tests/root_test/issue893_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//go:build linux

package root_test

import (
"fmt"
"io/ioutil"
"os"
"sync"
"syscall"
"testing"
"time"

"github.com/rfjakob/gocryptfs/v2/tests/test_helpers"
)

// gocryptfs v2.5.0 upgraded x/sys/unix and we found out that, since
// https://github.com/golang/sys/commit/d0df966e6959f00dc1c74363e537872647352d51 ,
// unix.Setreuid() and friends now affect the whole process instead of only the
// current thread, breaking allow_other: https://github.com/rfjakob/gocryptfs/issues/893
//
// Let's not have this happen again by testing it here.
func TestConcurrentUserOps(t *testing.T) {
if os.Getuid() != 0 {
t.Skip("must run as root")
}

var wg sync.WaitGroup

oneStressor := func(tid int) {
defer wg.Done()
err := asUser(10000+tid, 20000+tid, nil, func() (err error) {
for i := 0; i < 100; i++ {
d := fmt.Sprintf("%s/tid%d.i%d/foo/bar/baz", test_helpers.DefaultPlainDir, tid, i)
if err = os.MkdirAll(d, 0700); err != nil {
return
}
if err = ioutil.WriteFile(d+"/foo", nil, 0400); err != nil {
return
}
if err = ioutil.WriteFile(d+"/bar", []byte("aaaaaaaaaaaaaaaaaaaaa"), 0400); err != nil {
return
}
if err = syscall.Unlink(d + "/foo"); err != nil {
return
}
if err = os.Mkdir(d+"/foo", 0700); err != nil {
return
}
}
return nil
})
if err != nil {
t.Error(err)
}
}

threads := 4
wg.Add(threads)
for tid := 0; tid < threads; tid++ {
go oneStressor(tid)
}
wg.Wait()
}

// Test that our root_test.asUser function works as expected under concurrency by
// similating a long-runnig operation with sleep(10ms).
// https://github.com/rfjakob/gocryptfs/issues/893
func TestAsUserSleep(t *testing.T) {
if os.Getuid() != 0 {
t.Skip("must run as root")
}

var wg sync.WaitGroup
f := func(euid_want int) error {
euid_have := syscall.Geteuid()
if euid_want != euid_have {
return fmt.Errorf("wrong euid: want=%d have=%d", euid_want, euid_have)
}
time.Sleep(10 * time.Millisecond)
euid_have2 := syscall.Geteuid()
if euid_want != euid_have2 {
return fmt.Errorf("wrong euid: want=%d have2=%d", euid_want, euid_have2)
}
return nil
}
threads := 100
wg.Add(threads)
for i := 0; i < threads; i++ {
go func(i int) {
defer wg.Done()
err := asUser(10000+i, 20000+i, nil, func() error { return f(10000 + i) })
if err != nil {
t.Error(err)
}
}(i)
}
wg.Wait()
}
4 changes: 3 additions & 1 deletion tests/root_test/main_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux

package root_test

import (
Expand All @@ -9,7 +11,7 @@ import (

func TestMain(m *testing.M) {
test_helpers.ResetTmpDir(true)
os.Chmod(test_helpers.DefaultCipherDir, 0755)
os.Chmod(test_helpers.DefaultCipherDir, 0777)
test_helpers.MountOrExit(test_helpers.DefaultCipherDir, test_helpers.DefaultPlainDir, "-zerokey", "-allow_other")
r := m.Run()
test_helpers.UnmountPanic(test_helpers.DefaultPlainDir)
Expand Down
1 change: 0 additions & 1 deletion tests/root_test/root_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build linux
// +build linux

// Package root_test contains tests that need root
// permissions to run
Expand Down

0 comments on commit 178f570

Please sign in to comment.