Skip to content

Commit c644bce

Browse files
amir73ilbrauner
authored andcommitted
readdir: require opt-in for d_type flags
Commit c31f91c ("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. Fixes: c31f91c ("fuse: don't allow signals to interrupt getdents copying") Link: https://lore.kernel.org/all/20260107034551.439-1-luochunsheng@ustc.edu/ Link: containerd/stargz-snapshotter#2214 Reported-by: Chunsheng Luo <luochunsheng@ustc.edu> Reviewed-by: Chunsheng Luo <luochunsheng@ustc.edu> Tested-by: Chunsheng Luo <luochunsheng@ustc.edu> Signed-off-by: Amir Goldstein <amir73il@gmail.com> Link: https://patch.msgid.link/20260108074522.3400998-1-amir73il@gmail.com Signed-off-by: Christian Brauner <brauner@kernel.org>
1 parent 7d42f2b commit c644bce

File tree

2 files changed

+8
-1
lines changed

2 files changed

+8
-1
lines changed

fs/readdir.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
316316
struct getdents_callback buf = {
317317
.ctx.actor = filldir,
318318
.ctx.count = count,
319+
.ctx.dt_flags_mask = FILLDIR_FLAG_NOINTR,
319320
.current_dir = dirent
320321
};
321322
int error;
@@ -400,6 +401,7 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
400401
struct getdents_callback64 buf = {
401402
.ctx.actor = filldir64,
402403
.ctx.count = count,
404+
.ctx.dt_flags_mask = FILLDIR_FLAG_NOINTR,
403405
.current_dir = dirent
404406
};
405407
int error;
@@ -569,6 +571,7 @@ COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
569571
struct compat_getdents_callback buf = {
570572
.ctx.actor = compat_filldir,
571573
.ctx.count = count,
574+
.ctx.dt_flags_mask = FILLDIR_FLAG_NOINTR,
572575
.current_dir = dirent,
573576
};
574577
int error;

include/linux/fs.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1855,6 +1855,8 @@ struct dir_context {
18551855
* INT_MAX unlimited
18561856
*/
18571857
int count;
1858+
/* @actor supports these flags in d_type high bits */
1859+
unsigned int dt_flags_mask;
18581860
};
18591861

18601862
/* If OR-ed with d_type, pending signals are not checked */
@@ -3524,7 +3526,9 @@ static inline bool dir_emit(struct dir_context *ctx,
35243526
const char *name, int namelen,
35253527
u64 ino, unsigned type)
35263528
{
3527-
return ctx->actor(ctx, name, namelen, ctx->pos, ino, type);
3529+
unsigned int dt_mask = S_DT_MASK | ctx->dt_flags_mask;
3530+
3531+
return ctx->actor(ctx, name, namelen, ctx->pos, ino, type & dt_mask);
35283532
}
35293533
static inline bool dir_emit_dot(struct file *file, struct dir_context *ctx)
35303534
{

0 commit comments

Comments
 (0)