Linux kernel -stable discussions
 help / color / mirror / Atom feed
* FAILED: patch "[PATCH] ksmbd: prevent out-of-bounds reads in share config responses" failed to apply to 5.15-stable tree
@ 2026-09-14 11:03 gregkh
  2026-09-14 18:43 ` [PATCH 5.15.y 1/5] ksmbd: Use struct_size() to improve smb_direct_rdma_xmit() Sasha Levin
  0 siblings, 1 reply; 6+ messages in thread
From: gregkh @ 2026-09-14 11:03 UTC (permalink / raw)
  To: linkinjeon, farhad.alemi, kpskanna1915; +Cc: stable


The patch below does not apply to the 5.15-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 <stable@vger.kernel.org>.

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-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x f25e93768fcc5d8287e50b1ec52a42e4c276df34
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026091413-gills-macarena-de56@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'

Possible dependencies:



thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From f25e93768fcc5d8287e50b1ec52a42e4c276df34 Mon Sep 17 00:00:00 2001
From: Namjae Jeon <linkinjeon@kernel.org>
Date: Fri, 28 Aug 2026 08:39:57 +0900
Subject: [PATCH] ksmbd: prevent out-of-bounds reads in share config responses

Validate IPC share configuration payload sizes before consuming
variable-length fields. Bound veto list parsing and account for
the separator byte when deriving the path length.

Fixes: a677ebd8ca2f ("ksmbd: validate payload size in ipc response")
Reported-by: Kanishka De Silva <kpskanna1915@gmail.com>
Reported-by: Farhad Alemi <farhad.alemi@berkeley.edu>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>

diff --git a/fs/smb/server/mgmt/share_config.c b/fs/smb/server/mgmt/share_config.c
index b2d9580bddc6..cc9f18ede80d 100644
--- a/fs/smb/server/mgmt/share_config.c
+++ b/fs/smb/server/mgmt/share_config.c
@@ -146,9 +146,9 @@ static struct ksmbd_share_config *__share_lookup(const char *name)
 
 static int parse_veto_list(struct ksmbd_share_config *share,
 			   char *veto_list,
-			   int veto_list_sz)
+			   size_t veto_list_sz)
 {
-	int sz = 0;
+	size_t sz;
 
 	if (!veto_list_sz)
 		return 0;
@@ -156,7 +156,7 @@ static int parse_veto_list(struct ksmbd_share_config *share,
 	while (veto_list_sz > 0) {
 		struct ksmbd_veto_pattern *p;
 
-		sz = strlen(veto_list);
+		sz = strnlen(veto_list, veto_list_sz);
 		if (!sz)
 			break;
 
@@ -164,7 +164,7 @@ static int parse_veto_list(struct ksmbd_share_config *share,
 		if (!p)
 			return -ENOMEM;
 
-		p->pattern = kstrdup(veto_list, KSMBD_DEFAULT_GFP);
+		p->pattern = kstrndup(veto_list, sz, KSMBD_DEFAULT_GFP);
 		if (!p->pattern) {
 			kfree(p);
 			return -ENOMEM;
@@ -172,6 +172,9 @@ static int parse_veto_list(struct ksmbd_share_config *share,
 
 		list_add(&p->list, &share->veto_list);
 
+		if (sz == veto_list_sz)
+			break;
+
 		veto_list += sz + 1;
 		veto_list_sz -= (sz + 1);
 	}
@@ -224,17 +227,28 @@ static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work,
 	}
 
 	if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
-		int path_len = PATH_MAX;
+		size_t path_len;
 
-		if (resp->payload_sz)
-			path_len = resp->payload_sz - resp->veto_list_sz;
-
-		share->path = kstrndup(ksmbd_share_config_path(resp), path_len,
-				      KSMBD_DEFAULT_GFP);
-		if (!share->path) {
-			ret = -ENOMEM;
+		if (resp->payload_sz <= resp->veto_list_sz) {
+			ret = -EINVAL;
 		} else {
-			ret = 0;
+			path_len = resp->payload_sz - resp->veto_list_sz;
+			if (resp->veto_list_sz)
+				path_len--;
+
+			if (!path_len) {
+				ret = -EINVAL;
+			} else {
+				share->path = kstrndup(
+					ksmbd_share_config_path(resp),
+					path_len, KSMBD_DEFAULT_GFP);
+				if (!share->path)
+					ret = -ENOMEM;
+				else
+					ret = 0;
+			}
+		}
+		if (share->path) {
 			share->path_sz = strlen(share->path);
 			while (share->path_sz > 1 &&
 			       share->path[share->path_sz - 1] == '/')
diff --git a/fs/smb/server/transport_ipc.c b/fs/smb/server/transport_ipc.c
index 4b0b572a3e1b..e550aa41ad2c 100644
--- a/fs/smb/server/transport_ipc.c
+++ b/fs/smb/server/transport_ipc.c
@@ -532,14 +532,21 @@ static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
 		if (entry->msg_sz < sizeof(struct ksmbd_share_config_response))
 			return -EINVAL;
 
-		if (resp->payload_sz) {
-			if (resp->payload_sz < resp->veto_list_sz)
-				return -EINVAL;
+		if (strnlen(resp->share_name, sizeof(resp->share_name)) ==
+		    sizeof(resp->share_name))
+			return -EINVAL;
 
-			if (check_add_overflow(sizeof(struct ksmbd_share_config_response),
-					       resp->payload_sz, &msg_sz))
-				return -EINVAL;
-		}
+		if (resp->veto_list_sz > resp->payload_sz)
+			return -EINVAL;
+
+		if (resp->flags != KSMBD_SHARE_FLAG_INVALID &&
+		    !(resp->flags & KSMBD_SHARE_FLAG_PIPE) &&
+		    resp->payload_sz <= resp->veto_list_sz)
+			return -EINVAL;
+
+		if (check_add_overflow(sizeof(struct ksmbd_share_config_response),
+				       resp->payload_sz, &msg_sz))
+			return -EINVAL;
 		break;
 	}
 	case KSMBD_EVENT_LOGIN_REQUEST_EXT:


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5.15.y 1/5] ksmbd: Use struct_size() to improve smb_direct_rdma_xmit()
  2026-09-14 11:03 FAILED: patch "[PATCH] ksmbd: prevent out-of-bounds reads in share config responses" failed to apply to 5.15-stable tree gregkh
@ 2026-09-14 18:43 ` Sasha Levin
  2026-09-14 18:43   ` [PATCH 5.15.y 2/5] ksmbd: use __GFP_RETRY_MAYFAIL Sasha Levin
                     ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-14 18:43 UTC (permalink / raw)
  To: stable; +Cc: Thorsten Blum, Namjae Jeon, Steve French, Sasha Levin

From: Thorsten Blum <thorsten.blum@linux.dev>

[ Upstream commit 9c383396362a4d1db99ed5240f4708d443361ef3 ]

Use struct_size() to calculate the number of bytes to allocate for a
new message.

Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Stable-dep-of: f25e93768fcc ("ksmbd: prevent out-of-bounds reads in share config responses")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/ksmbd/transport_rdma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c
index 6ea73fe6de6c5..5e0d821d0807e 100644
--- a/fs/ksmbd/transport_rdma.c
+++ b/fs/ksmbd/transport_rdma.c
@@ -1380,8 +1380,8 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
 	/* build rdma_rw_ctx for each descriptor */
 	desc_buf = buf;
 	for (i = 0; i < desc_num; i++) {
-		msg = kzalloc(offsetof(struct smb_direct_rdma_rw_msg, sg_list) +
-			      sizeof(struct scatterlist) * SG_CHUNK_SIZE, GFP_KERNEL);
+		msg = kzalloc(struct_size(msg, sg_list, SG_CHUNK_SIZE),
+			      GFP_KERNEL);
 		if (!msg) {
 			ret = -ENOMEM;
 			goto out;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5.15.y 2/5] ksmbd: use __GFP_RETRY_MAYFAIL
  2026-09-14 18:43 ` [PATCH 5.15.y 1/5] ksmbd: Use struct_size() to improve smb_direct_rdma_xmit() Sasha Levin
