Linux CIFS filesystem development
 help / color / mirror / Atom feed
From: Frank Sorenson <sorenson@redhat.com>
To: linux-cifs@vger.kernel.org, pc@manguebit.org, stfrench@microsoft.com
Subject: Re: [PATCH v2 0/2] cifs: fix attribute cache corruption from concurrent directory operations
Date: Mon, 20 Jul 2026 12:19:30 -0500	[thread overview]
Message-ID: <8e0060e7-8579-4ccb-a2e3-a4df93db07f3@redhat.com> (raw)
In-Reply-To: <20260720163541.1428872-1-sorenson@redhat.com>

Sashiko doesn't appear very happy with either patch.  Looks like I'll 
need to rethink the approaches.

Frank


On 7/20/26 11:35 AM, Frank Sorenson wrote:
> This series fixes two distinct but related race conditions in the
> cifs/smb3 client where directory operations (lease breaks and readdir)
> can corrupt the attribute cache of recently modified files, causing
> subsequent stat() calls to return incorrect file sizes or fail with EIO.
>
> Both issues stem from the fundamental problem that directory-level
> metadata -- whether from a lease break notification or a readdir
> enumeration -- is not strictly synchronized with the authoritative state
> of open or recently closed files.
>
> Both bugs require as few as 2 concurrent threads performing directory
> and file operations simultaneously.  They only reproduce against Windows
> Server (where directory lease breaks occur and directory enumeration
> metadata lags behind file state); they do not reproduce against Samba.
> The workaround for both is to mount with actimeo=0, which forces every
> stat() to query the server directly rather than trusting the cache.
>
>
> Patch 1: cifs: serialize readdir with directory cache invalidation from lease breaks
> -------------------------------------------------------------------------------------
> When a directory lease break occurs while readdir is actively traversing
> the directory cache, the lease break handler calls cifs_revalidate_mapping()
> -> cifs_zap_mapping() while holding CIFS_INO_LOCK, racing with
> cifs_readdir() which traverses the same cache without that lock.  The
> resulting corruption causes subsequent stat() calls to return wrong file
> sizes or EIO errors.
>
> Fix: acquire CIFS_INO_LOCK at the start of cifs_readdir() so that lease
> break cache invalidation and readdir traversal are mutually exclusive.
>
>
> Patch 2: cifs: prevent readdir from changing file size due to stale directory metadata
> ---------------------------------------------------------------------------------------
> After writing to a file and closing it, concurrent readdir() can fetch
> stale directory metadata from the server (EndOfFile=0 for a recently
> written file) and overwrite the correct cached i_size.  The race window
> is between cifsFileInfo_put() removing the handle from openFileList
> (after which is_inode_writable() returns false) and stat() being called.
> The existing is_size_safe_to_change() check only blocks this when an
> active RW lease was held -- not after the last writable handle is closed.
>
> Fix: track the time of the last writable close or truncate in a new
> cifsInodeInfo->time_last_write field.  If readdir attempts to change
> i_size within acregmax jiffies of that timestamp, the update is
> suppressed.  When the suppressed size differs from the cached value,
> cifs_i->time is set to zero, forcing the next stat() to issue a fresh
> QUERY_INFO RPC.  QUERY_INFO returns the authoritative size from the
> server's open-file table rather than stale directory enumeration metadata,
> which is the same path taken by actimeo=0.
>
>
> Testing
> -------
> Both bugs reproduce against Windows Server 2022 with SMB 3.1.1 and
> at least 2 concurrent threads.  A reproducer program exercising
> concurrent rename+readdir (bug 1) and write+close+stat with concurrent
> readdir (bug 2) was run for 400000 iterations with both patches applied
> without hitting either bug.
>
> A reproducer is available at https://github.com/fsorenson/cifs_cache_race_repro/
>
>
> v2: fix malformed patch 2
>
>
> Frank Sorenson (2):
>    cifs: serialize readdir with directory cache invalidation from lease breaks
>    cifs: prevent readdir from changing file size due to stale directory metadata
>
>   fs/smb/client/cifsfs.c   |  1 +
>   fs/smb/client/cifsglob.h |  1 +
>   fs/smb/client/cifsproto.h |  1 +
>   fs/smb/client/file.c     | 24 +++++++++++++++++++++---
>   fs/smb/client/inode.c    |  6 +++++-
>   fs/smb/client/readdir.c  | 12 ++++++++++++
>   6 files changed, 45 insertions(+), 4 deletions(-)
>
> --
> 2.55.0


      parent reply	other threads:[~2026-07-20 17:19 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20 16:35 [PATCH v2 0/2] cifs: fix attribute cache corruption from concurrent directory operations Frank Sorenson
2026-07-20 16:35 ` [PATCH v2 1/2] cifs: serialize readdir with directory cache invalidation from lease breaks Frank Sorenson
2026-07-20 16:35 ` [PATCH v2 2/2] cifs: prevent readdir from changing file size due to stale directory metadata Frank Sorenson
2026-07-20 17:19 ` Frank Sorenson [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8e0060e7-8579-4ccb-a2e3-a4df93db07f3@redhat.com \
    --to=sorenson@redhat.com \
    --cc=linux-cifs@vger.kernel.org \
    --cc=pc@manguebit.org \
    --cc=stfrench@microsoft.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox