Skip to content

Commit 349e13a

Browse files
aaptelsmfrench
authored andcommitted
cifs: add smb2 POSIX info level
* add new info level and structs for SMB2 posix extension * add functions to parse and validate it Signed-off-by: Aurelien Aptel <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 2e8af97 commit 349e13a

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed

fs/cifs/cifspdu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,6 +1691,7 @@ struct smb_t2_rsp {
16911691
#define SMB_FIND_FILE_ID_FULL_DIR_INFO 0x105
16921692
#define SMB_FIND_FILE_ID_BOTH_DIR_INFO 0x106
16931693
#define SMB_FIND_FILE_UNIX 0x202
1694+
#define SMB_FIND_FILE_POSIX_INFO 0x064
16941695

16951696
typedef struct smb_com_transaction2_qpi_req {
16961697
struct smb_hdr hdr; /* wct = 14+ */

fs/cifs/smb2pdu.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4302,6 +4302,101 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
43024302
return rc;
43034303
}
43044304

4305+
static int posix_info_sid_size(const void *beg, const void *end)
4306+
{
4307+
size_t subauth;
4308+
int total;
4309+
4310+
if (beg + 1 > end)
4311+
return -1;
4312+
4313+
subauth = *(u8 *)(beg+1);
4314+
if (subauth < 1 || subauth > 15)
4315+
return -1;
4316+
4317+
total = 1 + 1 + 6 + 4*subauth;
4318+
if (beg + total > end)
4319+
return -1;
4320+
4321+
return total;
4322+
}
4323+
4324+
int posix_info_parse(const void *beg, const void *end,
4325+
struct smb2_posix_info_parsed *out)
4326+
4327+
{
4328+
int total_len = 0;
4329+
int sid_len;
4330+
int name_len;
4331+
const void *owner_sid;
4332+
const void *group_sid;
4333+
const void *name;
4334+
4335+
/* if no end bound given, assume payload to be correct */
4336+
if (!end) {
4337+
const struct smb2_posix_info *p = beg;
4338+
4339+
end = beg + le32_to_cpu(p->NextEntryOffset);
4340+
/* last element will have a 0 offset, pick a sensible bound */
4341+
if (end == beg)
4342+
end += 0xFFFF;
4343+
}
4344+
4345+
/* check base buf */
4346+
if (beg + sizeof(struct smb2_posix_info) > end)
4347+
return -1;
4348+
total_len = sizeof(struct smb2_posix_info);
4349+
4350+
/* check owner sid */
4351+
owner_sid = beg + total_len;
4352+
sid_len = posix_info_sid_size(owner_sid, end);
4353+
if (sid_len < 0)
4354+
return -1;
4355+
total_len += sid_len;
4356+
4357+
/* check group sid */
4358+
group_sid = beg + total_len;
4359+
sid_len = posix_info_sid_size(group_sid, end);
4360+
if (sid_len < 0)
4361+
return -1;
4362+
total_len += sid_len;
4363+
4364+
/* check name len */
4365+
if (beg + total_len + 4 > end)
4366+
return -1;
4367+
name_len = le32_to_cpu(*(__le32 *)(beg + total_len));
4368+
if (name_len < 1 || name_len > 0xFFFF)
4369+
return -1;
4370+
total_len += 4;
4371+
4372+
/* check name */
4373+
name = beg + total_len;
4374+
if (name + name_len > end)
4375+
return -1;
4376+
total_len += name_len;
4377+
4378+
if (out) {
4379+
out->base = beg;
4380+
out->size = total_len;
4381+
out->name_len = name_len;
4382+
out->name = name;
4383+
memcpy(&out->owner, owner_sid,
4384+
posix_info_sid_size(owner_sid, end));
4385+
memcpy(&out->group, group_sid,
4386+
posix_info_sid_size(group_sid, end));
4387+
}
4388+
return total_len;
4389+
}
4390+
4391+
static int posix_info_extra_size(const void *beg, const void *end)
4392+
{
4393+
int len = posix_info_parse(beg, end, NULL);
4394+
4395+
if (len < 0)
4396+
return -1;
4397+
return len - sizeof(struct smb2_posix_info);
4398+
}
4399+
43054400
static unsigned int
43064401
num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size)
43074402
{

fs/cifs/smb2pdu.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,5 +1613,49 @@ struct create_posix_rsp {
16131613
* var sized group SID
16141614
*/
16151615
} __packed;
1616+
1617+
/*
1618+
* SMB2-only POSIX info level
1619+
*
1620+
* See posix_info_sid_size(), posix_info_extra_size() and
1621+
* posix_info_parse() to help with the handling of this struct.
1622+
*/
1623+
struct smb2_posix_info {
1624+
__le32 NextEntryOffset;
1625+
__u32 Ignored;
1626+
__le64 CreationTime;
1627+
__le64 LastAccessTime;
1628+
__le64 LastWriteTime;
1629+
__le64 ChangeTime;
1630+
__le64 EndOfFile;
1631+
__le64 AllocationSize;
1632+
__le32 DosAttributes;
1633+
__le64 Inode;
1634+
__le32 DeviceId;
1635+
__le32 Zero;
1636+
/* beginning of POSIX Create Context Response */
1637+
__le32 HardLinks;
1638+
__le32 ReparseTag;
1639+
__le32 Mode;
1640+
/*
1641+
* var sized owner SID
1642+
* var sized group SID
1643+
* le32 filenamelength
1644+
* u8 filename[]
1645+
*/
1646+
} __packed;
1647+
1648+
/*
1649+
* Parsed version of the above struct. Allows direct access to the
1650+
* variable length fields
1651+
*/
1652+
struct smb2_posix_info_parsed {
1653+
const struct smb2_posix_info *base;
1654+
size_t size;
1655+
struct cifs_sid owner;
1656+
struct cifs_sid group;
1657+
int name_len;
1658+
const u8 *name;
16161659
};
1660+
16171661
#endif /* _SMB2PDU_H */

fs/cifs/smb2proto.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,6 @@ extern int smb2_query_info_compound(const unsigned int xid,
272272
u32 class, u32 type, u32 output_len,
273273
struct kvec *rsp, int *buftype,
274274
struct cifs_sb_info *cifs_sb);
275+
int posix_info_parse(const void *beg, const void *end,
276+
struct smb2_posix_info_parsed *out);
275277
#endif /* _SMB2PROTO_H */

0 commit comments

Comments
 (0)