@ 2026-09-14 18:43   ` Sasha Levin
  2026-09-14 18:43   ` [PATCH 5.15.y 3/5] ksmbd: validate response sizes in ipc_validate_msg() Sasha Levin
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-14 18:43 UTC (permalink / raw)
  To: stable; +Cc: Namjae Jeon, Steve French, Sasha Levin

From: Namjae Jeon <linkinjeon@kernel.org>

[ Upstream commit 0066f623bce8f98b69b752ee03d46a5047c281b8 ]

Prefer to report ENOMEM rather than incur the oom for allocations in
ksmbd. __GFP_NORETRY could not achieve that, It would fail the allocations
just too easily. __GFP_RETRY_MAYFAIL will keep retrying the allocation
until there is no more progress and fail the allocation instead go OOM
and let the caller to deal with it.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>

[ Stable dependency adaptation for f25e93768fcc5d8287e50b1ec52a42e4c276df34:
  Keep the default allocation mask and its uses in share_config.c and
  transport_ipc.c. Drop unrelated allocation conversions, including the
  hunks that require IDA, supplementary-group, RPC, interface, or durable
  handle code not present in this stable tree.

  Prepare the existing share-config path for the target by retaining path
  allocation failures and only parsing the veto list on success, as in
  a74668eb2c0b. Convert the existing IPC validator to a switch for its three
  supported request types; add the share-response header-length check and
  checked size addition needed by the target, from e9b33376bd07 and
  d6a6aa81eac2. Do not introduce extended-login support or new functions. ]

