]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Jul 2023 17:53:57 +0000 (19:53 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Jul 2023 17:53:57 +0000 (19:53 +0200)
added patches:
ksmbd-add-missing-compound-request-handing-in-some-commands.patch
ksmbd-fix-out-of-bounds-read-in-smb2_sess_setup.patch

queue-6.4/ksmbd-add-missing-compound-request-handing-in-some-commands.patch [new file with mode: 0644]
queue-6.4/ksmbd-fix-out-of-bounds-read-in-smb2_sess_setup.patch [new file with mode: 0644]
queue-6.4/series

diff --git a/queue-6.4/ksmbd-add-missing-compound-request-handing-in-some-commands.patch b/queue-6.4/ksmbd-add-missing-compound-request-handing-in-some-commands.patch
new file mode 100644 (file)
index 0000000..7d6fabf
--- /dev/null
@@ -0,0 +1,239 @@
+From 7b7d709ef7cf285309157fb94c33f625dd22c5e1 Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Sat, 24 Jun 2023 12:35:39 +0900
+Subject: ksmbd: add missing compound request handing in some commands
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit 7b7d709ef7cf285309157fb94c33f625dd22c5e1 upstream.
+
+This patch add the compound request handling to the some commands.
+Existing clients do not send these commands as compound requests,
+but ksmbd should consider that they may come.
+
+Cc: stable@vger.kernel.org
+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/smb/server/smb2pdu.c |   78 ++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 53 insertions(+), 25 deletions(-)
+
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -1911,14 +1911,16 @@ out_err:
+ int smb2_tree_connect(struct ksmbd_work *work)
+ {
+       struct ksmbd_conn *conn = work->conn;
+-      struct smb2_tree_connect_req *req = smb2_get_msg(work->request_buf);
+-      struct smb2_tree_connect_rsp *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_tree_connect_req *req;
++      struct smb2_tree_connect_rsp *rsp;
+       struct ksmbd_session *sess = work->sess;
+       char *treename = NULL, *name = NULL;
+       struct ksmbd_tree_conn_status status;
+       struct ksmbd_share_config *share;
+       int rc = -EINVAL;
++      WORK_BUFFERS(work, req, rsp);
++
+       treename = smb_strndup_from_utf16(req->Buffer,
+                                         le16_to_cpu(req->PathLength), true,
+                                         conn->local_nls);
+@@ -2087,19 +2089,19 @@ static int smb2_create_open_flags(bool f
+  */
+ int smb2_tree_disconnect(struct ksmbd_work *work)
+ {
+-      struct smb2_tree_disconnect_rsp *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_tree_disconnect_rsp *rsp;
++      struct smb2_tree_disconnect_req *req;
+       struct ksmbd_session *sess = work->sess;
+       struct ksmbd_tree_connect *tcon = work->tcon;
++      WORK_BUFFERS(work, req, rsp);
++
+       rsp->StructureSize = cpu_to_le16(4);
+       inc_rfc1001_len(work->response_buf, 4);
+       ksmbd_debug(SMB, "request\n");
+       if (!tcon || test_and_set_bit(TREE_CONN_EXPIRE, &tcon->status)) {
+-              struct smb2_tree_disconnect_req *req =
+-                      smb2_get_msg(work->request_buf);
+-
+               ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
+               rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
+@@ -2122,10 +2124,14 @@ int smb2_tree_disconnect(struct ksmbd_wo
+ int smb2_session_logoff(struct ksmbd_work *work)
+ {
+       struct ksmbd_conn *conn = work->conn;
+-      struct smb2_logoff_rsp *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_logoff_req *req;
++      struct smb2_logoff_rsp *rsp;
+       struct ksmbd_session *sess;
+-      struct smb2_logoff_req *req = smb2_get_msg(work->request_buf);
+-      u64 sess_id = le64_to_cpu(req->hdr.SessionId);
++      u64 sess_id;
++
++      WORK_BUFFERS(work, req, rsp);
++
++      sess_id = le64_to_cpu(req->hdr.SessionId);
+       rsp->StructureSize = cpu_to_le16(4);
+       inc_rfc1001_len(work->response_buf, 4);
+@@ -2165,12 +2171,14 @@ int smb2_session_logoff(struct ksmbd_wor
+  */
+ static noinline int create_smb2_pipe(struct ksmbd_work *work)
+ {
+-      struct smb2_create_rsp *rsp = smb2_get_msg(work->response_buf);
+-      struct smb2_create_req *req = smb2_get_msg(work->request_buf);
++      struct smb2_create_rsp *rsp;
++      struct smb2_create_req *req;
+       int id;
+       int err;
+       char *name;
++      WORK_BUFFERS(work, req, rsp);
++
+       name = smb_strndup_from_utf16(req->Buffer, le16_to_cpu(req->NameLength),
+                                     1, work->conn->local_nls);
+       if (IS_ERR(name)) {
+@@ -5305,8 +5313,10 @@ int smb2_query_info(struct ksmbd_work *w
+ static noinline int smb2_close_pipe(struct ksmbd_work *work)
+ {
+       u64 id;
+-      struct smb2_close_req *req = smb2_get_msg(work->request_buf);
+-      struct smb2_close_rsp *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_close_req *req;
++      struct smb2_close_rsp *rsp;
++
++      WORK_BUFFERS(work, req, rsp);
+       id = req->VolatileFileId;
+       ksmbd_session_rpc_close(work->sess, id);
+@@ -5448,6 +5458,9 @@ int smb2_echo(struct ksmbd_work *work)
+ {
+       struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf);
++      if (work->next_smb2_rcv_hdr_off)
++              rsp = ksmbd_resp_buf_next(work);
++
+       rsp->StructureSize = cpu_to_le16(4);
+       rsp->Reserved = 0;
+       inc_rfc1001_len(work->response_buf, 4);
+@@ -6082,8 +6095,10 @@ static noinline int smb2_read_pipe(struc
+       int nbytes = 0, err;
+       u64 id;
+       struct ksmbd_rpc_command *rpc_resp;
+-      struct smb2_read_req *req = smb2_get_msg(work->request_buf);
+-      struct smb2_read_rsp *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_read_req *req;
++      struct smb2_read_rsp *rsp;
++
++      WORK_BUFFERS(work, req, rsp);
+       id = req->VolatileFileId;
+@@ -6331,14 +6346,16 @@ out:
+  */
+ static noinline int smb2_write_pipe(struct ksmbd_work *work)
+ {
+-      struct smb2_write_req *req = smb2_get_msg(work->request_buf);
+-      struct smb2_write_rsp *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_write_req *req;
++      struct smb2_write_rsp *rsp;
+       struct ksmbd_rpc_command *rpc_resp;
+       u64 id = 0;
+       int err = 0, ret = 0;
+       char *data_buf;
+       size_t length;
++      WORK_BUFFERS(work, req, rsp);
++
+       length = le32_to_cpu(req->Length);
+       id = req->VolatileFileId;
+@@ -6607,6 +6624,9 @@ int smb2_cancel(struct ksmbd_work *work)
+       struct ksmbd_work *iter;
+       struct list_head *command_list;
++      if (work->next_smb2_rcv_hdr_off)
++              hdr = ksmbd_resp_buf_next(work);
++
+       ksmbd_debug(SMB, "smb2 cancel called on mid %llu, async flags 0x%x\n",
+                   hdr->MessageId, hdr->Flags);
+@@ -6766,8 +6786,8 @@ static inline bool lock_defer_pending(st
+  */
+ int smb2_lock(struct ksmbd_work *work)
+ {
+-      struct smb2_lock_req *req = smb2_get_msg(work->request_buf);
+-      struct smb2_lock_rsp *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_lock_req *req;
++      struct smb2_lock_rsp *rsp;
+       struct smb2_lock_element *lock_ele;
+       struct ksmbd_file *fp = NULL;
+       struct file_lock *flock = NULL;
+@@ -6784,6 +6804,8 @@ int smb2_lock(struct ksmbd_work *work)
+       LIST_HEAD(rollback_list);
+       int prior_lock = 0;
++      WORK_BUFFERS(work, req, rsp);
++
+       ksmbd_debug(SMB, "Received lock request\n");
+       fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
+       if (!fp) {
+@@ -7897,8 +7919,8 @@ out:
+  */
+ static void smb20_oplock_break_ack(struct ksmbd_work *work)
+ {
+-      struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
+-      struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_oplock_break *req;
++      struct smb2_oplock_break *rsp;
+       struct ksmbd_file *fp;
+       struct oplock_info *opinfo = NULL;
+       __le32 err = 0;
+@@ -7907,6 +7929,8 @@ static void smb20_oplock_break_ack(struc
+       char req_oplevel = 0, rsp_oplevel = 0;
+       unsigned int oplock_change_type;
++      WORK_BUFFERS(work, req, rsp);
++
+       volatile_id = req->VolatileFid;
+       persistent_id = req->PersistentFid;
+       req_oplevel = req->OplockLevel;
+@@ -8041,8 +8065,8 @@ static int check_lease_state(struct leas
+ static void smb21_lease_break_ack(struct ksmbd_work *work)
+ {
+       struct ksmbd_conn *conn = work->conn;
+-      struct smb2_lease_ack *req = smb2_get_msg(work->request_buf);
+-      struct smb2_lease_ack *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_lease_ack *req;
++      struct smb2_lease_ack *rsp;
+       struct oplock_info *opinfo;
+       __le32 err = 0;
+       int ret = 0;
+@@ -8050,6 +8074,8 @@ static void smb21_lease_break_ack(struct
+       __le32 lease_state;
+       struct lease *lease;
++      WORK_BUFFERS(work, req, rsp);
++
+       ksmbd_debug(OPLOCK, "smb21 lease break, lease state(0x%x)\n",
+                   le32_to_cpu(req->LeaseState));
+       opinfo = lookup_lease_in_table(conn, req->LeaseKey);
+@@ -8175,8 +8201,10 @@ err_out:
+  */
+ int smb2_oplock_break(struct ksmbd_work *work)
+ {
+-      struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
+-      struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_oplock_break *req;
++      struct smb2_oplock_break *rsp;
++
++      WORK_BUFFERS(work, req, rsp);
+       switch (le16_to_cpu(req->StructureSize)) {
+       case OP_BREAK_STRUCT_SIZE_20:
diff --git a/queue-6.4/ksmbd-fix-out-of-bounds-read-in-smb2_sess_setup.patch b/queue-6.4/ksmbd-fix-out-of-bounds-read-in-smb2_sess_setup.patch
new file mode 100644 (file)
index 0000000..514ef47
--- /dev/null
@@ -0,0 +1,122 @@
+From 98422bdd4cb3ca4d08844046f6507d7ec2c2b8d8 Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Sat, 24 Jun 2023 12:33:09 +0900
+Subject: ksmbd: fix out of bounds read in smb2_sess_setup
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit 98422bdd4cb3ca4d08844046f6507d7ec2c2b8d8 upstream.
+
+ksmbd does not consider the case of that smb2 session setup is
+in compound request. If this is the second payload of the compound,
+OOB read issue occurs while processing the first payload in
+the smb2_sess_setup().
+
+Cc: stable@vger.kernel.org
+Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-21355
+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/smb/server/smb2pdu.c |   31 +++++++++++++++++--------------
+ 1 file changed, 17 insertions(+), 14 deletions(-)
+
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -1322,9 +1322,8 @@ static int decode_negotiation_token(stru
+ static int ntlm_negotiate(struct ksmbd_work *work,
+                         struct negotiate_message *negblob,
+-                        size_t negblob_len)
++                        size_t negblob_len, struct smb2_sess_setup_rsp *rsp)
+ {
+-      struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
+       struct challenge_message *chgblob;
+       unsigned char *spnego_blob = NULL;
+       u16 spnego_blob_len;
+@@ -1429,10 +1428,10 @@ static struct ksmbd_user *session_user(s
+       return user;
+ }
+-static int ntlm_authenticate(struct ksmbd_work *work)
++static int ntlm_authenticate(struct ksmbd_work *work,
++                           struct smb2_sess_setup_req *req,
++                           struct smb2_sess_setup_rsp *rsp)
+ {
+-      struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
+-      struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
+       struct ksmbd_conn *conn = work->conn;
+       struct ksmbd_session *sess = work->sess;
+       struct channel *chann = NULL;
+@@ -1566,10 +1565,10 @@ binding_session:
+ }
+ #ifdef CONFIG_SMB_SERVER_KERBEROS5
+-static int krb5_authenticate(struct ksmbd_work *work)
++static int krb5_authenticate(struct ksmbd_work *work,
++                           struct smb2_sess_setup_req *req,
++                           struct smb2_sess_setup_rsp *rsp)
+ {
+-      struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
+-      struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
+       struct ksmbd_conn *conn = work->conn;
+       struct ksmbd_session *sess = work->sess;
+       char *in_blob, *out_blob;
+@@ -1647,7 +1646,9 @@ static int krb5_authenticate(struct ksmb
+       return 0;
+ }
+ #else
+-static int krb5_authenticate(struct ksmbd_work *work)
++static int krb5_authenticate(struct ksmbd_work *work,
++                           struct smb2_sess_setup_req *req,
++                           struct smb2_sess_setup_rsp *rsp)
+ {
+       return -EOPNOTSUPP;
+ }
+@@ -1656,8 +1657,8 @@ static int krb5_authenticate(struct ksmb
+ int smb2_sess_setup(struct ksmbd_work *work)
+ {
+       struct ksmbd_conn *conn = work->conn;
+-      struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
+-      struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
++      struct smb2_sess_setup_req *req;
++      struct smb2_sess_setup_rsp *rsp;
+       struct ksmbd_session *sess;
+       struct negotiate_message *negblob;
+       unsigned int negblob_len, negblob_off;
+@@ -1665,6 +1666,8 @@ int smb2_sess_setup(struct ksmbd_work *w
+       ksmbd_debug(SMB, "Received request for session setup\n");
++      WORK_BUFFERS(work, req, rsp);
++
+       rsp->StructureSize = cpu_to_le16(9);
+       rsp->SessionFlags = 0;
+       rsp->SecurityBufferOffset = cpu_to_le16(72);
+@@ -1786,7 +1789,7 @@ int smb2_sess_setup(struct ksmbd_work *w
+               if (conn->preferred_auth_mech &
+                               (KSMBD_AUTH_KRB5 | KSMBD_AUTH_MSKRB5)) {
+-                      rc = krb5_authenticate(work);
++                      rc = krb5_authenticate(work, req, rsp);
+                       if (rc) {
+                               rc = -EINVAL;
+                               goto out_err;
+@@ -1800,7 +1803,7 @@ int smb2_sess_setup(struct ksmbd_work *w
+                       sess->Preauth_HashValue = NULL;
+               } else if (conn->preferred_auth_mech == KSMBD_AUTH_NTLMSSP) {
+                       if (negblob->MessageType == NtLmNegotiate) {
+-                              rc = ntlm_negotiate(work, negblob, negblob_len);
++                              rc = ntlm_negotiate(work, negblob, negblob_len, rsp);
+                               if (rc)
+                                       goto out_err;
+                               rsp->hdr.Status =
+@@ -1813,7 +1816,7 @@ int smb2_sess_setup(struct ksmbd_work *w
+                                               le16_to_cpu(rsp->SecurityBufferLength) - 1);
+                       } else if (negblob->MessageType == NtLmAuthenticate) {
+-                              rc = ntlm_authenticate(work);
++                              rc = ntlm_authenticate(work, req, rsp);
+                               if (rc)
+                                       goto out_err;
index b88379ece0f9e05d8d977dc75db8d1ce412bcf88..9f3cf737c566c83ba120eeb83129ae5dd948a065 100644 (file)
@@ -5,6 +5,8 @@ hid-amd_sfh-rename-the-float32-variable.patch
 hid-amd_sfh-fix-for-shift-out-of-bounds.patch
 net-lan743x-don-t-sleep-in-atomic-context.patch
 net-lan743x-select-fixed_phy.patch
+ksmbd-add-missing-compound-request-handing-in-some-commands.patch
+ksmbd-fix-out-of-bounds-read-in-smb2_sess_setup.patch
 drm-panel-simple-add-connector_type-for-innolux_at04.patch
 drm-bridge-dw_hdmi-fix-connector-access-for-scdc.patch
 drm-bridge-ti-sn65dsi86-fix-auxiliary-bus-lifetime.patch