mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
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>
This commit is contained in:
parent
63eb8bd6c8
commit
a365f2c049
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -73,6 +73,12 @@ struct cached_fids {
|
|||
/* Module-wide directory cache accounting (defined in cifsfs.c) */
|
||||
extern atomic64_t cifs_dircache_bytes_used; /* bytes across all mounts */
|
||||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -2704,7 +2704,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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user