[ sashal: Reduced backport -- upstream 0066f623bce8f touches 24 file(s), this
  backport carries 3. Not backported here:
  fs/smb/server/asn1.c
  fs/smb/server/auth.c
  fs/smb/server/connection.c
  fs/smb/server/crypto_ctx.c
  fs/smb/server/ksmbd_work.c
  fs/smb/server/mgmt/ksmbd_ida.c
  fs/smb/server/mgmt/tree_connect.c
  fs/smb/server/mgmt/user_config.c
  ... and 13 more
  This note is generated from the file lists only; see the resolution record
  for the reasoning. ]

Stable-dep-of: f25e93768fcc ("ksmbd: prevent out-of-bounds reads in share config responses")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/ksmbd/glob.h              |  2 ++
 fs/ksmbd/mgmt/share_config.c | 22 +++++++++++++---------
 fs/ksmbd/transport_ipc.c     | 31 +++++++++++++++++++++++--------
 3 files changed, 38 insertions(+), 17 deletions(-)

diff --git a/fs/ksmbd/glob.h b/fs/ksmbd/glob.h
index 5b8f3e0ebdb36..3ce12b60e46fe 100644
--- a/fs/ksmbd/glob.h
+++ b/fs/ksmbd/glob.h
@@ -46,4 +46,6 @@ extern int ksmbd_debug_types;
 
 #define UNICODE_LEN(x)		((x) * 2)
 
+#define KSMBD_DEFAULT_GFP	(GFP_KERNEL | __GFP_RETRY_MAYFAIL)
+
 #endif /* __KSMBD_GLOB_H */
diff --git a/fs/ksmbd/mgmt/share_config.c b/fs/ksmbd/mgmt/share_config.c
index e0a6b758094fc..bd31f4c75201e 100644
--- a/fs/ksmbd/mgmt/share_config.c
+++ b/fs/ksmbd/mgmt/share_config.c
@@ -101,11 +101,11 @@ static int parse_veto_list(struct ksmbd_share_config *share,
 		if (!sz)
 			break;
 
-		p = kzalloc(sizeof(struct ksmbd_veto_pattern), GFP_KERNEL);
+		p = kzalloc(sizeof(struct ksmbd_veto_pattern), KSMBD_DEFAULT_GFP);
 		if (!p)
 			return -ENOMEM;
 
-		p->pattern = kstrdup(veto_list, GFP_KERNEL);
+		p->pattern = kstrdup(veto_list, KSMBD_DEFAULT_GFP);
 		if (!p->pattern) {
 			kfree(p);
 			return -ENOMEM;
@@ -148,14 +148,14 @@ static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
 			goto out;
 	}
 
-	share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);
+	share = kzalloc(sizeof(struct ksmbd_share_config), KSMBD_DEFAULT_GFP);
 	if (!share)
 		goto out;
 
 	share->flags = resp->flags;
 	atomic_set(&share->refcount, 1);
 	INIT_LIST_HEAD(&share->veto_list);
-	share->name = kstrdup(name, GFP_KERNEL);
+	share->name = kstrdup(name, KSMBD_DEFAULT_GFP);
 
 	if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
 		int path_len = PATH_MAX;
