]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ksmbd: fix durable reconnect context parsing
authorNamjae Jeon <linkinjeon@kernel.org>
Sun, 21 Jun 2026 10:34:37 +0000 (19:34 +0900)
committerSteve French <stfrench@microsoft.com>
Tue, 23 Jun 2026 01:15:05 +0000 (20:15 -0500)
SMB2 create context DataLength describes only the create context data
payload. It does not include the create context header, name field, or
any local padding that exists in ksmbd's helper structures.

ksmbd validated durable reconnect contexts by comparing
DataOffset + DataLength against sizeof the whole helper structure. This
rejects a valid durable v2 reconnect context because the wire DH2C data
is 36 bytes while struct create_durable_handle_reconnect_v2 contains an
extra four byte pad.

Validate the durable context payload length against the corresponding
payload member instead. Also keep the reconnect context authoritative
when a later durable request context is present, matching the existing
durable v1 reconnect behavior.

This fixes smbtorture smb2.durable-v2-open.durable-v2-setinfo, where
the durable v2 reconnect after SET_INFO was rejected with
STATUS_INVALID_PARAMETER.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/server/smb2pdu.c

index f700f2f94ff220470f716bd91fdb0db1c96093d6..35db86da79d36509823a3a9cb3215703d9722084 100644 (file)
@@ -2845,9 +2845,8 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
                                goto out;
                        }
 
-                       if (le16_to_cpu(context->DataOffset) +
-                               le32_to_cpu(context->DataLength) <
-                           sizeof(struct create_durable_handle_reconnect_v2)) {
+                       if (le32_to_cpu(context->DataLength) <
+                           sizeof(recon_v2->dcontext)) {
                                err = -EINVAL;
                                goto out;
                        }
@@ -2892,9 +2891,8 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
                                goto out;
                        }
 
-                       if (le16_to_cpu(context->DataOffset) +
-                               le32_to_cpu(context->DataLength) <
-                           sizeof(create_durable_reconn_t)) {
+                       if (le32_to_cpu(context->DataLength) <
+                           sizeof(recon->Data)) {
                                err = -EINVAL;
                                goto out;
                        }
@@ -2931,9 +2929,8 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
                                goto out;
                        }
 
-                       if (le16_to_cpu(context->DataOffset) +
-                               le32_to_cpu(context->DataLength) <
-                           sizeof(struct create_durable_req_v2)) {
+                       if (le32_to_cpu(context->DataLength) <
+                           sizeof(durable_v2_blob->dcontext)) {
                                err = -EINVAL;
                                goto out;
                        }