From eaca820e876bfcdc67323eac6dd43ecc420968f2 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sun, 7 Feb 2021 20:01:16 +0100 Subject: fusefrontend: do not encrypt ACLs Pass through system.posix_acl_access and system.posix_acl_default unencrypted to fix "cp -a" problems. "cp -a" uses "setxattr" even to set normal permissions, see https://www.spinics.net/lists/linux-nfs/msg63986.html . Fixes https://github.com/rfjakob/gocryptfs/issues/543 --- tests/defaults/acl_test.go | 202 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 tests/defaults/acl_test.go (limited to 'tests') diff --git a/tests/defaults/acl_test.go b/tests/defaults/acl_test.go new file mode 100644 index 0000000..b3826e8 --- /dev/null +++ b/tests/defaults/acl_test.go @@ -0,0 +1,202 @@ +package defaults + +import ( + "io/ioutil" + "math/rand" + "os" + "os/exec" + "path/filepath" + "syscall" + "testing" + "time" + + "golang.org/x/sys/unix" + + "github.com/pkg/xattr" + + "github.com/rfjakob/gocryptfs/tests/test_helpers" +) + +// https://github.com/rfjakob/gocryptfs/issues/543 +func TestCpA(t *testing.T) { + fn1 := filepath.Join(test_helpers.TmpDir, t.Name()) + fn2 := filepath.Join(test_helpers.DefaultPlainDir, t.Name()) + + rand.Seed(int64(time.Now().Nanosecond())) + + { + // Need unrestricted umask + old := syscall.Umask(000) + defer syscall.Umask(old) + } + + for i := 0; i < 10; i++ { + // Random permissions (except owner read, which cp needs) + var modeWant os.FileMode = os.FileMode(rand.Int31n(0777+1) | 0400) + + // Create file outside mount + err := ioutil.WriteFile(fn1, nil, modeWant) + if err != nil { + t.Fatal(err) + } + // Verify perms (umask problems?) + fi, err := os.Stat(fn1) + if err != nil { + t.Fatal(err) + } + if fi.Mode() != modeWant { + t.Errorf("ioutil.WriteFile created wrong permissions: want %o have %o", modeWant, fi.Mode()) + } + + // "cp -a" from outside to inside mount + c := exec.Command("cp", "-a", fn1, fn2) + c.Stderr = os.Stderr + c.Stdout = os.Stdout + err = c.Run() + if err != nil { + t.Fatal(err) + } + + // Check perms + fi, err = os.Stat(fn2) + if err != nil { + t.Fatal(err) + } + if fi.Mode() != modeWant { + t.Errorf("cp -a did not preserve permissions: want %o have %o", modeWant, fi.Mode()) + } + + syscall.Unlink(fn1) + syscall.Unlink(fn2) + } +} + +func getfacl(fn string) (string, error) { + c := exec.Command("getfacl", "-c", "--", fn) + out, err := c.Output() + return string(out), err +} + +// https://github.com/rfjakob/gocryptfs/issues/543 +func TestAcl543(t *testing.T) { + fn1 := test_helpers.TmpDir + "/TestAcl543" + fn2 := test_helpers.DefaultPlainDir + "/TestAcl543" + + var c *exec.Cmd + + var modeWant os.FileMode = 0777 + + { + // Need unrestricted umask + old := syscall.Umask(000) + defer syscall.Umask(old) + } + + // Set acl on file outside gocryptfs mount + err := ioutil.WriteFile(fn1, nil, modeWant) + if err != nil { + t.Fatal(err) + } + c = exec.Command("setfacl", "-m", "u:daemon:rwx", fn1) + c.Stderr = os.Stderr + c.Stdout = os.Stdout + err = c.Run() + if err != nil { + t.Skip(err) + } + aclWant, err := getfacl(fn1) + if err != nil { + t.Fatal(err) + } + fi, err := os.Stat(fn1) + if fi.Mode() != modeWant { + t.Fatalf("mode changed from %o to %o", modeWant, fi.Mode()) + } + + // Set acl on file inside gocryptfs mount + err = ioutil.WriteFile(fn2, nil, modeWant) + if err != nil { + t.Fatal(err) + } + c = exec.Command("setfacl", "-m", "u:daemon:rwx", fn2) + c.Stderr = os.Stderr + c.Stdout = os.Stdout + err = c.Run() + if err != nil { + t.Fatal(err) + } + aclHave1, err := getfacl(fn1) + if err != nil { + t.Fatal(err) + } + if aclHave1 != aclWant { + t.Error(aclHave1) + } + os.Remove(fn2) + + // "cp -a" from outside to inside mount + c = exec.Command("cp", "-a", fn1, fn2) + c.Stderr = os.Stderr + c.Stdout = os.Stdout + err = c.Run() + if err != nil { + t.Fatal(err) + } + fi, err = os.Stat(fn2) + if err != nil { + t.Fatal(err) + } + if fi.Mode() != modeWant { + t.Errorf("cp -a did not preserve permissions: want %o have %o", modeWant, fi.Mode()) + } + aclHave2, err := getfacl(fn2) + if err != nil { + t.Fatal(err) + } + if aclHave2 != aclWant { + t.Errorf("cp -a did not preserve acl: %q", aclHave1) + } +} + +// Check that we handle zero-sized and undersized buffers correctly +func TestXattrOverflow(t *testing.T) { + fn := filepath.Join(test_helpers.DefaultPlainDir, t.Name()) + ioutil.WriteFile(fn, nil, 0600) + + attr := "user.foo123" + val := []byte("12341234") + err := xattr.LSet(fn, attr, val) + if err != nil { + t.Skip(err) + } + + // Getxattr + sz, err := unix.Lgetxattr(fn, attr, nil) + if err != nil { + t.Error(err) + } + if sz != len(val) { + t.Errorf("wrong sz: want %d have %d", len(val), sz) + } + sz, err = unix.Lgetxattr(fn, attr, make([]byte, 1)) + if err != syscall.ERANGE { + t.Error(err) + } + + // Listxattr + szWant, err := unix.Llistxattr(fn, make([]byte, 64*1024)) + if err != nil { + t.Fatal(err) + } + sz, err = unix.Llistxattr(fn, nil) + if err != nil { + t.Error(err) + } + if sz != szWant { + t.Errorf("wrong sz: want %d have %d", szWant, sz) + } + sz, err = unix.Llistxattr(fn, make([]byte, 1)) + if err != syscall.ERANGE { + t.Error(err) + } +} -- cgit v1.2.3