Skip to content

Commit

Permalink
smb3.1.1: fix posix mounts to older servers
Browse files Browse the repository at this point in the history
commit ddca5023091588eb303e3c0097d95c325992d05f upstream.

Some servers which implement the SMB3.1.1 POSIX extensions did not
set the file type in the mode in the infolevel 100 response.
With the recent changes for checking the file type via the mode field,
this can cause the root directory to be reported incorrectly and
mounts (e.g. to ksmbd) to fail.

Fixes: 6a832bc8bbb2 ("fs/smb/client: Implement new SMB3 POSIX type")
Cc: stable@vger.kernel.org
Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
Cc: Ralph Boehme <slow@samba.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Steve French authored and opsiff committed Dec 15, 2024
1 parent 2f59f2b commit dc0f863
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 5 deletions.
2 changes: 1 addition & 1 deletion fs/smb/client/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev);
umode_t wire_mode_to_posix(u32 wire);
umode_t wire_mode_to_posix(u32 wire, bool is_dir);

#ifdef CONFIG_CIFS_DFS_UPCALL
static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
Expand Down
11 changes: 8 additions & 3 deletions fs/smb/client/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,13 +731,17 @@ static u32 wire_filetype_to_posix(u32 wire_type)
return posix_filetypes[wire_type];
}

umode_t wire_mode_to_posix(u32 wire)
umode_t wire_mode_to_posix(u32 wire, bool is_dir)
{
u32 wire_type;
u32 mode;

wire_type = (wire & POSIX_FILETYPE_MASK) >> POSIX_FILETYPE_SHIFT;
mode = (wire_perms_to_posix(wire) | wire_filetype_to_posix(wire_type));
/* older servers do not set POSIX file type in the mode field in the response */
if ((wire_type == 0) && is_dir)
mode = wire_perms_to_posix(wire) | S_IFDIR;
else
mode = (wire_perms_to_posix(wire) | wire_filetype_to_posix(wire_type));
return (umode_t)mode;
}

Expand Down Expand Up @@ -777,7 +781,8 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr,
fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
fattr->cf_createtime = le64_to_cpu(info->CreationTime);
fattr->cf_nlink = le32_to_cpu(info->HardLinks);
fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode));
fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode),
fattr->cf_cifsattrs & ATTR_DIRECTORY);

if (cifs_open_data_reparse(data) &&
cifs_reparse_point_to_fattr(cifs_sb, fattr, data))
Expand Down
3 changes: 2 additions & 1 deletion fs/smb/client/readdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info,
fattr->cf_cifstag = le32_to_cpu(info->ReparseTag);

/* The Mode field in the response can now include the file type as well */
fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode));
fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode),
fattr->cf_cifsattrs & ATTR_DIRECTORY);
fattr->cf_dtype = S_DT(le32_to_cpu(info->Mode));

switch (fattr->cf_mode & S_IFMT) {
Expand Down

0 comments on commit dc0f863

Please sign in to comment.