You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Several callers wrote fd_table[gfd].linux_flags under different locks
or none at all, so a concurrent fcntl(F_SETFL/F_SETFD) on fd_lock could
race a creator's bare assignment. sys_fcntl read the slot's type and
flags outside fd_lock and mutated them without revalidation, so a
close+reopen between the read and the write could update an unrelated
fd. This commit unifies both concerns under fd_lock.
fd_publish_linux_flags helper
New fdtable helper takes fd_lock around a single linux_flags write.
Replaces bare assignments in sys_timerfd_create, sys_eventfd,
sys_signalfd, sys_inotify_init1, the FUSE dev mount, and fuse_open.
fuse_dup_fd takes fd_lock once for both the source read and the
destination write so the preserved-flags snapshot stays consistent
with a racing F_SETFL on either fd. The result: every write to
fd_table[*].linux_flags is now serialized on the same lock, with no
fuse_lock<->fd_lock nesting introduced.
sys_fcntl snapshot-then-revalidate
sys_fcntl now takes a single fd_snapshot at entry and uses it for
F_GETFD, F_GETFL, and F_DUPFD source reads. F_SETFD and the FUSE /
timerfd F_SETFL writers reacquire fd_lock and revalidate against
fd_snap.generation before mutating linux_flags. fd_alloc bumps a
monotonic generation counter per slot reuse, so close+reopen between
snapshot and lock is caught and returns EBADF rather than mutating an
unrelated fd.
The timerfd F_SETFL O_DIRECT EINVAL check moves inside the lock so a
stale-snapshot race cannot report EINVAL based on a fd that is no
longer a timerfd; the revalidation returns EBADF first instead.
A new test exercises the cross-cutting fd_lock RMW: F_SETFL stamps the
writable status bits, then F_SETFD toggles CLOEXEC, and F_GETFL must
still surface the status bits unperturbed.
0 commit comments