FAILED: patch "[PATCH] ksmbd: validate minimum PDU size for transform requests" failed to apply to 6.12-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x cfc0b8e5080aec87700774e8568765eaa4b7b92b
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026072924-music-polyester-3132@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From cfc0b8e5080aec87700774e8568765eaa4b7b92b Mon Sep 17 00:00:00 2001
From: Namjae Jeon <[email protected]>
Date: Sat, 4 Jul 2026 11:30:27 +0900
Subject: [PATCH] ksmbd: validate minimum PDU size for transform requests
The receive path applies the minimum SMB2 PDU size check only when ProtocolId is SMB2_PROTO_NUMBER. A packet carrying SMB2_TRANSFORM_PROTO_NUM bypasses the check even when the negotiated dialect does not provide transform handling.
On an SMB 2.1 connection, a short transform packet therefore reaches init_smb2_rsp_hdr(), which interprets the request as a full SMB2 header and reads beyond the request allocation. The copied fields can then be returned to the unauthenticated client.
Compression transforms are converted to ordinary SMB2 messages before protocol validation. After that conversion, validate ordinary SMB2 requests against SMB2_MIN_SUPPORTED_PDU_SIZE and require encryption transform requests to contain both a transform header and an SMB2 header. This rejects truncated requests before work allocation.
fs/smb/server/connection.c +11 -5
@@ -441,6 +441,8 @@ bool ksmbd_conn_alive(struct ksmbd_conn *conn)/* "+2" for BCC field (ByteCount, 2 bytes) */ #define SMB1_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb_hdr) + 2)#define SMB2_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb2_pdu)) +#define SMB2_TRANSFORM_MIN_SUPPORTED_PDU_SIZE \ + (sizeof(struct smb2_transform_hdr) + sizeof(struct smb2_hdr))/** * ksmbd_conn_handler_loop() - session thread to listen on new smb requests
@@ -455,6 +457,7 @@ int ksmbd_conn_handler_loop(void *p)struct ksmbd_conn *conn = (struct ksmbd_conn *)p;struct ksmbd_transport *t = conn->transport;unsigned int pdu_size, max_allowed_pdu_size, max_req; +__le32 proto;char hdr_buf[4 ] = {0 ,};int size;
@@ -546,11 +549,14 @@ int ksmbd_conn_handler_loop(void *p)if (!ksmbd_smb_request (conn))break ; -if (((struct smb2_hdr *)smb_get_msg (conn->request_buf))->ProtocolId == -SMB2_PROTO_NUMBER ) { -if (pdu_size <SMB2_MIN_SUPPORTED_PDU_SIZE ) -break ; - } + proto = *(__le32 *)smb_get_msg (conn->request_buf); +if (proto ==SMB2_PROTO_NUMBER && + pdu_size <SMB2_MIN_SUPPORTED_PDU_SIZE ) +break ; + +if (proto ==SMB2_TRANSFORM_PROTO_NUM && + pdu_size <SMB2_TRANSFORM_MIN_SUPPORTED_PDU_SIZE ) +break ;if (!default_conn_ops.process_fn) {pr_err ("No connection request callback\n" );
Sasha Levin
maintainerPATCH 1/7 smb: move smb_version_values to common/smbglob.h
From: ZhangGuoDong <[email protected]>
[ Upstream commit 34cf191bb6a349dc88ec2c4f6355fe006ac669e0 ]
Merge the struct members of the server and the client:
- req_capabilities: from client
- header_preamble_size: from client
- cap_unicode: from client
- capabilities: from server, rename to req_capabilities
- max_read_size: from server
- max_write_size: from server
- max_trans_size: from server
- max_credits: from server
- create_durable_size: from server
- create_durable_v2_size: from server
- create_mxac_size: from server
- create_disk_id_size: from server
- create_posix_size: from server
Then move duplicate definitions to common header file.
Stable-dep-of: cfc0b8e5080a ("ksmbd: validate minimum PDU size for transform requests")
--- fs/smb/client/cifsglob.h | 21 --------------------- fs/smb/common/cifsglob.h | 31 +++++++++++++++++++++++++++++++ fs/smb/server/smb2misc.c | 2 +- fs/smb/server/smb2ops.c | 32 ++++++++++++++++---------------- fs/smb/server/smb2pdu.c | 10 +++++----- fs/smb/server/smb_common.h | 29 ----------------------------- 6 files changed, 53 insertions(+), 72 deletions(-)
fs/smb/client/cifsglob.h +0 -21
@@ -606,27 +606,6 @@ struct smb_version_operations { const char *symname); }; -struct smb_version_values { -char *version_string; -__u16 protocol_id; -__u32 req_capabilities; -__u32 large_lock_type; -__u32 exclusive_lock_type; -__u32 shared_lock_type; -__u32 unlock_lock_type; -size_t header_preamble_size; -size_t header_size; -size_t max_header_size; -size_t read_rsp_size; -__le16 lock_cmd; -unsigned int cap_unix; -unsigned int cap_nt_find; -unsigned int cap_large_files; -__u16 signing_enabled; -__u16 signing_required; -size_t create_lease_size; -}; -#define HEADER_SIZE (server) (server->vals->header_size)#define MAX_HEADER_SIZE (server) (server->vals->max_header_size)#define HEADER_PREAMBLE_SIZE (server) (server->vals->header_preamble_size)
fs/smb/common/cifsglob.h +31 -0
@@ -9,6 +9,37 @@#ifndef _COMMON_CIFS_GLOB_H#define _COMMON_CIFS_GLOB_H +struct smb_version_values { +char *version_string; +__u16 protocol_id; +__le16 lock_cmd; +__u32 req_capabilities; +__u32 max_read_size; +__u32 max_write_size; +__u32 max_trans_size; +__u32 max_credits; +__u32 large_lock_type; +__u32 exclusive_lock_type; +__u32 shared_lock_type; +__u32 unlock_lock_type; +size_t header_preamble_size; +size_t header_size; +size_t max_header_size; +size_t read_rsp_size; +unsigned int cap_unix; +unsigned int cap_nt_find; +unsigned int cap_large_files; +unsigned int cap_unicode; +__u16 signing_enabled; +__u16 signing_required; +size_t create_lease_size; +size_t create_durable_size; +size_t create_durable_v2_size; +size_t create_mxac_size; +size_t create_disk_id_size; +size_t create_posix_size; +}; +static inline void inc_rfc1001_len (void *buf,int count) {be32_add_cpu ((__be32 *)buf, count);
fs/smb/server/smb2misc.c +1 -1
@@ -465,7 +465,7 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) } validate_credit: -if ((work->conn->vals->capabilities &SMB2_GLOBAL_CAP_LARGE_MTU ) && +if ((work->conn->vals->req_capabilities &SMB2_GLOBAL_CAP_LARGE_MTU ) &&smb2_validate_credit_charge (work->conn, hdr))return 1 ;
fs/smb/server/smb2ops.c +16 -16
@@ -15,7 +15,7 @@static struct smb_version_values smb21_server_values = { .version_string =SMB21_VERSION_STRING , .protocol_id =SMB21_PROT_ID , - .capabilities =SMB2_GLOBAL_CAP_LARGE_MTU , + .req_capabilities =SMB2_GLOBAL_CAP_LARGE_MTU , .max_read_size =SMB21_DEFAULT_IOSIZE , .max_write_size =SMB21_DEFAULT_IOSIZE , .max_trans_size =SMB21_DEFAULT_IOSIZE ,
@@ -41,7 +41,7 @@ static struct smb_version_values smb21_server_values = {static struct smb_version_values smb30_server_values = { .version_string =SMB30_VERSION_STRING , .protocol_id =SMB30_PROT_ID , - .capabilities =SMB2_GLOBAL_CAP_LARGE_MTU , + .req_capabilities =SMB2_GLOBAL_CAP_LARGE_MTU , .max_read_size =SMB3_DEFAULT_IOSIZE , .max_write_size =SMB3_DEFAULT_IOSIZE , .max_trans_size =SMB3_DEFAULT_TRANS_SIZE ,
@@ -68,7 +68,7 @@ static struct smb_version_values smb30_server_values = {static struct smb_version_values smb302_server_values = { .version_string =SMB302_VERSION_STRING , .protocol_id =SMB302_PROT_ID , - .capabilities =SMB2_GLOBAL_CAP_LARGE_MTU , + .req_capabilities =SMB2_GLOBAL_CAP_LARGE_MTU , .max_read_size =SMB3_DEFAULT_IOSIZE , .max_write_size =SMB3_DEFAULT_IOSIZE , .max_trans_size =SMB3_DEFAULT_TRANS_SIZE ,
@@ -95,7 +95,7 @@ static struct smb_version_values smb302_server_values = {static struct smb_version_values smb311_server_values = { .version_string =SMB311_VERSION_STRING , .protocol_id =SMB311_PROT_ID , - .capabilities =SMB2_GLOBAL_CAP_LARGE_MTU , + .req_capabilities =SMB2_GLOBAL_CAP_LARGE_MTU , .max_read_size =SMB3_DEFAULT_IOSIZE , .max_write_size =SMB3_DEFAULT_IOSIZE , .max_trans_size =SMB3_DEFAULT_TRANS_SIZE ,
@@ -204,7 +204,7 @@ void init_smb2_1_server(struct ksmbd_conn *conn) conn->signing_algorithm =SIGNING_ALG_HMAC_SHA256_LE ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB2_LEASES ) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_LEASING ; + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_LEASING ; }/**
@@ -221,20 +221,20 @@ void init_smb3_0_server(struct ksmbd_conn *conn) conn->signing_algorithm =SIGNING_ALG_AES_CMAC_LE ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB2_LEASES ) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_LEASING | + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_LEASING |SMB2_GLOBAL_CAP_DIRECTORY_LEASING ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION && conn->cli_cap &SMB2_GLOBAL_CAP_ENCRYPTION ) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_ENCRYPTION ; + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_ENCRYPTION ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION || (!(server_conf.flags &KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF ) && conn->cli_cap &SMB2_GLOBAL_CAP_ENCRYPTION )) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_ENCRYPTION ; + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_ENCRYPTION ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL ) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_MULTI_CHANNEL ; + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_MULTI_CHANNEL ; }/**
@@ -251,19 +251,19 @@ void init_smb3_02_server(struct ksmbd_conn *conn) conn->signing_algorithm =SIGNING_ALG_AES_CMAC_LE ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB2_LEASES ) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_LEASING | + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_LEASING |SMB2_GLOBAL_CAP_DIRECTORY_LEASING ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION || (!(server_conf.flags &KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF ) && conn->cli_cap &SMB2_GLOBAL_CAP_ENCRYPTION )) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_ENCRYPTION ; + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_ENCRYPTION ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL ) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_MULTI_CHANNEL ; + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_MULTI_CHANNEL ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_DURABLE_HANDLE ) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_PERSISTENT_HANDLES ; + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_PERSISTENT_HANDLES ; }/**
@@ -280,14 +280,14 @@ int init_smb3_11_server(struct ksmbd_conn *conn) conn->signing_algorithm =SIGNING_ALG_AES_CMAC_LE ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB2_LEASES ) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_LEASING | + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_LEASING |SMB2_GLOBAL_CAP_DIRECTORY_LEASING ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL ) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_MULTI_CHANNEL ; + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_MULTI_CHANNEL ;if (server_conf.flags &KSMBD_GLOBAL_FLAG_DURABLE_HANDLE ) - conn->vals->capabilities |=SMB2_GLOBAL_CAP_PERSISTENT_HANDLES ; + conn->vals->req_capabilities |=SMB2_GLOBAL_CAP_PERSISTENT_HANDLES ;INIT_LIST_HEAD (&conn->preauth_sess_table);return 0 ;
fs/smb/server/smb2pdu.c +5 -5
@@ -290,7 +290,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)/* Not setting conn guid rsp->ServerGUID, as it * not used by client for identifying connection */ - rsp->Capabilities =cpu_to_le32 (conn->vals->capabilities); + rsp->Capabilities =cpu_to_le32 (conn->vals->req_capabilities);/* Default Max Message Size till SMB2.0, 64K*/ rsp->MaxTransactSize =cpu_to_le32 (conn->vals->max_trans_size); rsp->MaxReadSize =cpu_to_le32 (conn->vals->max_read_size);
@@ -969,7 +969,7 @@ bool smb3_encryption_negotiated(struct ksmbd_conn *conn)* SMB 3.0 and 3.0.2 dialects use the SMB2_GLOBAL_CAP_ENCRYPTION flag. * SMB 3.1.1 uses the cipher_type field. */ -return (conn->vals->capabilities &SMB2_GLOBAL_CAP_ENCRYPTION ) || +return (conn->vals->req_capabilities &SMB2_GLOBAL_CAP_ENCRYPTION ) || conn->cipher_type; }
@@ -1222,7 +1222,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work) rc = -EINVAL ; goto err_out; } - rsp->Capabilities =cpu_to_le32 (conn->vals->capabilities); + rsp->Capabilities =cpu_to_le32 (conn->vals->req_capabilities);/* For stats */ conn->connection_type = conn->dialect;
@@ -3501,7 +3501,7 @@ int smb2_open(struct ksmbd_work *work) share_ret =ksmbd_smb_check_shared_mode (fp->filp, fp);if (!test_share_config_flag (work->tcon->share_conf,KSMBD_SHARE_FLAG_OPLOCKS ) || (req_op_level ==SMB2_OPLOCK_LEVEL_LEASE && - !(conn->vals->capabilities &SMB2_GLOBAL_CAP_LEASING ))) { + !(conn->vals->req_capabilities &SMB2_GLOBAL_CAP_LEASING ))) {if (share_ret <0 && !S_ISDIR (file_inode (fp->filp)->i_mode)) { rc = share_ret; goto err_out1;
@@ -8102,7 +8102,7 @@ static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn, goto err_out; } - neg_rsp->Capabilities =cpu_to_le32 (conn->vals->capabilities); + neg_rsp->Capabilities =cpu_to_le32 (conn->vals->req_capabilities);memset (neg_rsp->Guid,0 ,SMB2_CLIENT_GUID_SIZE ); neg_rsp->SecurityMode =cpu_to_le16 (conn->srv_sec_mode); neg_rsp->Dialect =cpu_to_le16 (conn->dialect);
fs/smb/server/smb_common.h +0 -29
@@ -336,35 +336,6 @@ struct file_id_full_dir_info {char FileName[]; } __packed;/* level 0x105 FF rsp data */ -struct smb_version_values { -char *version_string; -__u16 protocol_id; -__le16 lock_cmd; -__u32 capabilities; -__u32 max_read_size; -__u32 max_write_size; -__u32 max_trans_size; -__u32 max_credits; -__u32 large_lock_type; -__u32 exclusive_lock_type; -__u32 shared_lock_type; -__u32 unlock_lock_type; -size_t header_size; -size_t max_header_size; -size_t read_rsp_size; -unsigned int cap_unix; -unsigned int cap_nt_find; -unsigned int cap_large_files; -__u16 signing_enabled; -__u16 signing_required; -size_t create_lease_size; -size_t create_durable_size; -size_t create_durable_v2_size; -size_t create_mxac_size; -size_t create_disk_id_size; -size_t create_posix_size; -}; -struct filesystem_posix_info {/* For undefined recommended transfer size return -1 in that field */ __le32 OptimalTransferSize;/* bsize on some os, iosize on other os */
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/7 smb: move get_rfc1002_len() to common/smbglob.h
From: ZhangGuoDong <[email protected]>
[ Upstream commit 36c31540cf5279262bfd148d8537cd04866499f2 ]
Rename get_rfc1002_length() to get_rfc1002_len(), then move duplicate definitions to common header file.
Stable-dep-of: cfc0b8e5080a ("ksmbd: validate minimum PDU size for transform requests")
--- fs/smb/client/cifsglob.h | 6 ------ fs/smb/client/cifssmb.c | 6 +++--- fs/smb/client/connect.c | 2 +- fs/smb/client/transport.c | 8 ++++---- fs/smb/common/cifsglob.h | 5 +++++ fs/smb/server/smb_common.h | 5 ----- 6 files changed, 13 insertions(+), 19 deletions(-)
fs/smb/client/cifsglob.h +0 -6
@@ -643,12 +643,6 @@ struct cifs_mnt_data {int flags; }; -static inline unsigned int -get_rfc1002_length (void *buf) -{ -return be32_to_cpu (*((__be32 *)buf)) &0xffffff ; -} -struct TCP_Server_Info {struct list_head tcp_ses_list;struct list_head smb_ses_list;
fs/smb/client/cifssmb.c +3 -3
@@ -597,7 +597,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server) iov[0 ].iov_len =4 ; iov[0 ].iov_base = smb; - iov[1 ].iov_len =get_rfc1002_length (smb); + iov[1 ].iov_len =get_rfc1002_len (smb); iov[1 ].iov_base = (char *)smb +4 ; rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
@@ -1387,7 +1387,7 @@ cifs_async_readv(struct cifs_io_subrequest *rdata) rdata->iov[0 ].iov_base = smb; rdata->iov[0 ].iov_len =4 ; rdata->iov[1 ].iov_base = (char *)smb +4 ; - rdata->iov[1 ].iov_len =get_rfc1002_length (smb); + rdata->iov[1 ].iov_len =get_rfc1002_len (smb); rc =cifs_call_async (tcon->ses->server, &rqst, cifs_readv_receive, cifs_readv_callback,NULL , rdata,0 ,NULL );
@@ -1739,7 +1739,7 @@ cifs_async_writev(struct cifs_io_subrequest *wdata)/* 4 for RFC1001 length + 1 for BCC */ iov[0 ].iov_len =4 ; iov[0 ].iov_base = smb; - iov[1 ].iov_len =get_rfc1002_length (smb) +1 ; + iov[1 ].iov_len =get_rfc1002_len (smb) +1 ; iov[1 ].iov_base = (char *)smb +4 ; rqst.rq_iov = iov;
fs/smb/client/connect.c +1 -1
@@ -1213,7 +1213,7 @@ cifs_demultiplex_thread(void *p)* The right amount was read from socket - 4 bytes, * so we can now interpret the length field. */ - pdu_length =get_rfc1002_length (buf); + pdu_length =get_rfc1002_len (buf);cifs_dbg (FYI ,"RFC1002 header 0x%x\n" , pdu_length);if (!is_smb_response (server, buf[0 ]))
fs/smb/client/transport.c +4 -4
@@ -886,7 +886,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,int resp_buf_type; iov[0 ].iov_base = in_buf; - iov[0 ].iov_len =get_rfc1002_length (in_buf) +4 ; + iov[0 ].iov_len =get_rfc1002_len (in_buf) +4 ; flags |=CIFS_NO_RSP_BUF ; rc =SendReceive2 (xid, ses, iov,1 , &resp_buf_type, flags, &rsp_iov);cifs_dbg (NOISY ,"SendRcvNoRsp flags %d rc %d\n" , flags, rc);
@@ -946,7 +946,7 @@ int cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, bool log_error) { - unsigned int len = get_rfc1002_length(mid->resp_buf) + 4; + unsigned int len = get_rfc1002_len(mid->resp_buf) + 4;dump_smb (mid->resp_buf,min_t (u32,92 , len));
@@ -1466,7 +1466,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, goto out; } - *pbytes_returned =get_rfc1002_length (midQ->resp_buf); + *pbytes_returned =get_rfc1002_len (midQ->resp_buf);memcpy (out_buf, midQ->resp_buf, *pbytes_returned +4 ); rc =cifs_check_receive (midQ, server,0 ); out:
@@ -1651,7 +1651,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, goto out; } - *pbytes_returned =get_rfc1002_length (midQ->resp_buf); + *pbytes_returned =get_rfc1002_len (midQ->resp_buf);memcpy (out_buf, midQ->resp_buf, *pbytes_returned +4 ); rc =cifs_check_receive (midQ, server,0 ); out:
fs/smb/common/cifsglob.h +5 -0
@@ -40,6 +40,11 @@ struct smb_version_values {size_t create_posix_size; }; +static inline unsigned int get_rfc1002_len (void *buf) +{ +return be32_to_cpu (*((__be32 *)buf)) &0xffffff ; +} +static inline void inc_rfc1001_len (void *buf,int count) {be32_add_cpu ((__be32 *)buf, count);
fs/smb/server/smb_common.h +0 -5
@@ -421,9 +421,4 @@ unsigned int ksmbd_server_side_copy_max_chunk_size(void);unsigned int ksmbd_server_side_copy_max_total_size (void );bool is_asterisk (char *p);__le32 smb_map_generic_desired_access (__le32 daccess); - -static inline unsigned int get_rfc1002_len (void *buf) -{ -return be32_to_cpu (*((__be32 *)buf)) &0xffffff ; -}#endif /* __SMB_COMMON_H__ */
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/7 smb/server: rename include guard in smb_common.h
In reply to Sasha LevinFrom: ChenXiaoSong <[email protected]>
[ Upstream commit 01ab0d1640e379f0a0d6602250b33ff2b45e9560 ]
Make the include guard more descriptive to avoid conflicts with include guards that may be used in the future.
Stable-dep-of: cfc0b8e5080a ("ksmbd: validate minimum PDU size for transform requests")
--- fs/smb/server/smb_common.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/smb/server/smb_common.h +3 -3
@@ -3,8 +3,8 @@* Copyright (C) 2018 Samsung Electronics Co., Ltd. */ -#ifndef __SMB_COMMON_H__ -#define __SMB_COMMON_H__ +#ifndef __SMB_SERVER_COMMON_H__ +#define __SMB_SERVER_COMMON_H__#include <linux/kernel.h>
@@ -421,4 +421,4 @@ unsigned int ksmbd_server_side_copy_max_chunk_size(void);unsigned int ksmbd_server_side_copy_max_total_size (void );bool is_asterisk (char *p);__le32 smb_map_generic_desired_access (__le32 daccess); -#endif /* __SMB_COMMON_H__ */ +#endif /* __SMB_SERVER_COMMON_H__ */
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 4/7 ksmbd: rename smb2_get_msg to smb_get_msg
In reply to Sasha LevinFrom: Namjae Jeon <[email protected]>
[ Upstream commit 0b444cfd8b74ebce421ccd96eac9c495e536c92e ]
With the removal of the RFC1002 length field from the SMB header, smb2_get_msg is now used to get the smb1 request from the request buffer. Since this function is no longer exclusive to smb2 and now supports smb1 as well, This patch rename it to smb_get_msg to better reflect its usage.
Stable-dep-of: cfc0b8e5080a ("ksmbd: validate minimum PDU size for transform requests")
--- fs/smb/server/auth.c | 4 +-- fs/smb/server/connection.c | 2 +- fs/smb/server/oplock.c | 8 ++--- fs/smb/server/smb2pdu.c | 70 +++++++++++++++++++------------------- fs/smb/server/smb2pdu.h | 9 ----- fs/smb/server/smb_common.c | 6 ++-- fs/smb/server/smb_common.h | 9 +++++ 7 files changed, 54 insertions(+), 54 deletions(-)
fs/smb/server/auth.c +2 -2
@@ -920,7 +920,7 @@ int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf, __u8 *pi_hash) {int rc; -struct smb2_hdr *rcv_hdr =smb2_get_msg (buf); +struct smb2_hdr *rcv_hdr =smb_get_msg (buf);char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;int msg_size =get_rfc1002_len (buf);struct ksmbd_crypto_ctx *ctx =NULL ;
@@ -1108,7 +1108,7 @@ int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov, unsigned int nvec, int enc) {struct ksmbd_conn *conn = work->conn; -struct smb2_transform_hdr *tr_hdr =smb2_get_msg (iov[0 ].iov_base); +struct smb2_transform_hdr *tr_hdr =smb_get_msg (iov[0 ].iov_base);unsigned int assoc_data_len =sizeof (struct smb2_transform_hdr ) -20 ;int rc;DECLARE_CRYPTO_WAIT (wait);
fs/smb/server/connection.c +1 -1
@@ -475,7 +475,7 @@ int ksmbd_conn_handler_loop(void *p)if (!ksmbd_smb_request (conn))break ; -if (((struct smb2_hdr *)smb2_get_msg (conn->request_buf))->ProtocolId == +if (((struct smb2_hdr *)smb_get_msg (conn->request_buf))->ProtocolId ==SMB2_PROTO_NUMBER ) {if (pdu_size <SMB2_MIN_SUPPORTED_HEADER_SIZE )break ;
fs/smb/server/oplock.c +4 -4
@@ -663,7 +663,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) goto out; } - rsp_hdr =smb2_get_msg (work->response_buf); + rsp_hdr =smb_get_msg (work->response_buf);memset (rsp_hdr,0 ,sizeof (struct smb2_hdr ) +2 ); rsp_hdr->ProtocolId =SMB2_PROTO_NUMBER ; rsp_hdr->StructureSize =SMB2_HEADER_STRUCTURE_SIZE ;
@@ -677,7 +677,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) rsp_hdr->SessionId =0 ;memset (rsp_hdr->Signature,0 ,16 ); - rsp =smb2_get_msg (work->response_buf); + rsp =smb_get_msg (work->response_buf); rsp->StructureSize =cpu_to_le16 (24 ); if (!br_info->open_trunc &&
@@ -776,7 +776,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) goto out; } - rsp_hdr =smb2_get_msg (work->response_buf); + rsp_hdr =smb_get_msg (work->response_buf);memset (rsp_hdr,0 ,sizeof (struct smb2_hdr ) +2 ); rsp_hdr->ProtocolId =SMB2_PROTO_NUMBER ; rsp_hdr->StructureSize =SMB2_HEADER_STRUCTURE_SIZE ;
@@ -790,7 +790,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) rsp_hdr->SessionId =0 ;memset (rsp_hdr->Signature,0 ,16 ); - rsp =smb2_get_msg (work->response_buf); + rsp =smb_get_msg (work->response_buf); rsp->StructureSize =cpu_to_le16 (44 ); rsp->Epoch = br_info->epoch; rsp->Flags =0 ;
fs/smb/server/smb2pdu.c +35 -35
240 lines not on this page · raw message
fs/smb/server/smb2pdu.h +0 -9
@@ -496,15 +496,6 @@ int smb2_ioctl(struct ksmbd_work *work);int smb2_oplock_break (struct ksmbd_work *work);int smb2_notify (struct ksmbd_work *ksmbd_work); -/* -* Get the body of the smb2 message excluding the 4 byte rfc1002 headers -* from request/response buffer. -*/ -static inline void *smb2_get_msg (void *buf) -{ -return buf +4 ; -} -#define POSIX_TYPE_FILE 0#define POSIX_TYPE_DIR 1#define POSIX_TYPE_SYMLINK 2
fs/smb/server/smb_common.c +3 -3
@@ -163,7 +163,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn)if (conn->request_buf[0 ] !=0 )return false; - proto = (__le32 *)smb2_get_msg (conn->request_buf); + proto = (__le32 *)smb_get_msg (conn->request_buf);if (*proto ==SMB2_COMPRESSION_TRANSFORM_ID ) {pr_err_ratelimited ("smb2 compression not support yet" );return false;
@@ -259,14 +259,14 @@ int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count)static int ksmbd_negotiate_smb_dialect (void *buf) {int smb_buf_length =get_rfc1002_len (buf); -__le32 proto = ((struct smb2_hdr *)smb2_get_msg (buf))->ProtocolId; +__le32 proto = ((struct smb2_hdr *)smb_get_msg (buf))->ProtocolId;if (proto ==SMB2_PROTO_NUMBER ) {struct smb2_negotiate_req *req;int smb2_neg_size = offsetof(struct smb2_negotiate_req , Dialects); - req = (struct smb2_negotiate_req *)smb2_get_msg (buf); + req = (struct smb2_negotiate_req *)smb_get_msg (buf);if (smb2_neg_size > smb_buf_length) goto err_out;
fs/smb/server/smb_common.h +9 -0
@@ -421,4 +421,13 @@ unsigned int ksmbd_server_side_copy_max_chunk_size(void);unsigned int ksmbd_server_side_copy_max_total_size (void );bool is_asterisk (char *p);__le32 smb_map_generic_desired_access (__le32 daccess); + +/* +* Get the body of the smb message excluding the 4 byte rfc1002 headers +* from request/response buffer. +*/ +static inline void *smb_get_msg (void *buf) +{ +return buf +4 ; +}#endif /* __SMB_SERVER_COMMON_H__ */
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 5/7 smb/server: fix minimum SMB1 PDU size
In reply to Sasha LevinFrom: ChenXiaoSong <[email protected]>
[ Upstream commit 3b9c30eb8f5aaad4a54cdfa470b74c0467cc71e8 ]
Since the RFC1002 header has been removed from struct smb_hdr, the minimum SMB1 PDU size should be updated as well.
Stable-dep-of: cfc0b8e5080a ("ksmbd: validate minimum PDU size for transform requests")
--- fs/smb/server/connection.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/smb/server/connection.c +3 -2
@@ -376,7 +376,8 @@ bool ksmbd_conn_alive(struct ksmbd_conn *conn)return true; } -#define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr)) +/* "+2" for BCC field (ByteCount, 2 bytes) */ +#define SMB1_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb_hdr) + 2)#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)/**
@@ -444,7 +445,7 @@ int ksmbd_conn_handler_loop(void *p)if (pdu_size >MAX_STREAM_PROT_LEN )break ; -if (pdu_size <SMB1_MIN_SUPPORTED_HEADER_SIZE ) +if (pdu_size <SMB1_MIN_SUPPORTED_PDU_SIZE )break ;/* 4 for rfc1002 length field */
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 6/7 smb/server: fix minimum SMB2 PDU size
In reply to Sasha LevinFrom: ChenXiaoSong <[email protected]>
[ Upstream commit 4c7d8eb9a79ae5400eac19c4f6f0815bff674452 ]
The minimum SMB2 PDU size should be updated to the size of struct smb2_pdu (that is, the size of struct smb2_hdr + 2).
Stable-dep-of: cfc0b8e5080a ("ksmbd: validate minimum PDU size for transform requests")
--- fs/smb/server/connection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/smb/server/connection.c +2 -2
@@ -378,7 +378,7 @@ bool ksmbd_conn_alive(struct ksmbd_conn *conn)/* "+2" for BCC field (ByteCount, 2 bytes) */ #define SMB1_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb_hdr) + 2) -#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4) +#define SMB2_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb2_pdu))/** * ksmbd_conn_handler_loop() - session thread to listen on new smb requests
@@ -478,7 +478,7 @@ int ksmbd_conn_handler_loop(void *p)if (((struct smb2_hdr *)smb_get_msg (conn->request_buf))->ProtocolId ==SMB2_PROTO_NUMBER ) { -if (pdu_size <SMB2_MIN_SUPPORTED_HEADER_SIZE ) +if (pdu_size <SMB2_MIN_SUPPORTED_PDU_SIZE )break ; }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 7/7 ksmbd: validate minimum PDU size for transform requests
In reply to Sasha LevinFrom: Namjae Jeon <[email protected]>
[ Upstream commit cfc0b8e5080aec87700774e8568765eaa4b7b92b ]
The receive path applies the minimum SMB2 PDU size check only when ProtocolId is SMB2_PROTO_NUMBER. A packet carrying SMB2_TRANSFORM_PROTO_NUM bypasses the check even when the negotiated dialect does not provide transform handling.
On an SMB 2.1 connection, a short transform packet therefore reaches init_smb2_rsp_hdr(), which interprets the request as a full SMB2 header and reads beyond the request allocation. The copied fields can then be returned to the unauthenticated client.
Compression transforms are converted to ordinary SMB2 messages before protocol validation. After that conversion, validate ordinary SMB2 requests against SMB2_MIN_SUPPORTED_PDU_SIZE and require encryption transform requests to contain both a transform header and an SMB2 header. This rejects truncated requests before work allocation.
--- fs/smb/server/connection.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
fs/smb/server/connection.c +11 -5
@@ -379,6 +379,8 @@ bool ksmbd_conn_alive(struct ksmbd_conn *conn)/* "+2" for BCC field (ByteCount, 2 bytes) */ #define SMB1_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb_hdr) + 2)#define SMB2_MIN_SUPPORTED_PDU_SIZE (sizeof(struct smb2_pdu)) +#define SMB2_TRANSFORM_MIN_SUPPORTED_PDU_SIZE \ + (sizeof(struct smb2_transform_hdr) + sizeof(struct smb2_hdr))/** * ksmbd_conn_handler_loop() - session thread to listen on new smb requests
@@ -393,6 +395,7 @@ int ksmbd_conn_handler_loop(void *p)struct ksmbd_conn *conn = (struct ksmbd_conn *)p;struct ksmbd_transport *t = conn->transport;unsigned int pdu_size, max_allowed_pdu_size, max_req; +__le32 proto;char hdr_buf[4 ] = {0 ,};int size;
@@ -476,11 +479,14 @@ int ksmbd_conn_handler_loop(void *p)if (!ksmbd_smb_request (conn))break ; -if (((struct smb2_hdr *)smb_get_msg (conn->request_buf))->ProtocolId == -SMB2_PROTO_NUMBER ) { -if (pdu_size <SMB2_MIN_SUPPORTED_PDU_SIZE ) -break ; - } + proto = *(__le32 *)smb_get_msg (conn->request_buf); +if (proto ==SMB2_PROTO_NUMBER && + pdu_size <SMB2_MIN_SUPPORTED_PDU_SIZE ) +break ; + +if (proto ==SMB2_TRANSFORM_PROTO_NUM && + pdu_size <SMB2_TRANSFORM_MIN_SUPPORTED_PDU_SIZE ) +break ;if (!default_conn_ops.process_fn) {pr_err ("No connection request callback\n" );
Signature · 1 line
2.53.0