google / gvisor

Application Kernel for Containers
https://gvisor.dev
Apache License 2.0
15.31k stars 1.27k forks source link

Open control FD in gofer server (and directfs gofer client) with O_PATH. #10385

Open ayushr2 opened 2 months ago

ayushr2 commented 2 months ago

Description

          > mountpoint_s3::fuse: open failed: inode error: inode 3 (full key "synmon/test_file.txt") is not writable while being read

The issue is that gVisor's gofer client (pkg/fsimpl/gofer/) opens the file read-only first and then opens it for writing, but mountpoint_s3::fuse refuses to support that. The gofer client first caches the dentry for the file being opened. It holds a "control FD" for all the dentries it caches. This control FD is opened with O_RDONLY|O_NONBLOCK: https://github.com/google/gvisor/blob/f67e10cf3866fe3a809c217ae0f47a9c47854ce1/pkg/sentry/fsimpl/gofer/directfs_dentry.go#L41-L50

I think we should change that logic to open regular files with O_PATH only. Directories and FIFOs can continue to be opened with O_RDONLY.

Originally posted by @ayushr2 in https://github.com/awslabs/mountpoint-s3/issues/862#issuecomment-2093697443

ayushr2 commented 2 months ago

This work may be more involved. The control FD is used to perform various operations on a file (see usages). Some of those operations will fail with EBADF if the control FD is a O_PATH FD. For instance: fchmod(2), fchown(2) and fgetxattr(2). See Linux kernel source code for these syscalls; they use fdget(fd) => __fget_light(fd, FMODE_PATH) which returns NULL for O_PATH FDs. So we will need to open all files with O_PATH and upgrade to a readable FD when needed OR use f*at(2) syscall variant with AT_EMPTY_PATH (which effectively bypasses this issue).

Some questions: