From 964f0c190932e5dc53b05ec69ccda6e8d33a73b6 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Fri, 2 Jun 2023 14:24:44 +0200 Subject: fusefrontend: sharedstorage: use byte-range lock on file header creation Multiple hosts creating the same file at the same time could have overwritten each other's file header, leading to data corruption. Fix the race by placing a byte-range lock on the file when creating the file header. --- tests/cluster/cluster_test.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'tests/cluster') diff --git a/tests/cluster/cluster_test.go b/tests/cluster/cluster_test.go index 2e969ce..def03f1 100644 --- a/tests/cluster/cluster_test.go +++ b/tests/cluster/cluster_test.go @@ -10,8 +10,11 @@ import ( "math/rand" "os" "sync" + "syscall" "testing" + "golang.org/x/sys/unix" + "github.com/rfjakob/gocryptfs/v2/tests/test_helpers" ) @@ -109,3 +112,37 @@ func TestClusterConcurrentRW(t *testing.T) { go readThread(f2) wg.Wait() } + +// Check that byte-range locks work on an empty file +func TestFcntlFlock(t *testing.T) { + path := test_helpers.TmpDir + "/" + t.Name() + + fd1, err := syscall.Open(path, syscall.O_CREAT|syscall.O_WRONLY|syscall.O_EXCL, 0600) + if err != nil { + t.Fatal(err) + } + defer syscall.Close(fd1) + + // F_OFD_SETLK locks on the same fd always succeed, so we have to + // open a 2nd time. + fd2, err := syscall.Open(path, syscall.O_RDWR, 0) + if err != nil { + t.Fatal(err) + } + defer syscall.Close(fd2) + + lk := unix.Flock_t{ + Type: unix.F_WRLCK, + Whence: unix.SEEK_SET, + Start: 0, + Len: 0, + } + err = unix.FcntlFlock(uintptr(fd1), unix.F_OFD_SETLK, &lk) + if err != nil { + t.Fatal(err) + } + err = unix.FcntlFlock(uintptr(fd2), unix.F_OFD_SETLK, &lk) + if err == nil { + t.Fatal("double-lock succeeded but should have failed") + } +} -- cgit v1.2.3