Dangling Symlink Resolution and Missing sync_file_range and syncfs System Calls#110
Dangling Symlink Resolution and Missing sync_file_range and syncfs System Calls#110doanbaotrung wants to merge 1 commit into
Conversation
f381049 to
be86962
Compare
be86962 to
23ab75d
Compare
| */ | ||
| int64_t ret = 0; | ||
| if (flags & (1u | 4u)) { | ||
| ret = (fsync(host_ref.fd) < 0) ? linux_errno() : 0; |
There was a problem hiding this comment.
sync_file_range(2) on native Linux don't write back metadata. But MacOS don't provide syscall to accomplish such feature. fsync() will write back metadata.
So please add comment for mentioning different behavior comparing to Linux sync_file_range(2)
| return err; | ||
|
|
||
| /* Validate flags: only bits 1, 2, 4 are valid */ | ||
| if (flags & ~7u) { |
There was a problem hiding this comment.
Add offset, nbytes invalid check
if (offset < 0 || nbytes < 0 || offset + nbytes < offset)
return -LINUX_EINVAL;
dd617b3 to
c68c7d1
Compare
| return -LINUX_EINVAL; | ||
|
|
||
| host_fd_ref_t host_ref; | ||
| int64_t err = host_fd_ref_open_io(fd, &host_ref); |
There was a problem hiding this comment.
Mainline Linux rejects sync_file_range() on a descriptor that is not a
regular file, block device, or directory, returning -ESPIPE.
The current shim does not
classify the fd, so calling it on a pipe / socket / fifo / char device. Linux returns -ESPIPE in both cases.
Suggested fix (after host_fd_ref_open_io succeeds):
struct stat st;
if (fstat(host_ref.fd, &st) == 0 &&
!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode) && !S_ISDIR(st.st_mode)) {
host_fd_ref_close(&host_ref);
return -LINUX_ESPIPE;
}| SYS_fsync sc_fsync 1 | ||
| SYS_fdatasync sc_fdatasync 1 | ||
| SYS_sync_file_range sc_sync_file_range 1 | ||
| SYS_syncfs sc_syncfs 1 |
There was a problem hiding this comment.
scripts/gen-syscall-dispatch.py:141-142:
* E=0 means only x0-x2 are required by the wrapper.
* E=1 means x3-x5 may also be consumed by the wrapper.
sc_syncfs (src/syscall/syscall.c:1294) only uses x0 and explicitly voids
the rest.
Suggested fix:
SYS_syncfs sc_syncfs 0
|
The added tests pass (
The untested Both gaps close with two extra cases that also pass on native Linux (so no /* SYNC_FILE_RANGE_WRITE only (async hint) returns 0 without blocking.
* Covers the deliberate-divergence branch. */
if (syscall(SYS_sync_file_range, fd, (off64_t) 0, (off64_t) 0, 2) != 0) {
FAIL("sync_file_range write-only");
close(fd);
return;
}
/* Bad fd → EBADF. */
errno = 0;
if (syscall(SYS_sync_file_range, -1, (off64_t) 0, (off64_t) 0, 7) != -1 ||
errno != EBADF) {
FAIL("sync_file_range bad fd");
close(fd);
return;
}
|
c68c7d1 to
17431fb
Compare
In fs.c, the sys_renameat2 and sys_linkat system calls were using the resolving PATH_TR_NONE translation mode for the source paths. This caused elfuse to follow the symlink leaf names to their targets, causing dangling symlinks during package extraction to fail with ENOENT (No such file or directory). We updated these to use PATH_TR_NOFOLLOW for the leaf components, preventing path resolution from walking past the symlink itself. Missing sync_file_range and syncfs System Calls: We registered and defined SYS_sync_file_range (84) and SYS_syncfs (267) in abi.h and dispatch.tbl, and implemented them in syscall.c as aliases of sc_fsync_common.
17431fb to
bc965a3
Compare
|
Updated |
the
sys_renameat2andsys_linkatsystem callswere using the resolving PATH_TR_NONE translation
mode for the source paths.
This caused elfuse to follow the symlink
leaf names to their targets, causing
dangling symlinks during package extraction
to fail with ENOENT (No such file or directory).
We updated these to use PATH_TR_NOFOLLOW for
the leaf components, preventing path resolution
from walking past the symlink itself.
Missing sync_file_range and syncfs System
Calls: We registered and defined
SYS_sync_file_range (84) and
SYS_syncfs (267) in abi.h and dispatch.tbl,
and implemented them in syscall.c as
aliases of sc_fsync_common.
Summary by cubic
Fixes dangling symlink handling in
renameat2/linkatto prevent ENOENT during package extraction. AddsSYS_sync_file_range(84) andSYS_syncfs(267) with minimal Linux-compatible behavior and smoke tests.Bug Fixes
renameat2andlinkatstop following leaf symlinks (PATH_TR_NOFOLLOW);linkathonorsAT_SYMLINK_FOLLOWfor the source. New targets usePATH_TR_CREATE | PATH_TR_NOFOLLOW.New Features
SYS_sync_file_range/SYS_syncfs.sync_file_rangevalidates fd/offset/len, allows only flag bits 1/2/4, returns immediately for WRITE-only, callsfsync(fd)when WAIT flags are set, and returnsESPIPEon non-regular fds (e.g., pipes).syncfsvalidates the fd then callssync(). Added smoke tests covering success and errors (EINVAL,EBADF,ESPIPE).Written for commit bc965a3. Summary will update on new commits.