Skip to content

Commit a365f2c

Browse files
committed
smb: client: ensure open_cached_dir_by_dentry() only returns valid cfid
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> Reviwed-by: Enzo Matsumiya <ematsumiya@suse.de> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 63eb8bd commit a365f2c

4 files changed

Lines changed: 13 additions & 6 deletions

File tree

fs/smb/client/cached_dir.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,8 @@ static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
3636
* fully cached or it may be in the process of
3737
* being deleted due to a lease break.
3838
*/
39-
if (!cfid->time || !cfid->has_lease) {
39+
if (!is_valid_cached_dir(cfid))
4040
return NULL;
41-
}
4241
kref_get(&cfid->refcount);
4342
return cfid;
4443
}
@@ -194,7 +193,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
194193
* Otherwise, it is either a new entry or laundromat worker removed it
195194
* from @cfids->entries. Caller will put last reference if the latter.
196195
*/
197-
if (cfid->has_lease && cfid->time) {
196+
if (is_valid_cached_dir(cfid)) {
198197
cfid->last_access_time = jiffies;
199198
spin_unlock(&cfids->cfid_list_lock);
200199
*ret_cfid = cfid;
@@ -233,7 +232,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
233232
list_for_each_entry(parent_cfid, &cfids->entries, entry) {
234233
if (parent_cfid->dentry == dentry->d_parent) {
235234
cifs_dbg(FYI, "found a parent cached file handle\n");
236-
if (parent_cfid->has_lease && parent_cfid->time) {
235+
if (is_valid_cached_dir(parent_cfid)) {
237236
lease_flags
238237
|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
239238
memcpy(pfid->parent_lease_key,
@@ -420,6 +419,8 @@ int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
420419
spin_lock(&cfids->cfid_list_lock);
421420
list_for_each_entry(cfid, &cfids->entries, entry) {
422421
if (dentry && cfid->dentry == dentry) {
422+
if (!is_valid_cached_dir(cfid))
423+
break;
423424
cifs_dbg(FYI, "found a cached file handle by dentry\n");
424425
kref_get(&cfid->refcount);
425426
*ret_cfid = cfid;

fs/smb/client/cached_dir.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ struct cached_fids {
7373
/* Module-wide directory cache accounting (defined in cifsfs.c) */
7474
extern atomic64_t cifs_dircache_bytes_used; /* bytes across all mounts */
7575

76+
static inline bool
77+
is_valid_cached_dir(struct cached_fid *cfid)
78+
{
79+
return cfid->time && cfid->has_lease;
80+
}
81+
7682
extern struct cached_fids *init_cached_dirs(void);
7783
extern void free_cached_dirs(struct cached_fids *cfids);
7884
extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,

fs/smb/client/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
322322
list_for_each_entry(parent_cfid, &tcon->cfids->entries, entry) {
323323
if (parent_cfid->dentry == direntry->d_parent) {
324324
cifs_dbg(FYI, "found a parent cached file handle\n");
325-
if (parent_cfid->has_lease && parent_cfid->time) {
325+
if (is_valid_cached_dir(parent_cfid)) {
326326
lease_flags
327327
|= SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE;
328328
memcpy(fid->parent_lease_key,

fs/smb/client/inode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2704,7 +2704,7 @@ cifs_dentry_needs_reval(struct dentry *dentry)
27042704
return true;
27052705

27062706
if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {
2707-
if (cfid->time && cifs_i->time > cfid->time) {
2707+
if (cifs_i->time > cfid->time) {
27082708
close_cached_dir(cfid);
27092709
return false;
27102710
}

0 commit comments

Comments
 (0)