Fix strict-root mode for files larger than 2 GiB on 32-bit platforms#61
Conversation
In strict-root mode files are opened through os.Root, whose internal openat
does not set O_LARGEFILE. On 32-bit kernels this makes opening any file larger
than 2 GiB fail with EOVERFLOW ("value too large for defined data type").
Since every PS3 ISO exceeds 2 GiB, strict-root mode cannot stream PS3 games on
32-bit hosts (e.g. armv5tel/armv7 NAS units); the relaxed root works only
because it uses os.Open, which does add O_LARGEFILE.
Wrap *os.Root so its Open/Create forward O_LARGEFILE via os.Root.OpenFile
(which passes the flag verbatim to openat), preserving os.Root's symlink-safe
traversal. O_LARGEFILE is 0 on 64-bit and non-Linux platforms, so the change
is a no-op there.
|
Thank you for this fix. I think this should be filed as an issue in Go repository if |
Address review feedback on the strict-root large-file fix: - Move the StrictSystemRoot wrapper and the openLargeFile constant from pkg/fs into internal/osutil, alongside the other os-specific helpers. The constant cannot live in pkg/fs and be referenced from a wrapper there while osutil imports pkg/fs (filetimes) without creating an import cycle, so the wrapper moves too; it only depends on os. - Drop the redundant "//go:build linux" tag. Instead of a filename OS suffix, use an explicit "linux || solaris || aix || zos" constraint, which are exactly the platforms where golang.org/x/sys/unix defines O_LARGEFILE. A plain "unix" constraint would fail to compile on darwin/BSD, where the constant does not exist. cmd/ps3netsrv-go/server.go now calls osutil.NewStrictSystemRoot.
|
Thanks for the review! Addressed in the latest commit:
Verified |
|
Thank you! I'll tag a new release later when finish work on socket-activation feature. |
Problem
In
strict-rootmode the server cannot open any file larger than 2 GiB on32-bit platforms. The open fails with:
Because every PS3 ISO exceeds 2 GiB, strict-root mode is effectively unusable
for PS3 streaming on 32-bit NAS hardware (e.g. armv5tel / armv7 units). The
relaxed root works only by accident: it uses
os.Open, which addsO_LARGEFILE.Root cause
strict-rootusesos.Root, whose internalopenat(
internal/syscall/unix.Openat) is called withoutO_LARGEFILE. On 32-bitkernels the kernel then rejects files whose size does not fit in a 32-bit
off_twithEOVERFLOW.os.Open/syscall.Opendo OR inO_LARGEFILE,which is why the relaxed root is unaffected.
Fix
Wrap
*os.Rootso itsOpen/CreateforwardO_LARGEFILEthroughos.Root.OpenFile, which passes the flag verbatim toopenat. This preservesall of
os.Root's symlink-safe, traversal-safe behaviour.O_LARGEFILEis0on 64-bit and on non-Linux platforms, so the change is a no-op there.
pkg/fs/strict_root.go—StrictSystemRootwrapperpkg/fs/largefile_linux.go/largefile_other.go— platform constantcmd/ps3netsrv-go/server.go— use the wrapper for strict-rootTesting
32-bit armv5tel QNAP NAS (previously failed with EOVERFLOW).
windows/amd64;
go vetclean.