Skip to content

Commit 858e748

Browse files
Paulo Alcantarasmfrench
authored andcommitted
smb: client: parse owner/group when creating reparse points
Parse owner/group when creating special files and symlinks under SMB3.1.1 POSIX mounts. Move the parsing of owner/group to smb2_compound_op() so we don't have to duplicate it in both smb2_get_reparse_inode() and smb311_posix_query_path_info(). Signed-off-by: Paulo Alcantara <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 76025cc commit 858e748

File tree

4 files changed

+71
-89
lines changed

4 files changed

+71
-89
lines changed

fs/smb/client/cifsglob.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ struct cifs_open_info_data {
204204
};
205205
} reparse;
206206
char *symlink_target;
207+
struct cifs_sid posix_owner;
208+
struct cifs_sid posix_group;
207209
union {
208210
struct smb2_file_all_info fi;
209211
struct smb311_posix_qinfo posix_fi;

fs/smb/client/inode.c

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,6 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
665665
/* Fill a cifs_fattr struct with info from POSIX info struct */
666666
static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr,
667667
struct cifs_open_info_data *data,
668-
struct cifs_sid *owner,
669-
struct cifs_sid *group,
670668
struct super_block *sb)
671669
{
672670
struct smb311_posix_qinfo *info = &data->posix_fi;
@@ -722,8 +720,8 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr,
722720
fattr->cf_symlink_target = data->symlink_target;
723721
data->symlink_target = NULL;
724722
}
725-
sid_to_id(cifs_sb, owner, fattr, SIDOWNER);
726-
sid_to_id(cifs_sb, group, fattr, SIDGROUP);
723+
sid_to_id(cifs_sb, &data->posix_owner, fattr, SIDOWNER);
724+
sid_to_id(cifs_sb, &data->posix_group, fattr, SIDGROUP);
727725

728726
cifs_dbg(FYI, "POSIX query info: mode 0x%x uniqueid 0x%llx nlink %d\n",
729727
fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink);
@@ -1070,9 +1068,7 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
10701068
const unsigned int xid,
10711069
struct cifs_tcon *tcon,
10721070
const char *full_path,
1073-
struct cifs_fattr *fattr,
1074-
struct cifs_sid *owner,
1075-
struct cifs_sid *group)
1071+
struct cifs_fattr *fattr)
10761072
{
10771073
struct TCP_Server_Info *server = tcon->ses->server;
10781074
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
@@ -1117,7 +1113,7 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
11171113
}
11181114

11191115
if (tcon->posix_extensions)
1120-
smb311_posix_info_to_fattr(fattr, data, owner, group, sb);
1116+
smb311_posix_info_to_fattr(fattr, data, sb);
11211117
else
11221118
cifs_open_info_to_fattr(fattr, data, sb);
11231119
out:
@@ -1171,8 +1167,7 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
11711167
*/
11721168
if (cifs_open_data_reparse(data)) {
11731169
rc = reparse_info_to_fattr(data, sb, xid, tcon,
1174-
full_path, fattr,
1175-
NULL, NULL);
1170+
full_path, fattr);
11761171
} else {
11771172
cifs_open_info_to_fattr(fattr, data, sb);
11781173
}
@@ -1320,7 +1315,6 @@ static int smb311_posix_get_fattr(struct cifs_open_info_data *data,
13201315
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
13211316
struct cifs_tcon *tcon;
13221317
struct tcon_link *tlink;
1323-
struct cifs_sid owner, group;
13241318
int tmprc;
13251319
int rc = 0;
13261320

@@ -1334,8 +1328,7 @@ static int smb311_posix_get_fattr(struct cifs_open_info_data *data,
13341328
*/
13351329
if (!data) {
13361330
rc = smb311_posix_query_path_info(xid, tcon, cifs_sb,
1337-
full_path, &tmp_data,
1338-
&owner, &group);
1331+
full_path, &tmp_data);
13391332
data = &tmp_data;
13401333
}
13411334

@@ -1347,11 +1340,9 @@ static int smb311_posix_get_fattr(struct cifs_open_info_data *data,
13471340
case 0:
13481341
if (cifs_open_data_reparse(data)) {
13491342
rc = reparse_info_to_fattr(data, sb, xid, tcon,
1350-
full_path, fattr,
1351-
&owner, &group);
1343+
full_path, fattr);
13521344
} else {
1353-
smb311_posix_info_to_fattr(fattr, data,
1354-
&owner, &group, sb);
1345+
smb311_posix_info_to_fattr(fattr, data, sb);
13551346
}
13561347
break;
13571348
case -EREMOTE:

fs/smb/client/smb2inode.c

Lines changed: 60 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,35 @@ static inline __u32 file_create_options(struct dentry *dentry)
5656
return 0;
5757
}
5858

59+
/* Parse owner and group from SMB3.1.1 POSIX query info */
60+
static int parse_posix_sids(struct cifs_open_info_data *data,
61+
struct kvec *rsp_iov)
62+
{
63+
struct smb2_query_info_rsp *qi = rsp_iov->iov_base;
64+
unsigned int out_len = le32_to_cpu(qi->OutputBufferLength);
65+
unsigned int qi_len = sizeof(data->posix_fi);
66+
int owner_len, group_len;
67+
u8 *sidsbuf, *sidsbuf_end;
68+
69+
if (out_len <= qi_len)
70+
return -EINVAL;
71+
72+
sidsbuf = (u8 *)qi + le16_to_cpu(qi->OutputBufferOffset) + qi_len;
73+
sidsbuf_end = sidsbuf + out_len - qi_len;
74+
75+
owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end);
76+
if (owner_len == -1)
77+
return -EINVAL;
78+
79+
memcpy(&data->posix_owner, sidsbuf, owner_len);
80+
group_len = posix_info_sid_size(sidsbuf + owner_len, sidsbuf_end);
81+
if (group_len == -1)
82+
return -EINVAL;
83+
84+
memcpy(&data->posix_group, sidsbuf + owner_len, group_len);
85+
return 0;
86+
}
87+
5988
/*
6089
* note: If cfile is passed, the reference to it is dropped here.
6190
* So make sure that you do not reuse cfile after return from this func.
@@ -69,7 +98,6 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
6998
__u32 desired_access, __u32 create_disposition,
7099
__u32 create_options, umode_t mode, struct kvec *in_iov,
71100
int *cmds, int num_cmds, struct cifsFileInfo *cfile,
72-
__u8 **extbuf, size_t *extbuflen,
73101
struct kvec *out_iov, int *out_buftype)
74102
{
75103

@@ -494,21 +522,9 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
494522
&rsp_iov[i + 1], sizeof(idata->posix_fi) /* add SIDs */,
495523
(char *)&idata->posix_fi);
496524
}
497-
if (rc == 0) {
498-
unsigned int length = le32_to_cpu(qi_rsp->OutputBufferLength);
499-
500-
if (length > sizeof(idata->posix_fi)) {
501-
char *base = (char *)rsp_iov[i + 1].iov_base +
502-
le16_to_cpu(qi_rsp->OutputBufferOffset) +
503-
sizeof(idata->posix_fi);
504-
*extbuflen = length - sizeof(idata->posix_fi);
505-
*extbuf = kmemdup(base, *extbuflen, GFP_KERNEL);
506-
if (!*extbuf)
507-
rc = -ENOMEM;
508-
} else {
509-
rc = -EINVAL;
510-
}
511-
}
525+
if (rc == 0)
526+
rc = parse_posix_sids(idata, &rsp_iov[i + 1]);
527+
512528
SMB2_query_info_free(&rqst[num_rqst++]);
513529
if (rc)
514530
trace_smb3_posix_query_info_compound_err(xid, ses->Suid,
@@ -693,9 +709,8 @@ int smb2_query_path_info(const unsigned int xid,
693709
cifs_get_readable_path(tcon, full_path, &cfile);
694710
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
695711
FILE_READ_ATTRIBUTES, FILE_OPEN,
696-
create_options, ACL_NO_MODE,
697-
in_iov, cmds, 1, cfile,
698-
NULL, NULL, out_iov, out_buftype);
712+
create_options, ACL_NO_MODE, in_iov,
713+
cmds, 1, cfile, out_iov, out_buftype);
699714
hdr = out_iov[0].iov_base;
700715
/*
701716
* If first iov is unset, then SMB session was dropped or we've got a
@@ -722,8 +737,8 @@ int smb2_query_path_info(const unsigned int xid,
722737
cifs_get_readable_path(tcon, full_path, &cfile);
723738
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
724739
FILE_READ_ATTRIBUTES, FILE_OPEN,
725-
create_options, ACL_NO_MODE, in_iov, cmds,
726-
num_cmds, cfile, NULL, NULL, NULL, NULL);
740+
create_options, ACL_NO_MODE, in_iov,
741+
cmds, num_cmds, cfile, NULL, NULL);
727742
break;
728743
case -EREMOTE:
729744
break;
@@ -750,19 +765,13 @@ int smb311_posix_query_path_info(const unsigned int xid,
750765
struct cifs_tcon *tcon,
751766
struct cifs_sb_info *cifs_sb,
752767
const char *full_path,
753-
struct cifs_open_info_data *data,
754-
struct cifs_sid *owner,
755-
struct cifs_sid *group)
768+
struct cifs_open_info_data *data)
756769
{
757770
int rc;
758771
__u32 create_options = 0;
759772
struct cifsFileInfo *cfile;
760773
struct kvec in_iov[2], out_iov[3] = {};
761774
int out_buftype[3] = {};
762-
__u8 *sidsbuf = NULL;
763-
__u8 *sidsbuf_end = NULL;
764-
size_t sidsbuflen = 0;
765-
size_t owner_len, group_len;
766775
int cmds[2] = { SMB2_OP_POSIX_QUERY_INFO, };
767776
int i, num_cmds;
768777

@@ -782,8 +791,8 @@ int smb311_posix_query_path_info(const unsigned int xid,
782791
cifs_get_readable_path(tcon, full_path, &cfile);
783792
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
784793
FILE_READ_ATTRIBUTES, FILE_OPEN,
785-
create_options, ACL_NO_MODE, in_iov, cmds, 1,
786-
cfile, &sidsbuf, &sidsbuflen, out_iov, out_buftype);
794+
create_options, ACL_NO_MODE, in_iov,
795+
cmds, 1, cfile, out_iov, out_buftype);
787796
/*
788797
* If first iov is unset, then SMB session was dropped or we've got a
789798
* cached open file (@cfile).
@@ -810,32 +819,12 @@ int smb311_posix_query_path_info(const unsigned int xid,
810819
cifs_get_readable_path(tcon, full_path, &cfile);
811820
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
812821
FILE_READ_ATTRIBUTES, FILE_OPEN,
813-
create_options, ACL_NO_MODE, in_iov, cmds,
814-
num_cmds, cfile, &sidsbuf, &sidsbuflen, NULL, NULL);
822+
create_options, ACL_NO_MODE, in_iov,
823+
cmds, num_cmds, cfile, NULL, NULL);
815824
break;
816825
}
817826

818827
out:
819-
if (rc == 0) {
820-
sidsbuf_end = sidsbuf + sidsbuflen;
821-
822-
owner_len = posix_info_sid_size(sidsbuf, sidsbuf_end);
823-
if (owner_len == -1) {
824-
rc = -EINVAL;
825-
goto out;
826-
}
827-
memcpy(owner, sidsbuf, owner_len);
828-
829-
group_len = posix_info_sid_size(
830-
sidsbuf + owner_len, sidsbuf_end);
831-
if (group_len == -1) {
832-
rc = -EINVAL;
833-
goto out;
834-
}
835-
memcpy(group, sidsbuf + owner_len, group_len);
836-
}
837-
838-
kfree(sidsbuf);
839828
for (i = 0; i < ARRAY_SIZE(out_buftype); i++)
840829
free_rsp_buf(out_buftype[i], out_iov[i].iov_base);
841830
return rc;
@@ -848,9 +837,9 @@ smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
848837
{
849838
return smb2_compound_op(xid, tcon, cifs_sb, name,
850839
FILE_WRITE_ATTRIBUTES, FILE_CREATE,
851-
CREATE_NOT_FILE, mode, NULL,
852-
&(int){SMB2_OP_MKDIR}, 1,
853-
NULL, NULL, NULL, NULL, NULL);
840+
CREATE_NOT_FILE, mode,
841+
NULL, &(int){SMB2_OP_MKDIR}, 1,
842+
NULL, NULL, NULL);
854843
}
855844

856845
void
@@ -875,7 +864,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
875864
FILE_WRITE_ATTRIBUTES, FILE_CREATE,
876865
CREATE_NOT_FILE, ACL_NO_MODE, &in_iov,
877866
&(int){SMB2_OP_SET_INFO}, 1,
878-
cfile, NULL, NULL, NULL, NULL);
867+
cfile, NULL, NULL);
879868
if (tmprc == 0)
880869
cifs_i->cifsAttrs = dosattrs;
881870
}
@@ -887,8 +876,9 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
887876
drop_cached_dir_by_name(xid, tcon, name, cifs_sb);
888877
return smb2_compound_op(xid, tcon, cifs_sb, name,
889878
DELETE, FILE_OPEN, CREATE_NOT_FILE,
890-
ACL_NO_MODE, NULL, &(int){SMB2_OP_RMDIR}, 1,
891-
NULL, NULL, NULL, NULL, NULL);
879+
ACL_NO_MODE, NULL,
880+
&(int){SMB2_OP_RMDIR}, 1,
881+
NULL, NULL, NULL);
892882
}
893883

894884
int
@@ -897,8 +887,9 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
897887
{
898888
return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
899889
CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
900-
ACL_NO_MODE, NULL, &(int){SMB2_OP_DELETE}, 1,
901-
NULL, NULL, NULL, NULL, NULL);
890+
ACL_NO_MODE, NULL,
891+
&(int){SMB2_OP_DELETE}, 1,
892+
NULL, NULL, NULL);
902893
}
903894

904895
static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
@@ -919,8 +910,8 @@ static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
919910
in_iov.iov_base = smb2_to_name;
920911
in_iov.iov_len = 2 * UniStrnlen((wchar_t *)smb2_to_name, PATH_MAX);
921912
rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
922-
FILE_OPEN, create_options, ACL_NO_MODE, &in_iov,
923-
&command, 1, cfile, NULL, NULL, NULL, NULL);
913+
FILE_OPEN, create_options, ACL_NO_MODE,
914+
&in_iov, &command, 1, cfile, NULL, NULL);
924915
smb2_rename_path:
925916
kfree(smb2_to_name);
926917
return rc;
@@ -971,7 +962,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
971962
FILE_WRITE_DATA, FILE_OPEN,
972963
0, ACL_NO_MODE, &in_iov,
973964
&(int){SMB2_OP_SET_EOF}, 1,
974-
cfile, NULL, NULL, NULL, NULL);
965+
cfile, NULL, NULL);
975966
}
976967

977968
int
@@ -999,8 +990,8 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
999990
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
1000991
FILE_WRITE_ATTRIBUTES, FILE_OPEN,
1001992
0, ACL_NO_MODE, &in_iov,
1002-
&(int){SMB2_OP_SET_INFO}, 1, cfile,
1003-
NULL, NULL, NULL, NULL);
993+
&(int){SMB2_OP_SET_INFO}, 1,
994+
cfile, NULL, NULL);
1004995
cifs_put_tlink(tlink);
1005996
return rc;
1006997
}
@@ -1035,7 +1026,7 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
10351026
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
10361027
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
10371028
da, cd, co, ACL_NO_MODE, in_iov,
1038-
cmds, 2, cfile, NULL, NULL, NULL, NULL);
1029+
cmds, 2, cfile, NULL, NULL);
10391030
if (!rc) {
10401031
rc = smb311_posix_get_inode_info(&new, full_path,
10411032
data, sb, xid);
@@ -1045,7 +1036,7 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
10451036
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
10461037
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
10471038
da, cd, co, ACL_NO_MODE, in_iov,
1048-
cmds, 2, cfile, NULL, NULL, NULL, NULL);
1039+
cmds, 2, cfile, NULL, NULL);
10491040
if (!rc) {
10501041
rc = cifs_get_inode_info(&new, full_path,
10511042
data, sb, xid, NULL);
@@ -1072,8 +1063,8 @@ int smb2_query_reparse_point(const unsigned int xid,
10721063
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
10731064
FILE_READ_ATTRIBUTES, FILE_OPEN,
10741065
OPEN_REPARSE_POINT, ACL_NO_MODE, &in_iov,
1075-
&(int){SMB2_OP_GET_REPARSE}, 1, cfile,
1076-
NULL, NULL, NULL, NULL);
1066+
&(int){SMB2_OP_GET_REPARSE}, 1,
1067+
cfile, NULL, NULL);
10771068
if (rc)
10781069
goto out;
10791070

fs/smb/client/smb2proto.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,7 @@ int smb311_posix_query_path_info(const unsigned int xid,
299299
struct cifs_tcon *tcon,
300300
struct cifs_sb_info *cifs_sb,
301301
const char *full_path,
302-
struct cifs_open_info_data *data,
303-
struct cifs_sid *owner,
304-
struct cifs_sid *group);
302+
struct cifs_open_info_data *data);
305303
int posix_info_parse(const void *beg, const void *end,
306304
struct smb2_posix_info_parsed *out);
307305
int posix_info_sid_size(const void *beg, const void *end);

0 commit comments

Comments
 (0)