@@ -164,8 +164,11 @@ static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
 			path_len = resp->payload_sz - resp->veto_list_sz;
 
 		share->path = kstrndup(ksmbd_share_config_path(resp), path_len,
-				      GFP_KERNEL);
-		if (share->path) {
+				      KSMBD_DEFAULT_GFP);
+		if (!share->path) {
+			ret = -ENOMEM;
+		} else {
+			ret = 0;
 			share->path_sz = strlen(share->path);
 			while (share->path_sz > 1 &&
 			       share->path[share->path_sz - 1] == '/')
@@ -177,9 +180,10 @@ static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
 		share->force_directory_mode = resp->force_directory_mode;
 		share->force_uid = resp->force_uid;
 		share->force_gid = resp->force_gid;
-		ret = parse_veto_list(share,
-				      KSMBD_SHARE_CONFIG_VETO_LIST(resp),
-				      resp->veto_list_sz);
+		if (!ret)
+			ret = parse_veto_list(share,
+					      KSMBD_SHARE_CONFIG_VETO_LIST(resp),
+					      resp->veto_list_sz);
 		if (!ret && share->path) {
 			ret = kern_path(share->path, 0, &share->vfs_path);
 			if (ret) {
diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
index 7e6003c6cd9bf..272f8f0b3a40a 100644
--- a/fs/ksmbd/transport_ipc.c
+++ b/fs/ksmbd/transport_ipc.c
@@ -13,6 +13,7 @@
 #include <net/genetlink.h>
 #include <linux/socket.h>
 #include <linux/workqueue.h>
+#include <linux/overflow.h>
 
 #include "vfs_cache.h"
 #include "transport_ipc.h"
@@ -229,7 +230,7 @@ static struct ksmbd_ipc_msg *ipc_msg_alloc(size_t sz)
 	struct ksmbd_ipc_msg *msg;
 	size_t msg_sz = sz + sizeof(struct ksmbd_ipc_msg);
 
-	msg = kvzalloc(msg_sz, GFP_KERNEL);
+	msg = kvzalloc(msg_sz, KSMBD_DEFAULT_GFP);
 	if (msg)
 		msg->sz = sz;
 	return msg;
@@ -268,7 +269,7 @@ static int handle_response(int type, void *payload, size_t sz)
 			       entry->type + 1, type);
 		}
 
-		entry->response = kvzalloc(sz, GFP_KERNEL);
+		entry->response = kvzalloc(sz, KSMBD_DEFAULT_GFP);
 		if (!entry->response) {
 			ret = -ENOMEM;
 			break;
@@ -434,7 +435,7 @@ static int ipc_msg_send(struct ksmbd_ipc_msg *msg)
 	if (!ksmbd_tools_pid)
 		return ret;
 
-	skb = genlmsg_new(msg->sz, GFP_KERNEL);
+	skb = genlmsg_new(msg->sz, KSMBD_DEFAULT_GFP);
 	if (!skb)
 		return -ENOMEM;
 
@@ -463,25 +464,39 @@ static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
 {
 	unsigned int msg_sz = entry->msg_sz;
 
-	if (entry->type == KSMBD_EVENT_RPC_REQUEST) {
+	switch (entry->type) {
+	case KSMBD_EVENT_RPC_REQUEST:
+	{
 		struct ksmbd_rpc_command *resp = entry->response;
 
 		msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz;
-	} else if (entry->type == KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST) {
+		break;
+	}
+	case KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST:
+	{
 		struct ksmbd_spnego_authen_response *resp = entry->response;
 
 		msg_sz = sizeof(struct ksmbd_spnego_authen_response) +
 				resp->session_key_len + resp->spnego_blob_len;
-	} else if (entry->type == KSMBD_EVENT_SHARE_CONFIG_REQUEST) {
+		break;
+	}
+	case KSMBD_EVENT_SHARE_CONFIG_REQUEST:
+	{
 		struct ksmbd_share_config_response *resp = entry->response;
 
+		if (entry->msg_sz < sizeof(struct ksmbd_share_config_response))
+			return -EINVAL;
+
 		if (resp->payload_sz) {
 			if (resp->payload_sz < resp->veto_list_sz)
 				return -EINVAL;
 
-			msg_sz = sizeof(struct ksmbd_share_config_response) +
-					resp->payload_sz;
+			if (check_add_overflow(sizeof(struct ksmbd_share_config_response),
+					       resp->payload_sz, &msg_sz))
+				return -EINVAL;
 		}
+		break;
+	}
 	}
 
 	return entry->msg_sz != msg_sz ? -EINVAL : 0;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5.15.y 3/5] ksmbd: validate response sizes in ipc_validate_msg()
  2026-09-14 18:43 ` [PATCH 5.15.y 1/5] ksmbd: Use struct_size() to improve smb_direct_rdma_xmit() Sasha Levin
  2026-09-14 18:43   ` [PATCH 5.15.y 2/5] ksmbd: use __GFP_RETRY_MAYFAIL Sasha Levin
@ 2026-09-14 18:43   ` Sasha Levin
  2026-09-14 18:43   ` [PATCH 5.15.y 4/5] ksmbd: validate ipc response length before dereferencing its fields Sasha Levin
  2026-09-14 18:43   ` [PATCH 5.15.y 5/5] ksmbd: prevent out-of-bounds reads in share config responses Sasha Levin
  3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-14 18:43 UTC (permalink / raw)
  To: stable; +Cc: Michael Bommarito, Namjae Jeon, Steve French, Sasha Levin

From: Michael Bommarito <michael.bommarito@gmail.com>

[ Upstream commit d6a6aa81eac2c9bff66dc6e191179cb69a14426b ]

ipc_validate_msg() computes the expected message size for each
response type by adding (or multiplying) attacker-controlled fields
from the daemon response to a fixed struct size in unsigned int
arithmetic.  Three cases can overflow:

  KSMBD_EVENT_RPC_REQUEST:
      msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz;
  KSMBD_EVENT_SHARE_CONFIG_REQUEST:
      msg_sz = sizeof(struct ksmbd_share_config_response) +
               resp->payload_sz;
  KSMBD_EVENT_LOGIN_REQUEST_EXT:
      msg_sz = sizeof(struct ksmbd_login_response_ext) +
               resp->ngroups * sizeof(gid_t);

resp->payload_sz is __u32 and resp->ngroups is __s32.  Each addition
can wrap in unsigned int; the multiplication by sizeof(gid_t) mixes
signed and size_t, so a negative ngroups is converted to SIZE_MAX
before the multiply.  A wrapped value of msg_sz that happens to
equal entry->msg_sz bypasses the size check on the next line, and
downstream consumers (smb2pdu.c:6742 memcpy using rpc_resp->payload_sz,
kmemdup in ksmbd_alloc_user using resp_ext->ngroups) then trust the
unverified length.

Use check_add_overflow() on the RPC_REQUEST and SHARE_CONFIG_REQUEST
paths to detect integer overflow without constraining functional
payload size; userspace ksmbd-tools grows NDR responses in 4096-byte
chunks for calls like NetShareEnumAll, so a hard transport cap is
unworkable on the response side.  For LOGIN_REQUEST_EXT, reject
resp->ngroups outside the signed [0, NGROUPS_MAX] range up front and
report the error from ipc_validate_msg() so it fires at the IPC
boundary; with that bound the subsequent multiplication and addition
stay well below UINT_MAX.  The now-redundant ngroups check and
pr_err in ksmbd_alloc_user() are removed.

This is the response-side analogue of aab98e2dbd64 ("ksmbd: fix
integer overflows on 32 bit systems"), which hardened the request
side.

Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers")
Fixes: a77e0e02af1c ("ksmbd: add support for supplementary groups")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-6
Assisted-by: Codex:gpt-5-4
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>

[ Stable dependency adaptation for f25e93768fcc5d8287e50b1ec52a42e4c276df34:
  Retain the RPC response-size overflow check in ipc_validate_msg().
  The previous dependency, 2d1f4c041770, already supplied the overflow
  header and the share-response checked addition required by the target.

  Drop both supplementary-group hunks: this stable tree has neither
  extended-login IPC messages nor supplementary-group fields in ksmbd_user.
  Keep user_config.c unchanged and do not introduce extended-login support
  or any new functions. The target applies cleanly by three-way application
  with the existing share-config preparation and this reduced dependency. ]

[ sashal: Reduced backport -- upstream d6a6aa81eac2c touches 2 file(s), this
  backport carries 1. Not backported here:
  fs/smb/server/mgmt/user_config.c
  This note is generated from the file lists only; see the resolution record
  for the reasoning. ]

Stable-dep-of: f25e93768fcc ("ksmbd: prevent out-of-bounds reads in share config responses")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/ksmbd/transport_ipc.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
index 272f8f0b3a40a..12fa21bf84918 100644
--- a/fs/ksmbd/transport_ipc.c
+++ b/fs/ksmbd/transport_ipc.c
@@ -469,7 +469,9 @@ static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
 	{
 		struct ksmbd_rpc_command *resp = entry->response;
 
-		msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz;
+		if (check_add_overflow(sizeof(struct ksmbd_rpc_command),
+				       resp->payload_sz, &msg_sz))
+			return -EINVAL;
 		break;
 	}
 	case KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST:
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5.15.y 4/5] ksmbd: validate ipc response length before dereferencing its fields
  2026-09-14 18:43 ` [PATCH 5.15.y 1/5] ksmbd: Use struct_size() to improve smb_direct_rdma_xmit() Sasha Levin
  2026-09-14 18:43   ` [PATCH 5.15.y 2/5] ksmbd: use __GFP_RETRY_MAYFAIL Sasha Levin
  2026-09-14 18:43   ` [PATCH 5.15.y 3/5] ksmbd: validate response sizes in ipc_validate_msg() Sasha Levin
@ 2026-09-14 18:43   ` Sasha Levin
  2026-09-14 18:43   ` [PATCH 5.15.y 5/5] ksmbd: prevent out-of-bounds reads in share config responses Sasha Levin
  3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-14 18:43 UTC (permalink / raw)
  To: stable; +Cc: Yunseong Kim, Namjae Jeon, Sasha Levin

From: Yunseong Kim <yunseong.kim@est.tech>

[ Upstream commit e9b33376bd07bca4175f7bcc2d6034ef250f8181 ]

ipc_validate_msg() computes the expected message size by reading length
fields out of the response buffer supplied by the userspace ksmbd daemon
(payload_sz, session_key_len, ngroups, ...).  Those fields are read before
the buffer is verified to be large enough to contain the struct they belong
to, so a short response makes the read land past the end of the allocation.

handle_response() sizes entry->response purely from the netlink attribute
length (nla_len()) and only guards the leading handle read, so the daemon
can install a response as small as the kmalloc-8 object seen below.  When
ipc_msg_send_request() then calls ipc_validate_msg() for a
KSMBD_EVENT_RPC_REQUEST, the cast to struct ksmbd_rpc_command reads
resp->payload_sz at offset 8 of an 8-byte allocation:

[ 3697.841381] ==================================================================
[ 3697.844099] BUG: KASAN: slab-out-of-bounds in ipc_msg_send_request+0x763/0x800
[ 3697.846604] Read of size 4 at addr ffff888105f95910 by task kworker/4:3/20682
[ 3697.849061]
[ 3697.849801] CPU: 4 UID: 0 PID: 20682 Comm: kworker/4:3 Not tainted 7.2.0-rc3-next-20260717-virtme #117 PREEMPT(lazy)
[ 3697.850077] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
[ 3697.850303] Workqueue: ksmbd-io handle_ksmbd_work
[ 3697.850592] Call Trace:
[ 3697.850794]  <TASK>
[ 3697.850952]  __dump_stack+0x21/0x60
[ 3697.851239]  dump_stack_lvl+0xc2/0x100
[ 3697.851528]  print_address_description+0x77/0x200
[ 3697.851816]  ? ipc_msg_send_request+0x763/0x800
[ 3697.852024]  print_report+0x58/0x70
[ 3697.852316]  kasan_report+0x117/0x150
[ 3697.852585]  ? down_write+0x146/0x1f0
[ 3697.852809]  ? ipc_msg_send_request+0x763/0x800
[ 3697.853082]  ipc_msg_send_request+0x763/0x800
[ 3697.853385]  ? __pfx_ipc_msg_send_request+0x10/0x10
[ 3697.853604]  ? kasan_unpoison+0x48/0x70
[ 3697.853936]  ? __pfx___up_read+0x10/0x10
[ 3697.854221]  ksmbd_rpc_ioctl+0x380/0x520
[ 3697.854542]  ? __pfx_ksmbd_rpc_ioctl+0x10/0x10
[ 3697.854757]  ? kasan_unpoison+0x48/0x70
[ 3697.854962]  ? copy_from_kernel_nofault+0x32c/0x4e0
[ 3697.855166]  ? kasan_unpoison+0x48/0x70
[ 3697.855416]  fsctl_pipe_transceive+0x139/0x7a0
[ 3697.855705]  ? __pfx_copy_from_kernel_nofault+0x10/0x10
[ 3697.855937]  ? __pfx_fsctl_pipe_transceive+0x10/0x10
[ 3697.856388]  ? __sanitizer_cov_trace_switch+0x7b/0x140
[ 3697.856620]  smb2_ioctl+0x1141/0x3420
[ 3697.856994]  ? __pfx_smb2_ioctl+0x10/0x10
[ 3697.857182]  ? get_smb2_cmd_val+0xe3/0x1c0
[ 3697.857655]  handle_ksmbd_work+0x9ad/0x15e0
[ 3697.858034]  ? __pfx_handle_ksmbd_work+0x10/0x10
[ 3697.858251]  ? lock_release+0xf7/0x360
[ 3697.858466]  ? process_scheduled_works+0x954/0x1600
[ 3697.858698]  ? process_scheduled_works+0x954/0x1600
[ 3697.858905]  process_scheduled_works+0xc22/0x1600
[ 3697.859368]  ? __pfx_process_scheduled_works+0x10/0x10
[ 3697.859637]  ? __pfx_assign_work+0x10/0x10
[ 3697.859896]  ? lock_is_held_type+0x7b/0x110
[ 3697.860146]  worker_thread+0x975/0xee0
[ 3697.860524]  ? __pfx_do_raw_spin_lock+0x10/0x10
[ 3697.860830]  ? __kthread_parkme+0x21e/0x260
[ 3697.861105]  kthread+0x3a6/0x490
[ 3697.861423]  ? __pfx_worker_thread+0x10/0x10
[ 3697.861643]  ? __pfx_kthread+0x10/0x10
[ 3697.861878]  ret_from_fork+0x55a/0xa20
[ 3697.862194]  ? __pfx_ret_from_fork+0x10/0x10
[ 3697.862480]  ? __pfx_kthread+0x10/0x10
[ 3697.862714]  ret_from_fork_asm+0x1a/0x30
[ 3697.862965]  </TASK>
[ 3697.863039]
[ 3697.938882] Allocated by task 20761:
[ 3697.940257]  kasan_save_track+0x3e/0x80
[ 3697.941782]  __kasan_kmalloc+0x72/0x90
[ 3697.943228]  __kvmalloc_node_noprof+0x3e9/0x6a0
[ 3697.944948]  handle_generic_event+0x59b/0x750
[ 3697.946592]  genl_family_rcv_msg_doit+0x3d6/0x560
[ 3697.946977]  genl_rcv_msg+0x67c/0x900
[ 3697.947224]  netlink_rcv_skb+0x286/0x580
[ 3697.947488]  genl_rcv+0x2d/0x80
[ 3697.947706]  netlink_unicast+0x937/0xb70
[ 3697.947993]  netlink_sendmsg+0x977/0xc10
[ 3697.948268]  __sock_sendmsg+0x264/0x2d0
[ 3697.948536]  __sys_sendto+0x4de/0x690
[ 3697.948789]  __x64_sys_sendto+0x173/0x380
[ 3697.949069]  do_syscall_64+0x13d/0x420
[ 3697.949328]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 3697.949662]
[ 3697.949779] The buggy address belongs to the object at ffff888105f95908
[ 3697.949779]  which belongs to the cache kmalloc-8 of size 8
[ 3697.950550] The buggy address is located 0 bytes to the right of
[ 3697.950550]  allocated 8-byte region [ffff888105f95908, ffff888105f95910)
[ 3697.951455]
[ 3697.951574] The buggy address belongs to the physical page:
[ 3697.951958] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff888105f951b8 pfn:0x105f95
[ 3697.952571] flags: 0x100000000000200(workingset|node=0|zone=2)
[ 3697.952973] page_type: f5(slab)
[ 3697.953198] raw: 0100000000000200 ffff888100042640 ffffea0004063610 ffff888100040588
[ 3697.953707] raw: ffff888105f951b8 00000000001c000e 00000000f5000000 0000000000000000
[ 3697.954240] page dumped because: kasan: bad access detected
[ 3697.954616]
[ 3697.954734] Memory state around the buggy address:
[ 3697.955063]  ffff888105f95800: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fa
[ 3697.955534]  ffff888105f95880: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 3697.956006] >ffff888105f95900: fc 00 fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 3697.956477]                          ^
[ 3697.956728]  ffff888105f95980: fc fc fc fa fc fc fc fc fc fc fc fc fc fc fc fc
[ 3697.957202]  ffff888105f95a00: fc fc fc fc fc fa fc fc fc fc fc fc fc fc fc fc
[ 3697.957671] ==================================================================

