aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/configfile/config_file.go8
-rw-r--r--internal/fido2/fido2.go2
-rw-r--r--internal/fusefrontend_reverse/node_helpers.go14
-rw-r--r--internal/fusefrontend_reverse/node_xattr_freebsd.go34
-rw-r--r--internal/syscallcompat/asuser_freebsd.go14
-rw-r--r--internal/syscallcompat/emulate.go2
-rw-r--r--internal/syscallcompat/emulate_test.go3
-rw-r--r--internal/syscallcompat/sys_freebsd.go68
-rw-r--r--internal/syscallcompat/sys_linux.go6
-rw-r--r--internal/syscallcompat/unix2syscall.go (renamed from internal/syscallcompat/unix2syscall_darwin.go)2
-rw-r--r--internal/syscallcompat/unix2syscall_freebsd.go28
-rw-r--r--tests/cluster/cluster_test.go4
-rw-r--r--tests/example_filesystems/example_test_helpers.go12
-rw-r--r--tests/matrix/atime_darwin+freebsd.go (renamed from tests/matrix/atime_darwin.go)2
-rw-r--r--tests/matrix/atime_freebsd.go9
15 files changed, 57 insertions, 151 deletions
diff --git a/internal/configfile/config_file.go b/internal/configfile/config_file.go
index 28a1ca5..ebd818e 100644
--- a/internal/configfile/config_file.go
+++ b/internal/configfile/config_file.go
@@ -31,7 +31,7 @@ type FIDO2Params struct {
// FIDO2 credential
CredentialID []byte
// FIDO2 hmac-secret salt
- HMACSalt []byte
+ HMACSalt []byte
AssertOptions []string
}
@@ -118,9 +118,9 @@ func Create(args *CreateArgs) error {
if len(args.Fido2CredentialID) > 0 {
cf.setFeatureFlag(FlagFIDO2)
cf.FIDO2 = &FIDO2Params{
- CredentialID: args.Fido2CredentialID,
- HMACSalt: args.Fido2HmacSalt,
- AssertOptions: args.Fido2AssertOptions,
+ CredentialID: args.Fido2CredentialID,
+ HMACSalt: args.Fido2HmacSalt,
+ AssertOptions: args.Fido2AssertOptions,
}
}
// Catch bugs and invalid cli flag combinations early
diff --git a/internal/fido2/fido2.go b/internal/fido2/fido2.go
index e08e589..f47795b 100644
--- a/internal/fido2/fido2.go
+++ b/internal/fido2/fido2.go
@@ -44,7 +44,7 @@ func callFidoCommand(command fidoCommand, assertOptions []string, device string,
var args []string
args = append(args, "-G")
args = append(args, "-h")
- for i := range assertOptions{
+ for i := range assertOptions {
args = append(args, "-t")
args = append(args, assertOptions[i])
}
diff --git a/internal/fusefrontend_reverse/node_helpers.go b/internal/fusefrontend_reverse/node_helpers.go
index f733689..dc8d928 100644
--- a/internal/fusefrontend_reverse/node_helpers.go
+++ b/internal/fusefrontend_reverse/node_helpers.go
@@ -17,13 +17,13 @@ import (
)
const (
- // File names are padded to 16-byte multiples, encrypted and
- // base64-encoded. We can encode at most 176 bytes to stay below the 255
- // bytes limit:
- // * base64(176 bytes) = 235 bytes
- // * base64(192 bytes) = 256 bytes (over 255!)
- // But the PKCS#7 padding is at least one byte. This means we can only use
- // 175 bytes for the file name.
+// File names are padded to 16-byte multiples, encrypted and
+// base64-encoded. We can encode at most 176 bytes to stay below the 255
+// bytes limit:
+// * base64(176 bytes) = 235 bytes
+// * base64(192 bytes) = 256 bytes (over 255!)
+// But the PKCS#7 padding is at least one byte. This means we can only use
+// 175 bytes for the file name.
)
// translateSize translates the ciphertext size in `out` into plaintext size.
diff --git a/internal/fusefrontend_reverse/node_xattr_freebsd.go b/internal/fusefrontend_reverse/node_xattr_freebsd.go
index 0577521..949cf15 100644
--- a/internal/fusefrontend_reverse/node_xattr_freebsd.go
+++ b/internal/fusefrontend_reverse/node_xattr_freebsd.go
@@ -1,43 +1,17 @@
package fusefrontend_reverse
import (
- "fmt"
-
"golang.org/x/sys/unix"
-
- "github.com/hanwen/go-fuse/v2/fs"
-
- "github.com/rfjakob/gocryptfs/v2/internal/syscallcompat"
)
const noSuchAttributeError = unix.ENOATTR
func (n *Node) getXAttr(cAttr string) (out []byte, errno unix.Errno) {
- d, errno := n.prepareAtSyscall("")
- if errno != 0 {
- return
- }
- defer unix.Close(d.dirfd)
-
- procPath := fmt.Sprintf("/proc/self/fd/%d/%s", d.dirfd, d.pName)
- pData, err := syscallcompat.Lgetxattr(procPath, cAttr)
- if err != nil {
- return nil, fs.ToErrno(err)
- }
- return pData, 0
+ // TODO
+ return nil, unix.EOPNOTSUPP
}
func (n *Node) listXAttr() (out []string, errno unix.Errno) {
- d, errno := n.prepareAtSyscall("")
- if errno != 0 {
- return
- }
- defer unix.Close(d.dirfd)
-
- procPath := fmt.Sprintf("/proc/self/fd/%d/%s", d.dirfd, d.pName)
- pNames, err := syscallcompat.Llistxattr(procPath)
- if err != nil {
- return nil, fs.ToErrno(err)
- }
- return pNames, 0
+ // TODO
+ return nil, unix.EOPNOTSUPP
}
diff --git a/internal/syscallcompat/asuser_freebsd.go b/internal/syscallcompat/asuser_freebsd.go
index 34ad41f..dfa8e18 100644
--- a/internal/syscallcompat/asuser_freebsd.go
+++ b/internal/syscallcompat/asuser_freebsd.go
@@ -1,7 +1,11 @@
package syscallcompat
import (
+ "golang.org/x/sys/unix"
+
"github.com/hanwen/go-fuse/v2/fuse"
+
+ "github.com/rfjakob/gocryptfs/v2/internal/tlog"
)
// asUser runs `f()` under the effective uid, gid, groups specified
@@ -9,8 +13,12 @@ import (
//
// If `context` is nil, `f()` is executed directly without switching user id.
//
-// WARNING this function is not complete, and always runs f() as if context is nil.
-// FreeBSD does not support changing uid/gid per thread.
+// FreeBSD does not support changing uid/gid per thread. If context is not nil,
+// an error is returned.
func asUser(f func() (int, error), context *fuse.Context) (int, error) {
- return f()
+ if context == nil {
+ return f()
+ }
+ tlog.Warn.Printf("asUser: error, only nil context is supported\n")
+ return 0, unix.EOPNOTSUPP
}
diff --git a/internal/syscallcompat/emulate.go b/internal/syscallcompat/emulate.go
index cdc4d12..435c579 100644
--- a/internal/syscallcompat/emulate.go
+++ b/internal/syscallcompat/emulate.go
@@ -1,4 +1,4 @@
-//go:build darwin
+//go:build !freebsd
package syscallcompat
diff --git a/internal/syscallcompat/emulate_test.go b/internal/syscallcompat/emulate_test.go
index 37889dc..907ba3a 100644
--- a/internal/syscallcompat/emulate_test.go
+++ b/internal/syscallcompat/emulate_test.go
@@ -1,4 +1,5 @@
-//go:build darwin
+//go:build !freebsd
+
package syscallcompat
import (
diff --git a/internal/syscallcompat/sys_freebsd.go b/internal/syscallcompat/sys_freebsd.go
index 874e920..d88b1cf 100644
--- a/internal/syscallcompat/sys_freebsd.go
+++ b/internal/syscallcompat/sys_freebsd.go
@@ -2,13 +2,13 @@
package syscallcompat
import (
- "errors"
- "fmt"
"time"
"golang.org/x/sys/unix"
"github.com/hanwen/go-fuse/v2/fuse"
+
+ "github.com/rfjakob/gocryptfs/v2/internal/tlog"
)
const (
@@ -29,6 +29,9 @@ const (
// On FreeBSD, we only have O_NOFOLLOW.
OpenatFlagNofollowSymlink = unix.O_NOFOLLOW
+
+ // For the utimensat syscall on FreeBSD
+ AT_EMPTY_PATH = 0x4000
)
// EnospcPrealloc is supposed to preallocate ciphertext space without
@@ -45,7 +48,8 @@ func EnospcPrealloc(fd int, off int64, len int64) (err error) {
// Fallocate returns an error if mode is not 0
func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
if mode != 0 {
- return errors.New("fallocate unsupported mode")
+ tlog.Warn.Printf("Fallocate: unsupported mode\n")
+ return unix.EOPNOTSUPP
}
_, _, err = unix.Syscall(unix.SYS_POSIX_FALLOCATE, uintptr(fd), uintptr(off), uintptr(len))
return err
@@ -63,37 +67,8 @@ func Dup3(oldfd int, newfd int, flags int) (err error) {
}
// FchmodatNofollow is like Fchmodat but never follows symlinks.
-//
-// This should be handled by the AT_SYMLINK_NOFOLLOW flag, but Linux
-// does not implement it, so we have to perform an elaborate dance
-// with O_PATH and /proc/self/fd.
-//
-// See also: Qemu implemented the same logic as fchmodat_nofollow():
-// https://git.qemu.org/?p=qemu.git;a=blob;f=hw/9pfs/9p-local.c#l335
func FchmodatNofollow(dirfd int, path string, mode uint32) (err error) {
- // Open handle to the filename (but without opening the actual file).
- // This succeeds even when we don't have read permissions to the file.
- fd, err := unix.Openat(dirfd, path, unix.O_NOFOLLOW|O_PATH, 0)
- if err != nil {
- return err
- }
- defer unix.Close(fd)
-
- // Now we can check the type without the risk of race-conditions.
- // Return syscall.ELOOP if it is a symlink.
- var st unix.Stat_t
- err = unix.Fstat(fd, &st)
- if err != nil {
- return err
- }
- if st.Mode&unix.S_IFMT == unix.S_IFLNK {
- return unix.ELOOP
- }
-
- // Change mode of the actual file. Fchmod does not work with O_PATH,
- // but Chmod via /proc/self/fd works.
- procPath := fmt.Sprintf("/proc/self/fd/%d", fd)
- return unix.Chmod(procPath, mode)
+ return unix.Fchmodat(dirfd, path, mode, unix.AT_SYMLINK_NOFOLLOW)
}
// LsetxattrUser runs the Lsetxattr syscall in the context of a different user.
@@ -128,10 +103,7 @@ func timesToTimespec(a *time.Time, m *time.Time) []unix.Timespec {
// FutimesNano syscall.
func FutimesNano(fd int, a *time.Time, m *time.Time) (err error) {
ts := timesToTimespec(a, m)
- // To avoid introducing a separate syscall wrapper for futimens()
- // (as done in go-fuse, for example), we instead use the /proc/self/fd trick.
- procPath := fmt.Sprintf("/proc/self/fd/%d", fd)
- return unix.UtimesNanoAt(unix.AT_FDCWD, procPath, ts, 0)
+ return unix.UtimesNanoAt(unix.AT_FDCWD, "", ts, AT_EMPTY_PATH)
}
// UtimesNanoAtNofollow is like UtimesNanoAt but never follows symlinks.
@@ -156,8 +128,9 @@ func GetdentsSpecial(fd int) (entries []fuse.DirEntry, entriesSpecial []fuse.Dir
return emulateGetdents(fd)
}
-// Renameat2 does not exist on Darwin, so we have to wrap it here.
+// Renameat2 does not exist on FreeBSD, so we have to wrap it here.
// Retries on EINTR.
+// The RENAME_EXCHANGE and RENAME_WHITEOUT flags are not supported.
func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags uint) (err error) {
if flags&(RENAME_NOREPLACE|RENAME_EXCHANGE) == RENAME_NOREPLACE|RENAME_EXCHANGE {
return unix.EINVAL
@@ -177,24 +150,7 @@ func Renameat2(olddirfd int, oldpath string, newdirfd int, newpath string, flags
}
}
if flags&RENAME_EXCHANGE != 0 {
- // Note that on Linux, RENAME_EXCHANGE can handle oldpath and
- // newpath of different file types (e.g. directory and
- // symbolic link). On FreeBSD the file types must be the same.
- var stold, stnew unix.Stat_t
- err = unix.Fstatat(olddirfd, oldpath, &stold, 0)
- if err != nil {
- // Assume file does not exist if we can't stat() it.
- // On Linux, RENAME_EXCHANGE requires both oldpath
- // and newpath exist.
- return unix.ENOENT
- }
- err = unix.Fstatat(newdirfd, newpath, &stnew, 0)
- if err != nil {
- // Assume file does not exist if we can't stat() it.
- // On Linux, RENAME_EXCHANGE requires both oldpath
- // and newpath exist.
- return unix.ENOENT
- }
+ return unix.EINVAL
}
if flags&RENAME_WHITEOUT != 0 {
return unix.EINVAL
diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go
index 4669d8a..a850ba1 100644
--- a/internal/syscallcompat/sys_linux.go
+++ b/internal/syscallcompat/sys_linux.go
@@ -29,12 +29,12 @@ const (
RENAME_WHITEOUT = unix.RENAME_WHITEOUT
RENAME_EXCHANGE = unix.RENAME_EXCHANGE
- // Only defined on Linux
- ENODATA = unix.ENODATA
-
// On Darwin we use O_SYMLINK which allows opening a symlink itself.
// On Linux, we only have O_NOFOLLOW.
OpenatFlagNofollowSymlink = unix.O_NOFOLLOW
+
+ // Only defined on Linux
+ ENODATA = unix.ENODATA
)
var preallocWarn sync.Once
diff --git a/internal/syscallcompat/unix2syscall_darwin.go b/internal/syscallcompat/unix2syscall.go
index 5767a27..fa2e8c4 100644
--- a/internal/syscallcompat/unix2syscall_darwin.go
+++ b/internal/syscallcompat/unix2syscall.go
@@ -1,3 +1,5 @@
+//go:build darwin || freebsd
+
package syscallcompat
import (
diff --git a/internal/syscallcompat/unix2syscall_freebsd.go b/internal/syscallcompat/unix2syscall_freebsd.go
deleted file mode 100644
index fe85cf6..0000000
--- a/internal/syscallcompat/unix2syscall_freebsd.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package syscallcompat
-
-import (
- "syscall"
-
- "golang.org/x/sys/unix"
-)
-
-// Unix2syscall converts a unix.Stat_t struct to a syscall.Stat_t struct.
-// A direct cast does not work because the padding is named differently in
-// unix.Stat_t for some reason ("X__unused" in syscall, "_" in unix).
-func Unix2syscall(u unix.Stat_t) syscall.Stat_t {
- return syscall.Stat_t{
- Dev: u.Dev,
- Ino: u.Ino,
- Nlink: u.Nlink,
- Mode: u.Mode,
- Uid: u.Uid,
- Gid: u.Gid,
- Rdev: u.Rdev,
- Size: u.Size,
- Blksize: u.Blksize,
- Blocks: u.Blocks,
- Atimespec: syscall.NsecToTimespec(unix.TimespecToNsec(u.Atim)),
- Mtimespec: syscall.NsecToTimespec(unix.TimespecToNsec(u.Mtim)),
- Ctimespec: syscall.NsecToTimespec(unix.TimespecToNsec(u.Ctim)),
- }
-}
diff --git a/tests/cluster/cluster_test.go b/tests/cluster/cluster_test.go
index 2e969ce..af93bc4 100644
--- a/tests/cluster/cluster_test.go
+++ b/tests/cluster/cluster_test.go
@@ -27,8 +27,8 @@ import (
// > buffered read/write.
//
// See also:
-// * https://lore.kernel.org/linux-xfs/20190325001044.GA23020@dastard/
-// Dave Chinner: XFS is the only linux filesystem that provides this behaviour.
+// - https://lore.kernel.org/linux-xfs/20190325001044.GA23020@dastard/
+// Dave Chinner: XFS is the only linux filesystem that provides this behaviour.
func TestClusterConcurrentRW(t *testing.T) {
if os.Getenv("ENABLE_CLUSTER_TEST") != "1" {
t.Skipf("This test is disabled by default because it fails unless on XFS.\n" +
diff --git a/tests/example_filesystems/example_test_helpers.go b/tests/example_filesystems/example_test_helpers.go
index 34e5786..5e38721 100644
--- a/tests/example_filesystems/example_test_helpers.go
+++ b/tests/example_filesystems/example_test_helpers.go
@@ -27,26 +27,26 @@ func checkExampleFS(t *testing.T, dir string, rw bool) {
symlink := filepath.Join(dir, "rel")
target, err := os.Readlink(symlink)
if err != nil {
- t.Error(err)
+ t.Errorf("relative symlink: Readlink: %v", err)
return
}
if target != "status.txt" {
- t.Errorf("Unexpected link target: %s\n", target)
+ t.Errorf("relative symlink: Unexpected link target: %s\n", target)
}
// Read absolute symlink
symlink = filepath.Join(dir, "abs")
target, err = os.Readlink(symlink)
if err != nil {
- t.Error(err)
+ t.Errorf("absolute symlink: Readlink: %v", err)
return
}
if target != "/a/b/c/d" {
- t.Errorf("Unexpected link target: %s\n", target)
+ t.Errorf("absolute symlink: Unexpected link target: %s\n", target)
}
if rw {
// Test directory operations
- test_helpers.TestRename(t, dir)
- test_helpers.TestMkdirRmdir(t, dir)
+ t.Run("TestRename", func(t *testing.T) { test_helpers.TestRename(t, dir) })
+ t.Run("TestMkdirRmdir", func(t *testing.T) { test_helpers.TestMkdirRmdir(t, dir) })
}
}
diff --git a/tests/matrix/atime_darwin.go b/tests/matrix/atime_darwin+freebsd.go
index 5f89c69..43db0d5 100644
--- a/tests/matrix/atime_darwin.go
+++ b/tests/matrix/atime_darwin+freebsd.go
@@ -1,3 +1,5 @@
+//go:build darwin || freebsd
+
package matrix
import (
diff --git a/tests/matrix/atime_freebsd.go b/tests/matrix/atime_freebsd.go
deleted file mode 100644
index 5f89c69..0000000
--- a/tests/matrix/atime_freebsd.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package matrix
-
-import (
- "syscall"
-)
-
-func extractAtimeMtime(st syscall.Stat_t) [2]syscall.Timespec {
- return [2]syscall.Timespec{st.Atimespec, st.Mtimespec}
-}