smb: client: parse uid, gid, mode and dev from WSL reparse points
[ Upstream commit 78e26bec4d6d3aef04276e28bed48a45fd00e116 ] Parse the extended attributes from WSL reparse points to correctly report uid, gid mode and dev from ther instantiated inodes. Signed-off-by: Paulo Alcantara <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
7449d736bb
commit
97db416045
@ -759,6 +759,8 @@ static void cifs_open_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->NumberOfLinks);
|
||||
fattr->cf_uid = cifs_sb->ctx->linux_uid;
|
||||
fattr->cf_gid = cifs_sb->ctx->linux_gid;
|
||||
|
||||
fattr->cf_mode = cifs_sb->ctx->file_mode;
|
||||
if (cifs_open_data_reparse(data) &&
|
||||
@ -801,9 +803,6 @@ out_reparse:
|
||||
fattr->cf_symlink_target = data->symlink_target;
|
||||
data->symlink_target = NULL;
|
||||
}
|
||||
|
||||
fattr->cf_uid = cifs_sb->ctx->linux_uid;
|
||||
fattr->cf_gid = cifs_sb->ctx->linux_gid;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -125,6 +125,8 @@ retry:
|
||||
if (likely(reparse_inode_match(inode, fattr))) {
|
||||
fattr->cf_mode = inode->i_mode;
|
||||
fattr->cf_rdev = inode->i_rdev;
|
||||
fattr->cf_uid = inode->i_uid;
|
||||
fattr->cf_gid = inode->i_gid;
|
||||
fattr->cf_eof = CIFS_I(inode)->server_eof;
|
||||
fattr->cf_symlink_target = NULL;
|
||||
} else {
|
||||
|
@ -258,7 +258,9 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
|
||||
{
|
||||
struct cifs_open_info_data data;
|
||||
struct reparse_data_buffer buf;
|
||||
struct smb2_create_ea_ctx *cc;
|
||||
struct inode *new;
|
||||
unsigned int len;
|
||||
struct kvec reparse_iov, xattr_iov;
|
||||
int rc;
|
||||
|
||||
@ -275,6 +277,11 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
|
||||
.reparse = { .tag = le32_to_cpu(buf.ReparseTag), .buf = &buf, },
|
||||
};
|
||||
|
||||
cc = xattr_iov.iov_base;
|
||||
len = le32_to_cpu(cc->ctx.DataLength);
|
||||
memcpy(data.wsl.eas, &cc->ea, len);
|
||||
data.wsl.eas_len = len;
|
||||
|
||||
new = smb2_get_reparse_inode(&data, inode->i_sb,
|
||||
xid, tcon, full_path,
|
||||
&reparse_iov, &xattr_iov);
|
||||
@ -408,6 +415,62 @@ int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
|
||||
return parse_reparse_point(buf, plen, cifs_sb, true, data);
|
||||
}
|
||||
|
||||
static void wsl_to_fattr(struct cifs_open_info_data *data,
|
||||
struct cifs_sb_info *cifs_sb,
|
||||
u32 tag, struct cifs_fattr *fattr)
|
||||
{
|
||||
struct smb2_file_full_ea_info *ea;
|
||||
u32 next = 0;
|
||||
|
||||
switch (tag) {
|
||||
case IO_REPARSE_TAG_LX_SYMLINK:
|
||||
fattr->cf_mode |= S_IFLNK;
|
||||
break;
|
||||
case IO_REPARSE_TAG_LX_FIFO:
|
||||
fattr->cf_mode |= S_IFIFO;
|
||||
break;
|
||||
case IO_REPARSE_TAG_AF_UNIX:
|
||||
fattr->cf_mode |= S_IFSOCK;
|
||||
break;
|
||||
case IO_REPARSE_TAG_LX_CHR:
|
||||
fattr->cf_mode |= S_IFCHR;
|
||||
break;
|
||||
case IO_REPARSE_TAG_LX_BLK:
|
||||
fattr->cf_mode |= S_IFBLK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!data->wsl.eas_len)
|
||||
goto out;
|
||||
|
||||
ea = (struct smb2_file_full_ea_info *)data->wsl.eas;
|
||||
do {
|
||||
const char *name;
|
||||
void *v;
|
||||
u8 nlen;
|
||||
|
||||
ea = (void *)((u8 *)ea + next);
|
||||
next = le32_to_cpu(ea->next_entry_offset);
|
||||
if (!le16_to_cpu(ea->ea_value_length))
|
||||
continue;
|
||||
|
||||
name = ea->ea_data;
|
||||
nlen = ea->ea_name_length;
|
||||
v = (void *)((u8 *)ea->ea_data + ea->ea_name_length + 1);
|
||||
|
||||
if (!strncmp(name, SMB2_WSL_XATTR_UID, nlen))
|
||||
fattr->cf_uid = wsl_make_kuid(cifs_sb, v);
|
||||
else if (!strncmp(name, SMB2_WSL_XATTR_GID, nlen))
|
||||
fattr->cf_gid = wsl_make_kgid(cifs_sb, v);
|
||||
else if (!strncmp(name, SMB2_WSL_XATTR_MODE, nlen))
|
||||
fattr->cf_mode = (umode_t)le32_to_cpu(*(__le32 *)v);
|
||||
else if (!strncmp(name, SMB2_WSL_XATTR_DEV, nlen))
|
||||
fattr->cf_rdev = wsl_mkdev(v);
|
||||
} while (next);
|
||||
out:
|
||||
fattr->cf_dtype = S_DT(fattr->cf_mode);
|
||||
}
|
||||
|
||||
bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
|
||||
struct cifs_fattr *fattr,
|
||||
struct cifs_open_info_data *data)
|
||||
@ -448,24 +511,11 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
|
||||
|
||||
switch (tag) {
|
||||
case IO_REPARSE_TAG_LX_SYMLINK:
|
||||
fattr->cf_mode |= S_IFLNK;
|
||||
fattr->cf_dtype = DT_LNK;
|
||||
break;
|
||||
case IO_REPARSE_TAG_LX_FIFO:
|
||||
fattr->cf_mode |= S_IFIFO;
|
||||
fattr->cf_dtype = DT_FIFO;
|
||||
break;
|
||||
case IO_REPARSE_TAG_AF_UNIX:
|
||||
fattr->cf_mode |= S_IFSOCK;
|
||||
fattr->cf_dtype = DT_SOCK;
|
||||
break;
|
||||
case IO_REPARSE_TAG_LX_CHR:
|
||||
fattr->cf_mode |= S_IFCHR;
|
||||
fattr->cf_dtype = DT_CHR;
|
||||
break;
|
||||
case IO_REPARSE_TAG_LX_BLK:
|
||||
fattr->cf_mode |= S_IFBLK;
|
||||
fattr->cf_dtype = DT_BLK;
|
||||
wsl_to_fattr(data, cifs_sb, tag, fattr);
|
||||
break;
|
||||
case 0: /* SMB1 symlink */
|
||||
case IO_REPARSE_TAG_SYMLINK:
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/uidgid.h>
|
||||
#include "fs_context.h"
|
||||
#include "cifsglob.h"
|
||||
|
||||
static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf)
|
||||
@ -17,6 +19,33 @@ static inline dev_t reparse_nfs_mkdev(struct reparse_posix_data *buf)
|
||||
return MKDEV(v >> 32, v & 0xffffffff);
|
||||
}
|
||||
|
||||
static inline dev_t wsl_mkdev(void *ptr)
|
||||
{
|
||||
u64 v = le64_to_cpu(*(__le64 *)ptr);
|
||||
|
||||
return MKDEV(v & 0xffffffff, v >> 32);
|
||||
}
|
||||
|
||||
static inline kuid_t wsl_make_kuid(struct cifs_sb_info *cifs_sb,
|
||||
void *ptr)
|
||||
{
|
||||
u32 uid = le32_to_cpu(*(__le32 *)ptr);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
|
||||
return cifs_sb->ctx->linux_uid;
|
||||
return make_kuid(current_user_ns(), uid);
|
||||
}
|
||||
|
||||
static inline kgid_t wsl_make_kgid(struct cifs_sb_info *cifs_sb,
|
||||
void *ptr)
|
||||
{
|
||||
u32 gid = le32_to_cpu(*(__le32 *)ptr);
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
|
||||
return cifs_sb->ctx->linux_gid;
|
||||
return make_kgid(current_user_ns(), gid);
|
||||
}
|
||||
|
||||
static inline u64 reparse_mode_nfs_type(mode_t mode)
|
||||
{
|
||||
switch (mode & S_IFMT) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user