mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-12 15:38:37 +04:00
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:
1 parent
e1520c0619
commit
cfbfca7ee7
1 file changed
+110
+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;
|
||||
Reference in new issue
Block a user