Skip to content

Size of syscall.Dirent not always consistent with FUSE #197

Closed
@lechner

Description

@lechner

Hi,

This is from Debian packaging. On i386 the Getdents test in version 1.4.2 fails because the syscall.Dirent data structure gocryptfs uses has inconsistent sizes between architectures.

While the inode and offset members can vary in scenarios like this, they are not the issue here. The golang runtime uses only the getdents64 syscall and via cgo tweaks struct dirent to its liking (although I might have preferred struct dirent64 ). The issue here are the data types for name length and file type, as well as the padding for alignment.

On all architectures, both go-fuse and libfuse return at most 280 bytes. On amd64, that size matches the syscall.Dirent data type gocryptfs uses, but on i386 the latter drops to 276 bytes. It causes an error in internal/syscallcompat/getdents_linux.go:

if int(s.Reclen) > sizeofDirent {
    tlog.Warn.Printf("Getdents: corrupt entry #%d: Reclen=%d > %d. Returning EBADR",
        numEntries, s.Reclen, sizeofDirent)
    return nil, syscall.EBADR
}

Here is a small program to illustrate the various sizes. This is the output for amd64:

gocryptfs
unsafe.Sizeof (syscall.Dirent{})                 =  280

go-fuse
unsafe.Sizeof (gofuse_Dirent{}) + 256            =  280

libfuse
sizeof (struct libfuse_dirent) + 256             =  280

readdir(3), provided by libc
sizeof (struct dirent)                           =  280
sizeof (struct dirent64)                         =  280

getdents(3) syscall, not wrapped by libc
sizeof (struct linux_dirent) with 256[]          =  280

proposal to bring go-fuse in line with gocryptfs
unsafe.Sizeof (PROPOSED_gofuse_Dirent{}) + 256   =  280

For i386, the sizes are not nearly as consistent:

gocryptfs
unsafe.Sizeof (syscall.Dirent{})                 =  276

go-fuse
unsafe.Sizeof (gofuse_Dirent{}) + 256            =  280

libfuse
sizeof (struct libfuse_dirent) + 256             =  280

readdir(3), provided by libc
sizeof (struct dirent)                           =  276
sizeof (struct dirent64)                         =  276

getdents(3) syscall, not wrapped by libc
sizeof (struct linux_dirent) with 256[]          =  268

proposal to bring go-fuse in line with gocryptfs
unsafe.Sizeof (PROPOSED_gofuse_Dirent{}) + 256   =  276

Which data structure should be used in gocryptfs? Bonus question: Is FUSE safe on i386? Thank you!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions