]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.1-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Jun 2023 06:42:55 +0000 (08:42 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Jun 2023 06:42:55 +0000 (08:42 +0200)
added patches:
ksmbd-check-the-validation-of-pdu_size-in-ksmbd_conn_handler_loop.patch
ksmbd-fix-out-of-bound-read-in-deassemble_neg_contexts.patch
ksmbd-fix-out-of-bound-read-in-parse_lease_state.patch

queue-6.1/ksmbd-check-the-validation-of-pdu_size-in-ksmbd_conn_handler_loop.patch [new file with mode: 0644]
queue-6.1/ksmbd-fix-out-of-bound-read-in-deassemble_neg_contexts.patch [new file with mode: 0644]
queue-6.1/ksmbd-fix-out-of-bound-read-in-parse_lease_state.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/ksmbd-check-the-validation-of-pdu_size-in-ksmbd_conn_handler_loop.patch b/queue-6.1/ksmbd-check-the-validation-of-pdu_size-in-ksmbd_conn_handler_loop.patch
new file mode 100644 (file)
index 0000000..b277428
--- /dev/null
@@ -0,0 +1,73 @@
+From 368ba06881c395f1c9a7ba22203cf8d78b4addc0 Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Tue, 30 May 2023 23:10:31 +0900
+Subject: ksmbd: check the validation of pdu_size in ksmbd_conn_handler_loop
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit 368ba06881c395f1c9a7ba22203cf8d78b4addc0 upstream.
+
+The length field of netbios header must be greater than the SMB header
+sizes(smb1 or smb2 header), otherwise the packet is an invalid SMB packet.
+
+If `pdu_size` is 0, ksmbd allocates a 4 bytes chunk to `conn->request_buf`.
+In the function `get_smb2_cmd_val` ksmbd will read cmd from
+`rcv_hdr->Command`, which is `conn->request_buf + 12`, causing the KASAN
+detector to print the following error message:
+
+[    7.205018] BUG: KASAN: slab-out-of-bounds in get_smb2_cmd_val+0x45/0x60
+[    7.205423] Read of size 2 at addr ffff8880062d8b50 by task ksmbd:42632/248
+...
+[    7.207125]  <TASK>
+[    7.209191]  get_smb2_cmd_val+0x45/0x60
+[    7.209426]  ksmbd_conn_enqueue_request+0x3a/0x100
+[    7.209712]  ksmbd_server_process_request+0x72/0x160
+[    7.210295]  ksmbd_conn_handler_loop+0x30c/0x550
+[    7.212280]  kthread+0x160/0x190
+[    7.212762]  ret_from_fork+0x1f/0x30
+[    7.212981]  </TASK>
+
+Cc: stable@vger.kernel.org
+Reported-by: Chih-Yen Chang <cc85nod@gmail.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ksmbd/connection.c |   12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/fs/ksmbd/connection.c
++++ b/fs/ksmbd/connection.c
+@@ -296,6 +296,9 @@ bool ksmbd_conn_alive(struct ksmbd_conn
+       return true;
+ }
++#define SMB1_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb_hdr))
++#define SMB2_MIN_SUPPORTED_HEADER_SIZE (sizeof(struct smb2_hdr) + 4)
++
+ /**
+  * ksmbd_conn_handler_loop() - session thread to listen on new smb requests
+  * @p:                connection instance
+@@ -352,6 +355,9 @@ int ksmbd_conn_handler_loop(void *p)
+               if (pdu_size > MAX_STREAM_PROT_LEN)
+                       break;
++              if (pdu_size < SMB1_MIN_SUPPORTED_HEADER_SIZE)
++                      break;
++
+               /* 4 for rfc1002 length field */
+               /* 1 for implied bcc[0] */
+               size = pdu_size + 4 + 1;
+@@ -379,6 +385,12 @@ int ksmbd_conn_handler_loop(void *p)
+                       continue;
+               }
++              if (((struct smb2_hdr *)smb2_get_msg(conn->request_buf))->ProtocolId ==
++                  SMB2_PROTO_NUMBER) {
++                      if (pdu_size < SMB2_MIN_SUPPORTED_HEADER_SIZE)
++                              break;
++              }
++
+               if (!default_conn_ops.process_fn) {
+                       pr_err("No connection request callback\n");
+                       break;
diff --git a/queue-6.1/ksmbd-fix-out-of-bound-read-in-deassemble_neg_contexts.patch b/queue-6.1/ksmbd-fix-out-of-bound-read-in-deassemble_neg_contexts.patch
new file mode 100644 (file)
index 0000000..516aaad
--- /dev/null
@@ -0,0 +1,83 @@
+From f1a411873c85b642f13b01f21b534c2bab81fc1b Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Sun, 28 May 2023 00:23:09 +0900
+Subject: ksmbd: fix out-of-bound read in deassemble_neg_contexts()
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit f1a411873c85b642f13b01f21b534c2bab81fc1b upstream.
+
+The check in the beginning is
+`clen + sizeof(struct smb2_neg_context) <= len_of_ctxts`,
+but in the end of loop, `len_of_ctxts` will subtract
+`((clen + 7) & ~0x7) + sizeof(struct smb2_neg_context)`, which causes
+integer underflow when clen does the 8 alignment. We should use
+`(clen + 7) & ~0x7` in the check to avoid underflow from happening.
+
+Then there are some variables that need to be declared unsigned
+instead of signed.
+
+[   11.671070] BUG: KASAN: slab-out-of-bounds in smb2_handle_negotiate+0x799/0x1610
+[   11.671533] Read of size 2 at addr ffff888005e86cf2 by task kworker/0:0/7
+...
+[   11.673383] Call Trace:
+[   11.673541]  <TASK>
+[   11.673679]  dump_stack_lvl+0x33/0x50
+[   11.673913]  print_report+0xcc/0x620
+[   11.674671]  kasan_report+0xae/0xe0
+[   11.675171]  kasan_check_range+0x35/0x1b0
+[   11.675412]  smb2_handle_negotiate+0x799/0x1610
+[   11.676217]  ksmbd_smb_negotiate_common+0x526/0x770
+[   11.676795]  handle_ksmbd_work+0x274/0x810
+...
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Chih-Yen Chang <cc85nod@gmail.com>
+Tested-by: Chih-Yen Chang <cc85nod@gmail.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ksmbd/smb2pdu.c |   13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+--- a/fs/ksmbd/smb2pdu.c
++++ b/fs/ksmbd/smb2pdu.c
+@@ -979,13 +979,13 @@ static void decode_sign_cap_ctxt(struct
+ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
+                                     struct smb2_negotiate_req *req,
+-                                    int len_of_smb)
++                                    unsigned int len_of_smb)
+ {
+       /* +4 is to account for the RFC1001 len field */
+       struct smb2_neg_context *pctx = (struct smb2_neg_context *)req;
+       int i = 0, len_of_ctxts;
+-      int offset = le32_to_cpu(req->NegotiateContextOffset);
+-      int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
++      unsigned int offset = le32_to_cpu(req->NegotiateContextOffset);
++      unsigned int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
+       __le32 status = STATUS_INVALID_PARAMETER;
+       ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt);
+@@ -999,7 +999,7 @@ static __le32 deassemble_neg_contexts(st
+       while (i++ < neg_ctxt_cnt) {
+               int clen, ctxt_len;
+-              if (len_of_ctxts < sizeof(struct smb2_neg_context))
++              if (len_of_ctxts < (int)sizeof(struct smb2_neg_context))
+                       break;
+               pctx = (struct smb2_neg_context *)((char *)pctx + offset);
+@@ -1054,9 +1054,8 @@ static __le32 deassemble_neg_contexts(st
+               }
+               /* offsets must be 8 byte aligned */
+-              clen = (clen + 7) & ~0x7;
+-              offset = clen + sizeof(struct smb2_neg_context);
+-              len_of_ctxts -= clen + sizeof(struct smb2_neg_context);
++              offset = (ctxt_len + 7) & ~0x7;
++              len_of_ctxts -= offset;
+       }
+       return status;
+ }
diff --git a/queue-6.1/ksmbd-fix-out-of-bound-read-in-parse_lease_state.patch b/queue-6.1/ksmbd-fix-out-of-bound-read-in-parse_lease_state.patch
new file mode 100644 (file)
index 0000000..ead9c9d
--- /dev/null
@@ -0,0 +1,125 @@
+From fc6c6a3c324c1b3e93a03d0cfa3749c781f23de0 Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Sun, 28 May 2023 00:23:41 +0900
+Subject: ksmbd: fix out-of-bound read in parse_lease_state()
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit fc6c6a3c324c1b3e93a03d0cfa3749c781f23de0 upstream.
+
+This bug is in parse_lease_state, and it is caused by the missing check
+of `struct create_context`. When the ksmbd traverses the create_contexts,
+it doesn't check if the field of `NameOffset` and `Next` is valid,
+The KASAN message is following:
+
+[    6.664323] BUG: KASAN: slab-out-of-bounds in parse_lease_state+0x7d/0x280
+[    6.664738] Read of size 2 at addr ffff888005c08988 by task kworker/0:3/103
+...
+[    6.666644] Call Trace:
+[    6.666796]  <TASK>
+[    6.666933]  dump_stack_lvl+0x33/0x50
+[    6.667167]  print_report+0xcc/0x620
+[    6.667903]  kasan_report+0xae/0xe0
+[    6.668374]  kasan_check_range+0x35/0x1b0
+[    6.668621]  parse_lease_state+0x7d/0x280
+[    6.668868]  smb2_open+0xbe8/0x4420
+[    6.675137]  handle_ksmbd_work+0x282/0x820
+
+Use smb2_find_context_vals() to find smb2 create request lease context.
+smb2_find_context_vals validate create context fields.
+
+Cc: stable@vger.kernel.org
+Reported-by: Chih-Yen Chang <cc85nod@gmail.com>
+Tested-by: Chih-Yen Chang <cc85nod@gmail.com>
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ksmbd/oplock.c |   70 ++++++++++++++++++++----------------------------------
+ 1 file changed, 26 insertions(+), 44 deletions(-)
+
+--- a/fs/ksmbd/oplock.c
++++ b/fs/ksmbd/oplock.c
+@@ -1415,56 +1415,38 @@ void create_lease_buf(u8 *rbuf, struct l
+  */
+ struct lease_ctx_info *parse_lease_state(void *open_req)
+ {
+-      char *data_offset;
+       struct create_context *cc;
+-      unsigned int next = 0;
+-      char *name;
+-      bool found = false;
+       struct smb2_create_req *req = (struct smb2_create_req *)open_req;
+-      struct lease_ctx_info *lreq = kzalloc(sizeof(struct lease_ctx_info),
+-              GFP_KERNEL);
++      struct lease_ctx_info *lreq;
++
++      cc = smb2_find_context_vals(req, SMB2_CREATE_REQUEST_LEASE, 4);
++      if (IS_ERR_OR_NULL(cc))
++              return NULL;
++
++      lreq = kzalloc(sizeof(struct lease_ctx_info), GFP_KERNEL);
+       if (!lreq)
+               return NULL;
+-      data_offset = (char *)req + le32_to_cpu(req->CreateContextsOffset);
+-      cc = (struct create_context *)data_offset;
+-      do {
+-              cc = (struct create_context *)((char *)cc + next);
+-              name = le16_to_cpu(cc->NameOffset) + (char *)cc;
+-              if (le16_to_cpu(cc->NameLength) != 4 ||
+-                  strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) {
+-                      next = le32_to_cpu(cc->Next);
+-                      continue;
+-              }
+-              found = true;
+-              break;
+-      } while (next != 0);
+-
+-      if (found) {
+-              if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {
+-                      struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
+-
+-                      memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
+-                      lreq->req_state = lc->lcontext.LeaseState;
+-                      lreq->flags = lc->lcontext.LeaseFlags;
+-                      lreq->duration = lc->lcontext.LeaseDuration;
+-                      memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
+-                             SMB2_LEASE_KEY_SIZE);
+-                      lreq->version = 2;
+-              } else {
+-                      struct create_lease *lc = (struct create_lease *)cc;
+-
+-                      memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
+-                      lreq->req_state = lc->lcontext.LeaseState;
+-                      lreq->flags = lc->lcontext.LeaseFlags;
+-                      lreq->duration = lc->lcontext.LeaseDuration;
+-                      lreq->version = 1;
+-              }
+-              return lreq;
+-      }
++      if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {
++              struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
+-      kfree(lreq);
+-      return NULL;
++              memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
++              lreq->req_state = lc->lcontext.LeaseState;
++              lreq->flags = lc->lcontext.LeaseFlags;
++              lreq->duration = lc->lcontext.LeaseDuration;
++              memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
++                              SMB2_LEASE_KEY_SIZE);
++              lreq->version = 2;
++      } else {
++              struct create_lease *lc = (struct create_lease *)cc;
++
++              memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
++              lreq->req_state = lc->lcontext.LeaseState;
++              lreq->flags = lc->lcontext.LeaseFlags;
++              lreq->duration = lc->lcontext.LeaseDuration;
++              lreq->version = 1;
++      }
++      return lreq;
+ }
+ /**
index 3d958ce88abfdc1189699069aaceb1d3d6a3584c..03d6c7287cef6d1d527897d89702b6d3dd46a682 100644 (file)
@@ -122,3 +122,6 @@ riscv-fix-kprobe-__user-string-arg-print-fault-issue.patch
 vduse-avoid-empty-string-for-dev-name.patch
 vhost-support-packed-when-setting-getting-vring_base.patch
 vhost_vdpa-support-packed-when-setting-getting-vring.patch
+ksmbd-fix-out-of-bound-read-in-deassemble_neg_contexts.patch
+ksmbd-fix-out-of-bound-read-in-parse_lease_state.patch
+ksmbd-check-the-validation-of-pdu_size-in-ksmbd_conn_handler_loop.patch