mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-24 19:35:58 +00:00
smb3: Replace smb2pdu 1-element arrays with flex-arrays
commit eb3e28c1e8
upstream.
The kernel is globally removing the ambiguous 0-length and 1-element
arrays in favor of flexible arrays, so that we can gain both compile-time
and run-time array bounds checking[1].
Replace the trailing 1-element array with a flexible array in the
following structures:
struct smb2_err_rsp
struct smb2_tree_connect_req
struct smb2_negotiate_rsp
struct smb2_sess_setup_req
struct smb2_sess_setup_rsp
struct smb2_read_req
struct smb2_read_rsp
struct smb2_write_req
struct smb2_write_rsp
struct smb2_query_directory_req
struct smb2_query_directory_rsp
struct smb2_set_info_req
struct smb2_change_notify_rsp
struct smb2_create_rsp
struct smb2_query_info_req
struct smb2_query_info_rsp
Replace the trailing 1-element array with a flexible array, but leave
the existing structure padding:
struct smb2_file_all_info
struct smb2_lock_req
Adjust all related size calculations to match the changes to sizeof().
No machine code output or .data section differences are produced after
these changes.
[1] For lots of details, see both:
https://docs.kernel.org/process/deprecated.html#zero-length-and-one-element-arrays
https://people.kernel.org/kees/bounded-flexible-arrays-in-c
Cc: Steve French <sfrench@samba.org>
Cc: Paulo Alcantara <pc@cjr.nz>
Cc: Ronnie Sahlberg <lsahlber@redhat.com>
Cc: Shyam Prasad N <sprasad@microsoft.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Namjae Jeon <linkinjeon@kernel.org>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Vasiliy Kovalev <kovalev@altlinux.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
0b49eac39c
commit
9e25a00540
4 changed files with 38 additions and 33 deletions
|
@ -113,7 +113,7 @@ static __u32 get_neg_ctxt_len(struct smb2_sync_hdr *hdr, __u32 len,
|
|||
} else if (nc_offset + 1 == non_ctxlen) {
|
||||
cifs_dbg(FYI, "no SPNEGO security blob in negprot rsp\n");
|
||||
size_of_pad_before_neg_ctxts = 0;
|
||||
} else if (non_ctxlen == SMB311_NEGPROT_BASE_SIZE)
|
||||
} else if (non_ctxlen == SMB311_NEGPROT_BASE_SIZE + 1)
|
||||
/* has padding, but no SPNEGO blob */
|
||||
size_of_pad_before_neg_ctxts = nc_offset - non_ctxlen + 1;
|
||||
else
|
||||
|
|
|
@ -5826,7 +5826,7 @@ struct smb_version_values smb20_values = {
|
|||
.header_size = sizeof(struct smb2_sync_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
|
@ -5848,7 +5848,7 @@ struct smb_version_values smb21_values = {
|
|||
.header_size = sizeof(struct smb2_sync_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
|
@ -5869,7 +5869,7 @@ struct smb_version_values smb3any_values = {
|
|||
.header_size = sizeof(struct smb2_sync_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
|
@ -5890,7 +5890,7 @@ struct smb_version_values smbdefault_values = {
|
|||
.header_size = sizeof(struct smb2_sync_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
|
@ -5911,7 +5911,7 @@ struct smb_version_values smb30_values = {
|
|||
.header_size = sizeof(struct smb2_sync_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
|
@ -5932,7 +5932,7 @@ struct smb_version_values smb302_values = {
|
|||
.header_size = sizeof(struct smb2_sync_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
|
@ -5953,7 +5953,7 @@ struct smb_version_values smb311_values = {
|
|||
.header_size = sizeof(struct smb2_sync_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
.cap_unix = 0,
|
||||
.cap_nt_find = SMB2_NT_FIND,
|
||||
|
|
|
@ -1327,7 +1327,7 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
|
|||
|
||||
/* Testing shows that buffer offset must be at location of Buffer[0] */
|
||||
req->SecurityBufferOffset =
|
||||
cpu_to_le16(sizeof(struct smb2_sess_setup_req) - 1 /* pad */);
|
||||
cpu_to_le16(sizeof(struct smb2_sess_setup_req));
|
||||
req->SecurityBufferLength = cpu_to_le16(sess_data->iov[1].iov_len);
|
||||
|
||||
memset(&rqst, 0, sizeof(struct smb_rqst));
|
||||
|
@ -1826,8 +1826,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
|
|||
iov[0].iov_len = total_len - 1;
|
||||
|
||||
/* Testing shows that buffer offset must be at location of Buffer[0] */
|
||||
req->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req)
|
||||
- 1 /* pad */);
|
||||
req->PathOffset = cpu_to_le16(sizeof(struct smb2_tree_connect_req));
|
||||
req->PathLength = cpu_to_le16(unc_path_len - 2);
|
||||
iov[1].iov_base = unc_path;
|
||||
iov[1].iov_len = unc_path_len;
|
||||
|
@ -4748,7 +4747,7 @@ int SMB2_query_directory_init(const unsigned int xid,
|
|||
memcpy(bufptr, &asteriks, len);
|
||||
|
||||
req->FileNameOffset =
|
||||
cpu_to_le16(sizeof(struct smb2_query_directory_req) - 1);
|
||||
cpu_to_le16(sizeof(struct smb2_query_directory_req));
|
||||
req->FileNameLength = cpu_to_le16(len);
|
||||
/*
|
||||
* BB could be 30 bytes or so longer if we used SMB2 specific
|
||||
|
@ -4945,7 +4944,7 @@ SMB2_set_info_init(struct cifs_tcon *tcon, struct TCP_Server_Info *server,
|
|||
req->AdditionalInformation = cpu_to_le32(additional_info);
|
||||
|
||||
req->BufferOffset =
|
||||
cpu_to_le16(sizeof(struct smb2_set_info_req) - 1);
|
||||
cpu_to_le16(sizeof(struct smb2_set_info_req));
|
||||
req->BufferLength = cpu_to_le32(*size);
|
||||
|
||||
memcpy(req->Buffer, *data, *size);
|
||||
|
@ -5177,9 +5176,9 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon,
|
|||
req->VolatileFileId = volatile_fid;
|
||||
/* 1 for pad */
|
||||
req->InputBufferOffset =
|
||||
cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
|
||||
cpu_to_le16(sizeof(struct smb2_query_info_req));
|
||||
req->OutputBufferLength = cpu_to_le32(
|
||||
outbuf_len + sizeof(struct smb2_query_info_rsp) - 1);
|
||||
outbuf_len + sizeof(struct smb2_query_info_rsp));
|
||||
|
||||
iov->iov_base = (char *)req;
|
||||
iov->iov_len = total_len;
|
||||
|
|
|
@ -218,7 +218,7 @@ struct smb2_err_rsp {
|
|||
__le16 StructureSize;
|
||||
__le16 Reserved; /* MBZ */
|
||||
__le32 ByteCount; /* even if zero, at least one byte follows */
|
||||
__u8 ErrorData[1]; /* variable length */
|
||||
__u8 ErrorData[]; /* variable length */
|
||||
} __packed;
|
||||
|
||||
#define SYMLINK_ERROR_TAG 0x4c4d5953
|
||||
|
@ -487,7 +487,7 @@ struct smb2_negotiate_rsp {
|
|||
__le16 SecurityBufferOffset;
|
||||
__le16 SecurityBufferLength;
|
||||
__le32 NegotiateContextOffset; /* Pre:SMB3.1.1 was reserved/ignored */
|
||||
__u8 Buffer[1]; /* variable length GSS security buffer */
|
||||
__u8 Buffer[]; /* variable length GSS security buffer */
|
||||
} __packed;
|
||||
|
||||
/* Flags */
|
||||
|
@ -504,7 +504,7 @@ struct smb2_sess_setup_req {
|
|||
__le16 SecurityBufferOffset;
|
||||
__le16 SecurityBufferLength;
|
||||
__u64 PreviousSessionId;
|
||||
__u8 Buffer[1]; /* variable length GSS security buffer */
|
||||
__u8 Buffer[]; /* variable length GSS security buffer */
|
||||
} __packed;
|
||||
|
||||
/* Currently defined SessionFlags */
|
||||
|
@ -517,7 +517,7 @@ struct smb2_sess_setup_rsp {
|
|||
__le16 SessionFlags;
|
||||
__le16 SecurityBufferOffset;
|
||||
__le16 SecurityBufferLength;
|
||||
__u8 Buffer[1]; /* variable length GSS security buffer */
|
||||
__u8 Buffer[]; /* variable length GSS security buffer */
|
||||
} __packed;
|
||||
|
||||
struct smb2_logoff_req {
|
||||
|
@ -543,7 +543,7 @@ struct smb2_tree_connect_req {
|
|||
__le16 Flags; /* Reserved MBZ for dialects prior to SMB3.1.1 */
|
||||
__le16 PathOffset;
|
||||
__le16 PathLength;
|
||||
__u8 Buffer[1]; /* variable length */
|
||||
__u8 Buffer[]; /* variable length */
|
||||
} __packed;
|
||||
|
||||
/* See MS-SMB2 section 2.2.9.2 */
|
||||
|
@ -852,7 +852,7 @@ struct smb2_create_rsp {
|
|||
__u64 VolatileFileId; /* opaque endianness */
|
||||
__le32 CreateContextsOffset;
|
||||
__le32 CreateContextsLength;
|
||||
__u8 Buffer[1];
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
struct create_context {
|
||||
|
@ -1313,7 +1313,7 @@ struct smb2_read_plain_req {
|
|||
__le32 RemainingBytes;
|
||||
__le16 ReadChannelInfoOffset;
|
||||
__le16 ReadChannelInfoLength;
|
||||
__u8 Buffer[1];
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
/* Read flags */
|
||||
|
@ -1328,7 +1328,7 @@ struct smb2_read_rsp {
|
|||
__le32 DataLength;
|
||||
__le32 DataRemaining;
|
||||
__u32 Flags;
|
||||
__u8 Buffer[1];
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
/* For write request Flags field below the following flags are defined: */
|
||||
|
@ -1348,7 +1348,7 @@ struct smb2_write_req {
|
|||
__le16 WriteChannelInfoOffset;
|
||||
__le16 WriteChannelInfoLength;
|
||||
__le32 Flags;
|
||||
__u8 Buffer[1];
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
struct smb2_write_rsp {
|
||||
|
@ -1359,7 +1359,7 @@ struct smb2_write_rsp {
|
|||
__le32 DataLength;
|
||||
__le32 DataRemaining;
|
||||
__u32 Reserved2;
|
||||
__u8 Buffer[1];
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
/* notify flags */
|
||||
|
@ -1395,7 +1395,7 @@ struct smb2_change_notify_rsp {
|
|||
__le16 StructureSize; /* Must be 9 */
|
||||
__le16 OutputBufferOffset;
|
||||
__le32 OutputBufferLength;
|
||||
__u8 Buffer[1]; /* array of file notify structs */
|
||||
__u8 Buffer[]; /* array of file notify structs */
|
||||
} __packed;
|
||||
|
||||
#define SMB2_LOCKFLAG_SHARED_LOCK 0x0001
|
||||
|
@ -1422,7 +1422,10 @@ struct smb2_lock_req {
|
|||
__u64 PersistentFileId; /* opaque endianness */
|
||||
__u64 VolatileFileId; /* opaque endianness */
|
||||
/* Followed by at least one */
|
||||
struct smb2_lock_element locks[1];
|
||||
union {
|
||||
struct smb2_lock_element lock;
|
||||
DECLARE_FLEX_ARRAY(struct smb2_lock_element, locks);
|
||||
};
|
||||
} __packed;
|
||||
|
||||
struct smb2_lock_rsp {
|
||||
|
@ -1478,7 +1481,7 @@ struct smb2_query_directory_req {
|
|||
__le16 FileNameOffset;
|
||||
__le16 FileNameLength;
|
||||
__le32 OutputBufferLength;
|
||||
__u8 Buffer[1];
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
struct smb2_query_directory_rsp {
|
||||
|
@ -1486,7 +1489,7 @@ struct smb2_query_directory_rsp {
|
|||
__le16 StructureSize; /* Must be 9 */
|
||||
__le16 OutputBufferOffset;
|
||||
__le32 OutputBufferLength;
|
||||
__u8 Buffer[1];
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
/* Possible InfoType values */
|
||||
|
@ -1527,7 +1530,7 @@ struct smb2_query_info_req {
|
|||
__le32 Flags;
|
||||
__u64 PersistentFileId; /* opaque endianness */
|
||||
__u64 VolatileFileId; /* opaque endianness */
|
||||
__u8 Buffer[1];
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
struct smb2_query_info_rsp {
|
||||
|
@ -1535,7 +1538,7 @@ struct smb2_query_info_rsp {
|
|||
__le16 StructureSize; /* Must be 9 */
|
||||
__le16 OutputBufferOffset;
|
||||
__le32 OutputBufferLength;
|
||||
__u8 Buffer[1];
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
|
@ -1558,7 +1561,7 @@ struct smb2_set_info_req {
|
|||
__le32 AdditionalInformation;
|
||||
__u64 PersistentFileId; /* opaque endianness */
|
||||
__u64 VolatileFileId; /* opaque endianness */
|
||||
__u8 Buffer[1];
|
||||
__u8 Buffer[];
|
||||
} __packed;
|
||||
|
||||
struct smb2_set_info_rsp {
|
||||
|
@ -1761,7 +1764,10 @@ struct smb2_file_all_info { /* data block encoding of response to level 18 */
|
|||
__le32 Mode;
|
||||
__le32 AlignmentRequirement;
|
||||
__le32 FileNameLength;
|
||||
char FileName[1];
|
||||
union {
|
||||
char __pad; /* Legacy structure padding */
|
||||
DECLARE_FLEX_ARRAY(char, FileName);
|
||||
};
|
||||
} __packed; /* level 18 Query */
|
||||
|
||||
struct smb2_file_eof_info { /* encoding of request for level 10 */
|
||||
|
|
Loading…
Reference in a new issue