The final "entry->msg_sz != msg_sz" comparison cannot help: the offending
read has already happened by the time it runs.  Every case in the switch
shares this pattern.

Floor entry->msg_sz against the base struct of each event type before
dereferencing any of its length fields.  On failure ipc_msg_send_request()
already frees the response and returns NULL, so callers stay safe.

The malformed message originates from the ksmbd.mountd daemon over genl
netlink rather than a remote SMB client, so triggering it requires a buggy
or compromised daemon; it is still an out-of-bounds read the validator is
meant to prevent.

Fixes: d6a6aa81eac2 ("ksmbd: validate response sizes in ipc_validate_msg()")
Signed-off-by: Yunseong Kim <yunseong.kim@est.tech>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>

[ Stable dependency adaptation for f25e93768fcc5d8287e50b1ec52a42e4c276df34:
  Retain the minimum response-header checks for RPC and SPNEGO before
  dereferencing their variable-length fields in ipc_validate_msg().
  The share-config header check is already present from dependency
  2d1f4c041770, so it needs no additional change here.

  Drop the extended-login hunk: this stable tree has neither
  KSMBD_EVENT_LOGIN_REQUEST_EXT nor struct ksmbd_login_response_ext.
  Do not introduce extended-login support or any new functions.
  The target applies cleanly by three-way application to this tree. ]

