Linux CIFS filesystem development
 help / color / mirror / Atom feed
* [PATCH 1/6] smb: client: ensure open_cached_dir_by_dentry() only returns valid cfid
@ 2025-09-19 15:24 Henrique Carvalho
  2025-09-19 15:24 ` [PATCH 2/6] smb: client: short-circuit in open_cached_dir_by_dentry() if !dentry Henrique Carvalho
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Henrique Carvalho @ 2025-09-19 15:24 UTC (permalink / raw)
  To: smfrench; +Cc: ematsumiya, linux-cifs, Henrique Carvalho

open_cached_dir_by_dentry() was exposing an invalid cached directory to
callers. The validity check outside the function was exclusively based
on cfid->time.

Add validity check before returning success and introduce
is_valid_cached_dir() helper for consistent checks across the code.

Signed-off-by: Henrique Carvalho <henrique.carvalho@suse.com>
---
 fs/smb/client/cached_dir.c | 9 +++++----
 fs/smb/client/cached_dir.h | 6 ++++++
 fs/smb/client/dir.c        | 2 +-
 fs/smb/client/inode.c      | 2 +-
 4 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
index b69daeb1301b..63dc9add4f13 100644
--- a/fs/smb/client/cached_dir.c
+++ b/fs/smb/client/cached_dir.c
@@ -36,9 +36,8 @@ static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
 			 * fully cached or it may be in the process of
 			 * being deleted due to a lease break.
 			 */
-			if (!cfid->time || !cfid->has_lease) {
+			if (!is_valid_cached_dir(cfid))
 				return NULL;
-			}
 			kref_get(&cfid->refcount);
 			return cfid;
 		}
@@ -194,7 +193,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 	 * Otherwise, it is either a new entry or laundromat worker removed it
 	 * from @cfids->entries.  Caller will put last reference if the latter.
 	 */
-	if (cfid->has_lease && cfid->time) {
+	if (is_valid_cached_dir(cfid)) {
 		cfid->last_access_time = jiffies;
 		spin_unlock(&cfids->cfid_list_lock);
 		*ret_cfid = cfid;
@@ -233,7 +232,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 			list_for_each_entry(parent_cfid, &cfids->entries, entry) {
 				if (parent_cfid->dentry == dentry->d_parent) {
 					cifs_dbg(FYI, "found a parent cached file handle\n");
-					if (parent_cfid->has_lease && parent_cfid->time) {
+					if (is_valid_cached_dir(parent_cfid)) {
 						lease_flags
 							|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
 						memcpy(pfid->parent_lease_key,
@@ -420,6 +419,8 @@ int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
 	spin_lock(&cfids->cfid_list_lock);
 	list_for_each_entry(cfid, &cfids->entries, entry) {
 		if (dentry && cfid->dentry == dentry) {
+			if (!is_valid_cached_dir(cfid))
+				break;
 			cifs_dbg(FYI, "found a cached file handle by dentry\n");
 			kref_get(&cfid->refcount);
 			*ret_cfid = cfid;
diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
index 46b5a2fdf15b..aa12382b4249 100644
--- a/fs/smb/client/cached_dir.h
+++ b/fs/smb/client/cached_dir.h
@@ -64,6 +64,12 @@ struct cached_fids {
 	struct delayed_work laundromat_work;
 };
 
+static inline bool
+is_valid_cached_dir(struct cached_fid *cfid)
+{
+	return cfid->time && cfid->has_lease;
+}
+
 extern struct cached_fids *init_cached_dirs(void);
 extern void free_cached_dirs(struct cached_fids *cfids);
 extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
index 5223edf6d11a..56c59b67ecc2 100644
--- a/fs/smb/client/dir.c
+++ b/fs/smb/client/dir.c
@@ -322,7 +322,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
 		list_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) {
 			if (parent_cfid->dentry == direntry->d_parent) {
 				cifs_dbg(FYI, "found a parent cached file handle\n");
-				if (parent_cfid->has_lease && parent_cfid->time) {
+				if (is_valid_cached_dir(parent_cfid)) {
 					lease_flags
 						|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
 					memcpy(fid->parent_lease_key,
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index fe453a4b3dc8..9c8b8bd20edd 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -2639,7 +2639,7 @@ cifs_dentry_needs_reval(struct dentry *dentry)
 		return true;
 
 	if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {
-		if (cfid->time && cifs_i->time > cfid->time) {
+		if (cifs_i->time > cfid->time) {
 			close_cached_dir(cfid);
 			return false;
 		}
-- 
2.50.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2025-10-02  3:40 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-19 15:24 [PATCH 1/6] smb: client: ensure open_cached_dir_by_dentry() only returns valid cfid Henrique Carvalho
2025-09-19 15:24 ` [PATCH 2/6] smb: client: short-circuit in open_cached_dir_by_dentry() if !dentry Henrique Carvalho
2025-09-19 16:15   ` Enzo Matsumiya
2025-09-19 15:24 ` [PATCH 3/6] smb: client: short-circuit negative lookups when parent dir is fully cached Henrique Carvalho
2025-09-19 18:54   ` Enzo Matsumiya
2025-09-19 20:49     ` Henrique Carvalho
2025-09-19 15:24 ` [PATCH 4/6] smb: client: update cfid->last_access_time in open_cached_dir_by_dentry() Henrique Carvalho
2025-09-19 15:24 ` [PATCH 5/6] smb: client: remove pointless cfid->has_lease check Henrique Carvalho
2025-09-19 18:55   ` Enzo Matsumiya
2025-10-02  3:39     ` Steve French
2025-09-19 15:24 ` [PATCH 6/6] smb: client: remove unused fid_lock Henrique Carvalho
2025-09-19 18:56   ` Enzo Matsumiya
2025-09-19 15:55 ` [PATCH 1/6] smb: client: ensure open_cached_dir_by_dentry() only returns valid cfid Enzo Matsumiya
2025-10-02  3:10   ` Steve French

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox