readdir: require opt-in for d_type flags
PATCH v2 1/1 readdir: require opt-in for d_type flags
Commit c31f91c6af96 ("fuse: don't allow signals to interrupt getdents copying") introduced the use of high bits in d_type as flags. However, overlayfs was not adapted to handle this change.
In ovl_cache_entry_new(), the code checks if d_type == DT_CHR to determine if an entry might be a whiteout. When fuse is used as the lower layer and sets high bits in d_type, this comparison fails, causing whiteout files to not be recognized properly and resulting in incorrect overlayfs behavior.
Fix this by requiring callers of iterate_dir() to opt-in for getting flag bits in d_type outside of S_DT_MASK.
---
Christian,
"Not pretty, but fine." [0]
This is what you had to say on the Fixes commit ;) Maybe this will be finer...
I was considering whether or not a mention in porting.rst is due.
My conclusion was that the regressing commit might have needed to mention a change of vfs API, but this fix brings the vfs API back to conform to pre v6.16 semantics, so no porting instructions apply.
Thanks,
Amir.
Chages sinse v1:
- Rename s/dt_flag_mask/dt_flags_mask/
- Add Test/Reviewd-by
[0] https://lore.kernel.org/linux-fsdevel/20250515-antlitz-aufzwingen-cdba155ce864@brauner/
fs/readdir.c | 3 +++ include/linux/fs.h | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-)
fs/readdir.c +3 -0
@@ -316,6 +316,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,struct getdents_callback buf = { .ctx.actor = filldir, .ctx.count = count, + .ctx.dt_flags_mask =FILLDIR_FLAG_NOINTR , .current_dir = dirent };int error;
@@ -400,6 +401,7 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,struct getdents_callback64 buf = { .ctx.actor = filldir64, .ctx.count = count, + .ctx.dt_flags_mask =FILLDIR_FLAG_NOINTR , .current_dir = dirent };int error;
@@ -569,6 +571,7 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,struct compat_getdents_callback buf = { .ctx.actor = compat_filldir, .ctx.count = count, + .ctx.dt_flags_mask =FILLDIR_FLAG_NOINTR , .current_dir = dirent, };int error;
include/linux/fs.h +5 -1
@@ -1855,6 +1855,8 @@ struct dir_context {* INT_MAX unlimited */ int count; +/* @actor supports these flags in d_type high bits */ +unsigned int dt_flags_mask; };/* If OR-ed with d_type, pending signals are not checked */
@@ -3524,7 +3526,9 @@ static inline bool dir_emit(struct dir_context *ctx, const char *name, int namelen, u64 ino, unsigned type) { - return ctx->actor(ctx, name, namelen, ctx->pos, ino, type); + unsigned int dt_mask = S_DT_MASK | ctx->dt_flags_mask; + +return ctx->actor (ctx, name, namelen, ctx->pos, ino, type & dt_mask); }static inline bool dir_emit_dot (struct file *file,struct dir_context *ctx) {
Signature · 1 line
2.52.0
Quoted 11 lines · Amir Goldstein
Commit
c31f91c6af96("fuse: don't allow signals to interrupt getdents copying") introduced the use of high bits ind_typeas flags. However, overlayfs was not adapted to handle this change.In
ovl_cache_entry_new(), the code checks ifd_type==DT_CHRto determine if an entry might be a whiteout. When fuse is used as the lower layer and sets high bits ind_type, this comparison fails, causing whiteout files to not be recognized properly and resulting in incorrect overlayfs behavior.[...]
Applied to the vfs.fixes branch of the vfs/vfs.git tree. Patches in the vfs.fixes branch should appear in linux-next soon.
Please report any outstanding bugs that were missed during review in a new review to the original patch series allowing us to drop it.
It's encouraged to provide Acked-bys and Reviewed-bys even though the patch has now been applied. If possible patch trailers will be updated.
Note that commit hashes shown below are subject to change due to rebase, trailer updates or similar. If in doubt, please check the listed branch.
tree: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git branch: vfs.fixes
[1/1] readdir: require opt-in for d_type flags
https://git.kernel.org/vfs/vfs/c/c644bce62b9c