[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <c5e3cce3-5953-4060-ae62-76e33022f4aa@ustc.edu>
Date: Thu, 8 Jan 2026 11:45:10 +0800
From: Chunsheng Luo <luochunsheng@...c.edu>
To: Amir Goldstein <amir73il@...il.com>
Cc: miklos@...redi.hu, bschubert@....com, linux-unionfs@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-fsdevel <linux-fsdevel@...r.kernel.org>
Subject: Re: [PATCH] overlayfs: mask d_type high bits before whiteout check
On 1/8/26 4:43 AM, Amir Goldstein wrote:
> On Wed, Jan 7, 2026 at 4:46 AM Chunsheng Luo <luochunsheng@...c.edu> wrote:
>>
>> 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 masking out the high bits with S_DT_MASK before checking.
>>
>> Fixes: c31f91c6af96 ("fuse: don't allow signals to interrupt getdents copying")
>> Link: https://github.com/containerd/stargz-snapshotter/issues/2214
>> Signed-off-by: Chunsheng Luo <luochunsheng@...c.edu>
>
> Hi Chunsheng,
>
> Thanks for the report and the suggested fix.
>
> This time overlayfs was surprised by unexpected d_type flags and next
> time it could be another user.
>
> I prefer to fix this in a more profound way -
> Instead of making overlafys aware of d_type flags, require the users that
> use the d_type flags to opt-in for them.
>
> Please test/review the attached patch.
>
> Thanks,
> Amir.
>
Thank you for the profound solution!
The attached patch has been tested and verified to effectively address
the d_type high bits usage issue by enforcing the opt-in mechanism.
The variable `dt_flag_mask` might be clearer if renamed to
`dt_flags_mask` (plural "flags").
Reviewed-by: Chunsheng Luo <luochunsheng@...c.edu>
Tested-by: Chunsheng Luo <luochunsheng@...c.edu>
>
>> ---
>> fs/overlayfs/readdir.c | 15 +++++++++++++++
>> 1 file changed, 15 insertions(+)
>>
>> diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
>> index 160960bb0ad0..a2ac47458bf9 100644
>> --- a/fs/overlayfs/readdir.c
>> +++ b/fs/overlayfs/readdir.c
>> @@ -246,6 +246,9 @@ static int ovl_fill_lowest(struct ovl_readdir_data *rdd,
>> {
>> struct ovl_cache_entry *p;
>>
>> + /* Mask out high bits that may be used (e.g., fuse) */
>> + d_type &= S_DT_MASK;
>> +
>> p = ovl_cache_entry_find(rdd->root, c_name, c_len);
>> if (p) {
>> list_move_tail(&p->l_node, &rdd->middle);
>> @@ -316,6 +319,9 @@ static bool ovl_fill_merge(struct dir_context *ctx, const char *name,
>> char *cf_name = NULL;
>> int c_len = 0, ret;
>>
>> + /* Mask out high bits that may be used (e.g., fuse) */
>> + d_type &= S_DT_MASK;
>> +
>> if (ofs->casefold)
>> c_len = ovl_casefold(rdd, name, namelen, &cf_name);
>>
>> @@ -632,6 +638,9 @@ static bool ovl_fill_plain(struct dir_context *ctx, const char *name,
>> struct ovl_readdir_data *rdd =
>> container_of(ctx, struct ovl_readdir_data, ctx);
>>
>> + /* Mask out high bits that may be used (e.g., fuse) */
>> + d_type &= S_DT_MASK;
>> +
>> rdd->count++;
>> p = ovl_cache_entry_new(rdd, name, namelen, NULL, 0, ino, d_type);
>> if (p == NULL) {
>> @@ -755,6 +764,9 @@ static bool ovl_fill_real(struct dir_context *ctx, const char *name,
>> struct dir_context *orig_ctx = rdt->orig_ctx;
>> bool res;
>>
>> + /* Mask out high bits that may be used (e.g., fuse) */
>> + d_type &= S_DT_MASK;
>> +
>> if (rdt->parent_ino && strcmp(name, "..") == 0) {
>> ino = rdt->parent_ino;
>> } else if (rdt->cache) {
>> @@ -1144,6 +1156,9 @@ static bool ovl_check_d_type(struct dir_context *ctx, const char *name,
>> struct ovl_readdir_data *rdd =
>> container_of(ctx, struct ovl_readdir_data, ctx);
>>
>> + /* Mask out high bits that may be used (e.g., fuse) */
>> + d_type &= S_DT_MASK;
>> +
>> /* Even if d_type is not supported, DT_DIR is returned for . and .. */
>> if (!strncmp(name, ".", namelen) || !strncmp(name, "..", namelen))
>> return true;
>> --
>> 2.43.0
>>
Powered by blists - more mailing lists