Commit 4a91ccc7 authored by Kees Cook's avatar Kees Cook Committed by sanglipeng
Browse files

smb3: Replace smb2pdu 1-element arrays with flex-arrays

stable inclusion
from stable-v5.10.210
commit 02f629bb460d01c81d3acb8d7e383dde65acbb0c
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9O5W8

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=02f629bb460d01c81d3acb8d7e383dde65acbb0c

--------------------------------

commit eb3e28c1 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: default avatarNamjae Jeon <linkinjeon@kernel.org>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Signed-off-by: default avatarVasiliy Kovalev <kovalev@altlinux.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarsanglipeng <sanglipeng1@jd.com>
parent 07c7544b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -117,7 +117,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
+7 −7
Original line number Diff line number Diff line
@@ -5565,7 +5565,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,
@@ -5587,7 +5587,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,
@@ -5608,7 +5608,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,
@@ -5629,7 +5629,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,
@@ -5650,7 +5650,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,
@@ -5671,7 +5671,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,
@@ -5692,7 +5692,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,
+6 −7
Original line number Diff line number Diff line
@@ -1261,7 +1261,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));
@@ -1760,8 +1760,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;
@@ -4676,7 +4675,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
@@ -4873,7 +4872,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);
@@ -5105,9 +5104,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;
+24 −18
Original line number Diff line number Diff line
@@ -220,7 +220,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
@@ -464,7 +464,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 */
@@ -481,7 +481,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 */
@@ -494,7 +494,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 {
@@ -520,7 +520,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 */
@@ -828,7 +828,7 @@ struct smb2_create_rsp {
	__u64  VolatileFileId; /* opaque endianness */
	__le32 CreateContextsOffset;
	__le32 CreateContextsLength;
	__u8   Buffer[1];
	__u8   Buffer[];
} __packed;

struct create_context {
@@ -1289,7 +1289,7 @@ struct smb2_read_plain_req {
	__le32 RemainingBytes;
	__le16 ReadChannelInfoOffset;
	__le16 ReadChannelInfoLength;
	__u8   Buffer[1];
	__u8   Buffer[];
} __packed;

/* Read flags */
@@ -1304,7 +1304,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: */
@@ -1324,7 +1324,7 @@ struct smb2_write_req {
	__le16 WriteChannelInfoOffset;
	__le16 WriteChannelInfoLength;
	__le32 Flags;
	__u8   Buffer[1];
	__u8   Buffer[];
} __packed;

struct smb2_write_rsp {
@@ -1335,7 +1335,7 @@ struct smb2_write_rsp {
	__le32 DataLength;
	__le32 DataRemaining;
	__u32  Reserved2;
	__u8   Buffer[1];
	__u8   Buffer[];
} __packed;

/* notify flags */
@@ -1371,7 +1371,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
@@ -1394,7 +1394,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 {
@@ -1434,7 +1437,7 @@ struct smb2_query_directory_req {
	__le16 FileNameOffset;
	__le16 FileNameLength;
	__le32 OutputBufferLength;
	__u8   Buffer[1];
	__u8   Buffer[];
} __packed;

struct smb2_query_directory_rsp {
@@ -1442,7 +1445,7 @@ struct smb2_query_directory_rsp {
	__le16 StructureSize; /* Must be 9 */
	__le16 OutputBufferOffset;
	__le32 OutputBufferLength;
	__u8   Buffer[1];
	__u8   Buffer[];
} __packed;

/* Possible InfoType values */
@@ -1483,7 +1486,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 {
@@ -1491,7 +1494,7 @@ struct smb2_query_info_rsp {
	__le16 StructureSize; /* Must be 9 */
	__le16 OutputBufferOffset;
	__le32 OutputBufferLength;
	__u8   Buffer[1];
	__u8   Buffer[];
} __packed;

/*
@@ -1514,7 +1517,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 {
@@ -1716,7 +1719,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 */