mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-28 21:33:52 +00:00
cifs: Parse owner/group for stat in smb311 posix extensions
stat was returning default owner and group (unlike readdir) for SMB3.1.1 POSIX extensions Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Paulo Alcantara (SUSE) <pc@cjr.nz> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
83fb8abec2
commit
64ce47cb1b
3 changed files with 59 additions and 8 deletions
|
@ -632,6 +632,8 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
|
||||||
|
|
||||||
/* Fill a cifs_fattr struct with info from POSIX info struct */
|
/* Fill a cifs_fattr struct with info from POSIX info struct */
|
||||||
static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data,
|
static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_open_info_data *data,
|
||||||
|
struct cifs_sid *owner,
|
||||||
|
struct cifs_sid *group,
|
||||||
struct super_block *sb, bool adjust_tz, bool symlink)
|
struct super_block *sb, bool adjust_tz, bool symlink)
|
||||||
{
|
{
|
||||||
struct smb311_posix_qinfo *info = &data->posix_fi;
|
struct smb311_posix_qinfo *info = &data->posix_fi;
|
||||||
|
@ -680,8 +682,8 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, struct cifs_ope
|
||||||
}
|
}
|
||||||
/* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */
|
/* else if reparse point ... TODO: add support for FIFO and blk dev; special file types */
|
||||||
|
|
||||||
fattr->cf_uid = cifs_sb->ctx->linux_uid; /* TODO: map uid and gid from SID */
|
sid_to_id(cifs_sb, owner, fattr, SIDOWNER);
|
||||||
fattr->cf_gid = cifs_sb->ctx->linux_gid;
|
sid_to_id(cifs_sb, group, fattr, SIDGROUP);
|
||||||
|
|
||||||
cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
|
cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
|
||||||
fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
|
fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
|
||||||
|
@ -1175,6 +1177,7 @@ smb311_posix_get_inode_info(struct inode **inode,
|
||||||
struct cifs_fattr fattr = {0};
|
struct cifs_fattr fattr = {0};
|
||||||
bool symlink = false;
|
bool symlink = false;
|
||||||
struct cifs_open_info_data data = {};
|
struct cifs_open_info_data data = {};
|
||||||
|
struct cifs_sid owner, group;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int tmprc = 0;
|
int tmprc = 0;
|
||||||
|
|
||||||
|
@ -1192,7 +1195,8 @@ smb311_posix_get_inode_info(struct inode **inode,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, full_path, &data, &adjust_tz,
|
rc = smb311_posix_query_path_info(xid, tcon, cifs_sb, full_path, &data,
|
||||||
|
&owner, &group, &adjust_tz,
|
||||||
&symlink);
|
&symlink);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1201,7 +1205,8 @@ smb311_posix_get_inode_info(struct inode **inode,
|
||||||
|
|
||||||
switch (rc) {
|
switch (rc) {
|
||||||
case 0:
|
case 0:
|
||||||
smb311_posix_info_to_fattr(&fattr, &data, sb, adjust_tz, symlink);
|
smb311_posix_info_to_fattr(&fattr, &data, &owner, &group,
|
||||||
|
sb, adjust_tz, symlink);
|
||||||
break;
|
break;
|
||||||
case -EREMOTE:
|
case -EREMOTE:
|
||||||
/* DFS link, no metadata available on this server */
|
/* DFS link, no metadata available on this server */
|
||||||
|
|
|
@ -431,6 +431,21 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
&rsp_iov[1], sizeof(idata->posix_fi) /* add SIDs */,
|
&rsp_iov[1], sizeof(idata->posix_fi) /* add SIDs */,
|
||||||
(char *)&idata->posix_fi);
|
(char *)&idata->posix_fi);
|
||||||
}
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
unsigned int length = le32_to_cpu(qi_rsp->OutputBufferLength);
|
||||||
|
|
||||||
|
if (length > sizeof(idata->posix_fi)) {
|
||||||
|
char *base = (char *)rsp_iov[1].iov_base +
|
||||||
|
le16_to_cpu(qi_rsp->OutputBufferOffset) +
|
||||||
|
sizeof(idata->posix_fi);
|
||||||
|
*extbuflen = length - sizeof(idata->posix_fi);
|
||||||
|
*extbuf = kmemdup(base, *extbuflen, GFP_KERNEL);
|
||||||
|
if (!*extbuf)
|
||||||
|
rc = -ENOMEM;
|
||||||
|
} else {
|
||||||
|
rc = -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (rqst[1].rq_iov)
|
if (rqst[1].rq_iov)
|
||||||
SMB2_query_info_free(&rqst[1]);
|
SMB2_query_info_free(&rqst[1]);
|
||||||
if (rqst[2].rq_iov)
|
if (rqst[2].rq_iov)
|
||||||
|
@ -569,13 +584,20 @@ int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
|
||||||
int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||||
struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse)
|
struct cifs_open_info_data *data,
|
||||||
|
struct cifs_sid *owner,
|
||||||
|
struct cifs_sid *group,
|
||||||
|
bool *adjust_tz, bool *reparse)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
__u32 create_options = 0;
|
__u32 create_options = 0;
|
||||||
struct cifsFileInfo *cfile;
|
struct cifsFileInfo *cfile;
|
||||||
struct kvec err_iov[3] = {};
|
struct kvec err_iov[3] = {};
|
||||||
int err_buftype[3] = {};
|
int err_buftype[3] = {};
|
||||||
|
__u8 *sidsbuf = NULL;
|
||||||
|
__u8 *sidsbuf_end = NULL;
|
||||||
|
size_t sidsbuflen = 0;
|
||||||
|
size_t owner_len, group_len;
|
||||||
|
|
||||||
*adjust_tz = false;
|
*adjust_tz = false;
|
||||||
*reparse = false;
|
*reparse = false;
|
||||||
|
@ -590,7 +612,7 @@ int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
cifs_get_readable_path(tcon, full_path, &cfile);
|
cifs_get_readable_path(tcon, full_path, &cfile);
|
||||||
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
|
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES, FILE_OPEN,
|
||||||
create_options, ACL_NO_MODE, data, SMB2_OP_POSIX_QUERY_INFO, cfile,
|
create_options, ACL_NO_MODE, data, SMB2_OP_POSIX_QUERY_INFO, cfile,
|
||||||
NULL, NULL, err_iov, err_buftype);
|
&sidsbuf, &sidsbuflen, err_iov, err_buftype);
|
||||||
if (rc == -EOPNOTSUPP) {
|
if (rc == -EOPNOTSUPP) {
|
||||||
/* BB TODO: When support for special files added to Samba re-verify this path */
|
/* BB TODO: When support for special files added to Samba re-verify this path */
|
||||||
if (err_iov[0].iov_base && err_buftype[0] != CIFS_NO_BUFFER &&
|
if (err_iov[0].iov_base && err_buftype[0] != CIFS_NO_BUFFER &&
|
||||||
|
@ -607,10 +629,31 @@ int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
cifs_get_readable_path(tcon, full_path, &cfile);
|
cifs_get_readable_path(tcon, full_path, &cfile);
|
||||||
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES,
|
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, FILE_READ_ATTRIBUTES,
|
||||||
FILE_OPEN, create_options, ACL_NO_MODE, data,
|
FILE_OPEN, create_options, ACL_NO_MODE, data,
|
||||||
SMB2_OP_POSIX_QUERY_INFO, cfile, NULL, NULL, NULL, NULL);
|
SMB2_OP_POSIX_QUERY_INFO, cfile,
|
||||||
|
&sidsbuf, &sidsbuflen, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == 0) {
|
||||||
|
sidsbuf_end = sidsbuf + sidsbuflen;
|
||||||
|
|
||||||
|
owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end);
|
||||||
|
if (owner_len == -1) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
memcpy(owner, sidsbuf, owner_len);
|
||||||
|
|
||||||
|
group_len = posix_info_sid_size(
|
||||||
|
sidsbuf + owner_len, sidsbuf_end);
|
||||||
|
if (group_len == -1) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
memcpy(group, sidsbuf + owner_len, group_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
kfree(sidsbuf);
|
||||||
free_rsp_buf(err_buftype[0], err_iov[0].iov_base);
|
free_rsp_buf(err_buftype[0], err_iov[0].iov_base);
|
||||||
free_rsp_buf(err_buftype[1], err_iov[1].iov_base);
|
free_rsp_buf(err_buftype[1], err_iov[1].iov_base);
|
||||||
free_rsp_buf(err_buftype[2], err_iov[2].iov_base);
|
free_rsp_buf(err_buftype[2], err_iov[2].iov_base);
|
||||||
|
|
|
@ -277,7 +277,10 @@ extern int smb2_query_info_compound(const unsigned int xid,
|
||||||
/* query path info from the server using SMB311 POSIX extensions*/
|
/* query path info from the server using SMB311 POSIX extensions*/
|
||||||
int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
int smb311_posix_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
struct cifs_sb_info *cifs_sb, const char *full_path,
|
struct cifs_sb_info *cifs_sb, const char *full_path,
|
||||||
struct cifs_open_info_data *data, bool *adjust_tz, bool *reparse);
|
struct cifs_open_info_data *data,
|
||||||
|
struct cifs_sid *owner,
|
||||||
|
struct cifs_sid *group,
|
||||||
|
bool *adjust_tz, bool *reparse);
|
||||||
int posix_info_parse(const void *beg, const void *end,
|
int posix_info_parse(const void *beg, const void *end,
|
||||||
struct smb2_posix_info_parsed *out);
|
struct smb2_posix_info_parsed *out);
|
||||||
int posix_info_sid_size(const void *beg, const void *end);
|
int posix_info_sid_size(const void *beg, const void *end);
|
||||||
|
|
Loading…
Reference in a new issue