kernel: 6.18: revert broken ksmbd SMB1 backport

Linux 6.18.46 included stable commit 29dbb4e29e1f ("ksmbd: Fix
to handle removal of rfc1002 header from smb_hdr"), a backport of
upstream commit 0a70cac78967.

The upstream change depends on SMB1 header refactoring that removed the
RFC1002 length field from struct smb_hdr. Those prerequisites are not
present in 6.18.y, where struct smb_hdr still contains smb_buf_length.

Consequently, smb_get_msg() advances the buffer by four bytes before
it is cast to a structure that already includes the RFC1002 field. This
creates a four-byte offset mismatch while parsing and constructing the
initial SMB1 multi-protocol negotiate response. Windows clients receive
a malformed response and abort the connection.

Apply the revert provided by ksmbd maintainer Namjae Jeon to restore
consistent SMB1 buffer handling in 6.18.y.

Drop this patch with the kernel bump that includes the stable revert.

Fixes: 87e5289908 ("kernel: bump 6.18 to 6.18.46")
Link: https://git.kernel.org/torvalds/c/83bfbd0bb9025f98fa62b44f93bd67466773d1db
Link: https://git.kernel.org/torvalds/c/0a70cac7896712a08e3cd22c16f44be976d40dbf
Tested-by: Andrea Pesaresi <andreapesaresi82@gmail.com>
Tested-on: GL.iNet GL-MT3000
Signed-off-by: Andrea Pesaresi <andreapesaresi82@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/25271
Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
Andrea Pesaresi authored and Robert Marko committed 2026-09-20 17:33:57 +02:00
1 parent e1520c0619
commit cfbfca7ee7
1 file changed
+110
@@ -0,0 +1,110 @@
From ec0705f23e8780a43f75827d408e5427c1d1174b Mon Sep 17 00:00:00 2001
From: Namjae Jeon <linkinjeon@kernel.org>
Date: Sat, 19 Sep 2026 13:48:56 +0900
Subject: [PATCH] Revert "ksmbd: Fix to handle removal of rfc1002 header from
smb_hdr"
Commit 29dbb4e29e1f ("ksmbd: Fix to handle removal of rfc1002 header
from smb_hdr") is a backport of upstream commit 0a70cac78967.
The upstream commit depends on SMB1 header refactoring which removed the
RFC1002 length field from struct smb_hdr. Those prerequisite changes are
not present in the 6.18.y stable tree, where ksmbd still defines struct
smb_hdr with the smb_buf_length field.
As a result, smb_get_msg() advances the buffer by four bytes before it is
cast to a structure that already includes the RFC1002 field. This causes a
four-byte offset mismatch while parsing and constructing the initial SMB1
multi-protocol negotiate response.
Windows clients then receive a malformed negotiate response and abort the
connection.
This reverts commit 29dbb4e29e1f ("ksmbd: Fix to handle removal of
rfc1002 header from smb_hdr").
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
---
fs/smb/server/server.c | 2 +-
fs/smb/server/smb_common.c | 20 ++++++++++----------
2 files changed, 11 insertions(+), 11 deletions(-)
--- a/fs/smb/server/server.c
+++ b/fs/smb/server/server.c
@@ -95,7 +95,7 @@ static inline int check_conn_state(struc
if (ksmbd_conn_exiting(work->conn) ||
ksmbd_conn_need_reconnect(work->conn)) {
- rsp_hdr = smb_get_msg(work->response_buf);
+ rsp_hdr = work->response_buf;
rsp_hdr->Status.CifsError = STATUS_CONNECTION_DISCONNECTED;
return 1;
}
--- a/fs/smb/server/smb_common.c
+++ b/fs/smb/server/smb_common.c
@@ -140,7 +140,7 @@ int ksmbd_verify_smb_message(struct ksmb
if (smb2_hdr->ProtocolId == SMB2_PROTO_NUMBER)
return ksmbd_smb2_check_message(work);
- hdr = smb_get_msg(work->request_buf);
+ hdr = work->request_buf;
if (*(__le32 *)hdr->Protocol == SMB1_PROTO_NUMBER &&
hdr->Command == SMB_COM_NEGOTIATE) {
work->conn->outstanding_credits++;
@@ -278,14 +278,15 @@ static int ksmbd_negotiate_smb_dialect(v
req->DialectCount);
}
+ proto = *(__le32 *)((struct smb_hdr *)buf)->Protocol;
if (proto == SMB1_PROTO_NUMBER) {
struct smb_negotiate_req *req;
- req = (struct smb_negotiate_req *)smb_get_msg(buf);
+ req = (struct smb_negotiate_req *)buf;
if (le16_to_cpu(req->ByteCount) < 2)
goto err_out;
- if (offsetof(struct smb_negotiate_req, DialectsArray) +
+ if (offsetof(struct smb_negotiate_req, DialectsArray) - 4 +
le16_to_cpu(req->ByteCount) > smb_buf_length) {
goto err_out;
}
@@ -319,8 +320,8 @@ static u16 get_smb1_cmd_val(struct ksmbd
*/
static int init_smb1_rsp_hdr(struct ksmbd_work *work)
{
- struct smb_hdr *rsp_hdr = (struct smb_hdr *)smb_get_msg(work->response_buf);
- struct smb_hdr *rcv_hdr = (struct smb_hdr *)smb_get_msg(work->request_buf);
+ struct smb_hdr *rsp_hdr = (struct smb_hdr *)work->response_buf;
+ struct smb_hdr *rcv_hdr = (struct smb_hdr *)work->request_buf;
rsp_hdr->Command = SMB_COM_NEGOTIATE;
*(__le32 *)rsp_hdr->Protocol = SMB1_PROTO_NUMBER;
@@ -411,10 +412,9 @@ static int init_smb1_server(struct ksmbd
int ksmbd_init_smb_server(struct ksmbd_conn *conn)
{
- struct smb_hdr *rcv_hdr = (struct smb_hdr *)smb_get_msg(conn->request_buf);
__le32 proto;
- proto = *(__le32 *)rcv_hdr->Protocol;
+ proto = *(__le32 *)((struct smb_hdr *)conn->request_buf)->Protocol;
if (conn->need_neg == false) {
if (proto == SMB1_PROTO_NUMBER)
return -EINVAL;
@@ -572,12 +572,12 @@ static int __smb2_negotiate(struct ksmbd
static int smb_handle_negotiate(struct ksmbd_work *work)
{
- struct smb_negotiate_rsp *neg_rsp = smb_get_msg(work->response_buf);
+ struct smb_negotiate_rsp *neg_rsp = work->response_buf;
ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
- if (ksmbd_iov_pin_rsp(work, (void *)neg_rsp,
- sizeof(struct smb_negotiate_rsp)))
+ if (ksmbd_iov_pin_rsp(work, (void *)neg_rsp + 4,
+ sizeof(struct smb_negotiate_rsp) - 4))
return -ENOMEM;
neg_rsp->hdr.Status.CifsError = STATUS_SUCCESS;