mirror of https://gitee.com/openkylin/linux.git
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 <aaptel@suse.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
2e8af978d9
commit
349e13ad30
|
@ -1691,6 +1691,7 @@ struct smb_t2_rsp {
|
|||
#define SMB_FIND_FILE_ID_FULL_DIR_INFO 0x105
|
||||
#define SMB_FIND_FILE_ID_BOTH_DIR_INFO 0x106
|
||||
#define SMB_FIND_FILE_UNIX 0x202
|
||||
#define SMB_FIND_FILE_POSIX_INFO 0x064
|
||||
|
||||
typedef struct smb_com_transaction2_qpi_req {
|
||||
struct smb_hdr hdr; /* wct = 14+ */
|
||||
|
|
|
@ -4302,6 +4302,101 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int posix_info_sid_size(const void *beg, const void *end)
|
||||
{
|
||||
size_t subauth;
|
||||
int total;
|
||||
|
||||
if (beg + 1 > end)
|
||||
return -1;
|
||||
|
||||
subauth = *(u8 *)(beg+1);
|
||||
if (subauth < 1 || subauth > 15)
|
||||
return -1;
|
||||
|
||||
total = 1 + 1 + 6 + 4*subauth;
|
||||
if (beg + total > end)
|
||||
return -1;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
int posix_info_parse(const void *beg, const void *end,
|
||||
struct smb2_posix_info_parsed *out)
|
||||
|
||||
{
|
||||
int total_len = 0;
|
||||
int sid_len;
|
||||
int name_len;
|
||||
const void *owner_sid;
|
||||
const void *group_sid;
|
||||
const void *name;
|
||||
|
||||
/* if no end bound given, assume payload to be correct */
|
||||
if (!end) {
|
||||
const struct smb2_posix_info *p = beg;
|
||||
|
||||
end = beg + le32_to_cpu(p->NextEntryOffset);
|
||||
/* last element will have a 0 offset, pick a sensible bound */
|
||||
if (end == beg)
|
||||
end += 0xFFFF;
|
||||
}
|
||||
|
||||
/* check base buf */
|
||||
if (beg + sizeof(struct smb2_posix_info) > end)
|
||||
return -1;
|
||||
total_len = sizeof(struct smb2_posix_info);
|
||||
|
||||
/* check owner sid */
|
||||
owner_sid = beg + total_len;
|
||||
sid_len = posix_info_sid_size(owner_sid, end);
|
||||
if (sid_len < 0)
|
||||
return -1;
|
||||
total_len += sid_len;
|
||||
|
||||
/* check group sid */
|
||||
group_sid = beg + total_len;
|
||||
sid_len = posix_info_sid_size(group_sid, end);
|
||||
if (sid_len < 0)
|
||||
return -1;
|
||||
total_len += sid_len;
|
||||
|
||||
/* check name len */
|
||||
if (beg + total_len + 4 > end)
|
||||
return -1;
|
||||
name_len = le32_to_cpu(*(__le32 *)(beg + total_len));
|
||||
if (name_len < 1 || name_len > 0xFFFF)
|
||||
return -1;
|
||||
total_len += 4;
|
||||
|
||||
/* check name */
|
||||
name = beg + total_len;
|
||||
if (name + name_len > end)
|
||||
return -1;
|
||||
total_len += name_len;
|
||||
|
||||
if (out) {
|
||||
out->base = beg;
|
||||
out->size = total_len;
|
||||
out->name_len = name_len;
|
||||
out->name = name;
|
||||
memcpy(&out->owner, owner_sid,
|
||||
posix_info_sid_size(owner_sid, end));
|
||||
memcpy(&out->group, group_sid,
|
||||
posix_info_sid_size(group_sid, end));
|
||||
}
|
||||
return total_len;
|
||||
}
|
||||
|
||||
static int posix_info_extra_size(const void *beg, const void *end)
|
||||
{
|
||||
int len = posix_info_parse(beg, end, NULL);
|
||||
|
||||
if (len < 0)
|
||||
return -1;
|
||||
return len - sizeof(struct smb2_posix_info);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size)
|
||||
{
|
||||
|
|
|
@ -1613,5 +1613,49 @@ struct create_posix_rsp {
|
|||
* var sized group SID
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* SMB2-only POSIX info level
|
||||
*
|
||||
* See posix_info_sid_size(), posix_info_extra_size() and
|
||||
* posix_info_parse() to help with the handling of this struct.
|
||||
*/
|
||||
struct smb2_posix_info {
|
||||
__le32 NextEntryOffset;
|
||||
__u32 Ignored;
|
||||
__le64 CreationTime;
|
||||
__le64 LastAccessTime;
|
||||
__le64 LastWriteTime;
|
||||
__le64 ChangeTime;
|
||||
__le64 EndOfFile;
|
||||
__le64 AllocationSize;
|
||||
__le32 DosAttributes;
|
||||
__le64 Inode;
|
||||
__le32 DeviceId;
|
||||
__le32 Zero;
|
||||
/* beginning of POSIX Create Context Response */
|
||||
__le32 HardLinks;
|
||||
__le32 ReparseTag;
|
||||
__le32 Mode;
|
||||
/*
|
||||
* var sized owner SID
|
||||
* var sized group SID
|
||||
* le32 filenamelength
|
||||
* u8 filename[]
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Parsed version of the above struct. Allows direct access to the
|
||||
* variable length fields
|
||||
*/
|
||||
struct smb2_posix_info_parsed {
|
||||
const struct smb2_posix_info *base;
|
||||
size_t size;
|
||||
struct cifs_sid owner;
|
||||
struct cifs_sid group;
|
||||
int name_len;
|
||||
const u8 *name;
|
||||
};
|
||||
|
||||
#endif /* _SMB2PDU_H */
|
||||
|
|
|
@ -272,4 +272,6 @@ extern int smb2_query_info_compound(const unsigned int xid,
|
|||
u32 class, u32 type, u32 output_len,
|
||||
struct kvec *rsp, int *buftype,
|
||||
struct cifs_sb_info *cifs_sb);
|
||||
int posix_info_parse(const void *beg, const void *end,
|
||||
struct smb2_posix_info_parsed *out);
|
||||
#endif /* _SMB2PROTO_H */
|
||||
|
|
Loading…
Reference in New Issue