Skip to content

Commit

Permalink
smb3: Fix root directory when server returns inode number of zero
Browse files Browse the repository at this point in the history
Some servers return inode number zero for the root directory, which
causes ls to display incorrect data (missing "." and "..").

If the server returns zero for the inode number of the root directory,
fake an inode number for it.

Signed-off-by: Steve French <smfrench@gmail.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
CC: Stable <stable@vger.kernel.org>
  • Loading branch information
Steve French authored and Steve French committed Apr 2, 2018
1 parent 6c4ba31 commit 7ea884c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
1 change: 1 addition & 0 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -1470,6 +1470,7 @@ struct dfs_info3_param {
#define CIFS_FATTR_NEED_REVAL 0x4
#define CIFS_FATTR_INO_COLLISION 0x8
#define CIFS_FATTR_UNKNOWN_NLINK 0x10
#define CIFS_FATTR_FAKE_ROOT_INO 0x20

struct cifs_fattr {
u32 cf_flags;
Expand Down
33 changes: 33 additions & 0 deletions fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,18 @@ cifs_get_file_info(struct file *filp)
return rc;
}

/* Simple function to return a 64 bit hash of string. Rarely called */
static __u64 simple_hashstr(const char *str)
{
const __u64 hash_mult = 1125899906842597L; /* a big enough prime */
__u64 hash = 0;

while (*str)
hash = (hash + (__u64) *str++) * hash_mult;

return hash;
}

int
cifs_get_inode_info(struct inode **inode, const char *full_path,
FILE_ALL_INFO *data, struct super_block *sb, int xid,
Expand Down Expand Up @@ -816,6 +828,14 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
tmprc);
fattr.cf_uniqueid = iunique(sb, ROOT_I);
cifs_autodisable_serverino(cifs_sb);
} else if ((fattr.cf_uniqueid == 0) &&
strlen(full_path) == 0) {
/* some servers ret bad root ino ie 0 */
cifs_dbg(FYI, "Invalid (0) inodenum\n");
fattr.cf_flags |=
CIFS_FATTR_FAKE_ROOT_INO;
fattr.cf_uniqueid =
simple_hashstr(tcon->treeName);
}
}
} else
Expand All @@ -832,6 +852,16 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
&fattr.cf_uniqueid, data);
if (tmprc)
fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
else if ((fattr.cf_uniqueid == 0) &&
strlen(full_path) == 0) {
/*
* Reuse existing root inode num since
* inum zero for root causes ls of . and .. to
* not be returned
*/
cifs_dbg(FYI, "Srv ret 0 inode num for root\n");
fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
}
} else
fattr.cf_uniqueid = CIFS_I(*inode)->uniqueid;
}
Expand Down Expand Up @@ -893,6 +923,9 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
}

cgii_exit:
if ((*inode) && ((*inode)->i_ino == 0))
cifs_dbg(FYI, "inode number of zero returned\n");

kfree(buf);
cifs_put_tlink(tlink);
return rc;
Expand Down

0 comments on commit 7ea884c

Please sign in to comment.