Stable-dep-of: f25e93768fcc ("ksmbd: prevent out-of-bounds reads in share config responses")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/ksmbd/transport_ipc.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
index 12fa21bf84918..15ec5d8bd776b 100644
--- a/fs/ksmbd/transport_ipc.c
+++ b/fs/ksmbd/transport_ipc.c
@@ -469,6 +469,9 @@ static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
 	{
 		struct ksmbd_rpc_command *resp = entry->response;
 
+		if (entry->msg_sz < sizeof(struct ksmbd_rpc_command))
+			return -EINVAL;
+
 		if (check_add_overflow(sizeof(struct ksmbd_rpc_command),
 				       resp->payload_sz, &msg_sz))
 			return -EINVAL;
@@ -478,6 +481,9 @@ static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
 	{
 		struct ksmbd_spnego_authen_response *resp = entry->response;
 
+		if (entry->msg_sz < sizeof(struct ksmbd_spnego_authen_response))
+			return -EINVAL;
+
 		msg_sz = sizeof(struct ksmbd_spnego_authen_response) +
 				resp->session_key_len + resp->spnego_blob_len;
 		break;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 5.15.y 5/5] ksmbd: prevent out-of-bounds reads in share config responses
  2026-09-14 18:43 ` [PATCH 5.15.y 1/5] ksmbd: Use struct_size() to improve smb_direct_rdma_xmit() Sasha Levin
                     ` (2 preceding siblings ...)
  2026-09-14 18:43   ` [PATCH 5.15.y 4/5] ksmbd: validate ipc response length before dereferencing its fields Sasha Levin
@ 2026-09-14 18:43   ` Sasha Levin
  3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-14 18:43 UTC (permalink / raw)
  To: stable; +Cc: Namjae Jeon, Kanishka De Silva, Farhad Alemi, Sasha Levin

From: Namjae Jeon <linkinjeon@kernel.org>

[ Upstream commit f25e93768fcc5d8287e50b1ec52a42e4c276df34 ]

Validate IPC share configuration payload sizes before consuming
variable-length fields. Bound veto list parsing and account for
the separator byte when deriving the path length.

Fixes: a677ebd8ca2f ("ksmbd: validate payload size in ipc response")
Reported-by: Kanishka De Silva <kpskanna1915@gmail.com>
Reported-by: Farhad Alemi <farhad.alemi@berkeley.edu>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 fs/ksmbd/mgmt/share_config.c | 40 ++++++++++++++++++++++++------------
 fs/ksmbd/transport_ipc.c     | 21 ++++++++++++-------
 2 files changed, 41 insertions(+), 20 deletions(-)

diff --git a/fs/ksmbd/mgmt/share_config.c b/fs/ksmbd/mgmt/share_config.c
index bd31f4c75201e..695c9e78603a9 100644
--- a/fs/ksmbd/mgmt/share_config.c
+++ b/fs/ksmbd/mgmt/share_config.c
@@ -87,9 +87,9 @@ static struct ksmbd_share_config *__share_lookup(const char *name)
 
 static int parse_veto_list(struct ksmbd_share_config *share,
 			   char *veto_list,
-			   int veto_list_sz)
+			   size_t veto_list_sz)
 {
-	int sz = 0;
+	size_t sz;
 
 	if (!veto_list_sz)
 		return 0;
@@ -97,7 +97,7 @@ static int parse_veto_list(struct ksmbd_share_config *share,
 	while (veto_list_sz > 0) {
 		struct ksmbd_veto_pattern *p;
 
-		sz = strlen(veto_list);
+		sz = strnlen(veto_list, veto_list_sz);
 		if (!sz)
 			break;
 
@@ -105,7 +105,7 @@ static int parse_veto_list(struct ksmbd_share_config *share,
 		if (!p)
 			return -ENOMEM;
 
-		p->pattern = kstrdup(veto_list, KSMBD_DEFAULT_GFP);
+		p->pattern = kstrndup(veto_list, sz, KSMBD_DEFAULT_GFP);
 		if (!p->pattern) {
 			kfree(p);
 			return -ENOMEM;
@@ -113,6 +113,9 @@ static int parse_veto_list(struct ksmbd_share_config *share,
 
 		list_add(&p->list, &share->veto_list);
 
+		if (sz == veto_list_sz)
+			break;
+
 		veto_list += sz + 1;
 		veto_list_sz -= (sz + 1);
 	}
@@ -158,17 +161,28 @@ static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
 	share->name = kstrdup(name, KSMBD_DEFAULT_GFP);
 
 	if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
-		int path_len = PATH_MAX;
-
-		if (resp->payload_sz)
-			path_len = resp->payload_sz - resp->veto_list_sz;
+		size_t path_len;
 
-		share->path = kstrndup(ksmbd_share_config_path(resp), path_len,
-				      KSMBD_DEFAULT_GFP);
-		if (!share->path) {
-			ret = -ENOMEM;
+		if (resp->payload_sz <= resp->veto_list_sz) {
+			ret = -EINVAL;
 		} else {
-			ret = 0;
+			path_len = resp->payload_sz - resp->veto_list_sz;
+			if (resp->veto_list_sz)
+				path_len--;
+
+			if (!path_len) {
+				ret = -EINVAL;
+			} else {
+				share->path = kstrndup(
+					ksmbd_share_config_path(resp),
+					path_len, KSMBD_DEFAULT_GFP);
+				if (!share->path)
+					ret = -ENOMEM;
+				else
+					ret = 0;
+			}
+		}
+		if (share->path) {
 			share->path_sz = strlen(share->path);
 			while (share->path_sz > 1 &&
 			       share->path[share->path_sz - 1] == '/')
diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
index 15ec5d8bd776b..c4d7681679952 100644
--- a/fs/ksmbd/transport_ipc.c
+++ b/fs/ksmbd/transport_ipc.c
@@ -495,14 +495,21 @@ static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
 		if (entry->msg_sz < sizeof(struct ksmbd_share_config_response))
 			return -EINVAL;
 
-		if (resp->payload_sz) {
-			if (resp->payload_sz < resp->veto_list_sz)
-				return -EINVAL;
+		if (strnlen(resp->share_name, sizeof(resp->share_name)) ==
+		    sizeof(resp->share_name))
+			return -EINVAL;
 
-			if (check_add_overflow(sizeof(struct ksmbd_share_config_response),
-					       resp->payload_sz, &msg_sz))
-				return -EINVAL;
-		}
+		if (resp->veto_list_sz > resp->payload_sz)
+			return -EINVAL;
+
+		if (resp->flags != KSMBD_SHARE_FLAG_INVALID &&
+		    !(resp->flags & KSMBD_SHARE_FLAG_PIPE) &&
+		    resp->payload_sz <= resp->veto_list_sz)
+			return -EINVAL;
+
+		if (check_add_overflow(sizeof(struct ksmbd_share_config_response),
+				       resp->payload_sz, &msg_sz))
+			return -EINVAL;
 		break;
 	}
 	}
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-09-14 18:43 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-14 11:03 FAILED: patch "[PATCH] ksmbd: prevent out-of-bounds reads in share config responses" failed to apply to 5.15-stable tree gregkh
2026-09-14 18:43 ` [PATCH 5.15.y 1/5] ksmbd: Use struct_size() to improve smb_direct_rdma_xmit() Sasha Levin
2026-09-14 18:43   ` [PATCH 5.15.y 2/5] ksmbd: use __GFP_RETRY_MAYFAIL Sasha Levin
2026-09-14 18:43   ` [PATCH 5.15.y 3/5] ksmbd: validate response sizes in ipc_validate_msg() Sasha Levin
2026-09-14 18:43   ` [PATCH 5.15.y 4/5] ksmbd: validate ipc response length before dereferencing its fields Sasha Levin
2026-09-14 18:43   ` [PATCH 5.15.y 5/5] ksmbd: prevent out-of-bounds reads in share config responses Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox