Skip to content

Unchecked int64->uint64 cast in inodeAttrs publishes huge st_size on negative size_bytes #13

Description

@Nadav0077

What

inodeAttrs in internal/fusefs/fuse_unix.go takes size uint64 and every caller that threads a stored size through it does an unchecked uint64(size) cast on a value that is signed int64 everywhere else in the codebase. If that signed value is ever negative, the cast wraps and the mount publishes a huge st_size to the kernel instead of rejecting or clamping.

Why it's a problem

size_bytes is stored as a SQLite INTEGER in both internal/snapshot/store.go and internal/overlay/store.go, scanned back into Go as int64, and threaded through resolver.Getattr as int64. Nothing on the read path verifies that the value is non-negative before it reaches the FUSE attr boundary.

Concrete trip points are:

  • LookUpInode at internal/fusefs/fuse_unix.go:198
  • GetInodeAttributes at internal/fusefs/fuse_unix.go:219
  • SetInodeAttributes at internal/fusefs/fuse_unix.go:246

All three do inodeAttrs(mode, uint64(size), typ, mtime). The final assignment lands in fuseops.InodeAttributes.Size (uint64). So int64(-1) becomes st_size = 18446744073709551615.

The hunt notes persistent snapshot and overlay state as a trust boundary, which makes the unchecked conversion the actual bug rather than "garbage in, garbage out."

Repro

Manually set a negative size_bytes row in either database (or simulate one in a resolver.Getattr stub), then stat the path through the mount. The reported st_size is ~18 EB instead of 0 or an error.

Proposed fix

Change inodeAttrs to take a signed int64 and clamp negatives to 0 inside the function. All five existing call sites already have integer literals or int64 variables, so the casts disappear. The existing "dir with size 0 reports 4096" behavior is preserved. PR to follow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions