]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ksmbd: add missing compound request handing in some commands
authorNamjae Jeon <linkinjeon@kernel.org>
Mon, 18 Dec 2023 15:34:11 +0000 (00:34 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 23 Dec 2023 09:41:57 +0000 (10:41 +0100)
[ Upstream commit 7b7d709ef7cf285309157fb94c33f625dd22c5e1 ]

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/ksmbd/smb2pdu.c

index 12fdf6b56e8326ee8725c3ddd6767de627699cbc..e99ebbe63a7aed89f2f5c0fa14dd71df8cca803f 100644 (file)
@@ -1915,14 +1915,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);
@@ -2091,19 +2093,19 @@ static int smb2_create_open_flags(bool file_present, __le32 access,
  */
 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;
@@ -2126,10 +2128,14 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
 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);
@@ -2169,12 +2175,14 @@ int smb2_session_logoff(struct ksmbd_work *work)
  */
 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)) {
@@ -5314,8 +5322,10 @@ int smb2_query_info(struct ksmbd_work *work)
 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);
@@ -5457,6 +5467,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);
@@ -6093,8 +6106,10 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
        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;
 
@@ -6347,14 +6362,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;
 
@@ -6623,6 +6640,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);
 
@@ -6782,8 +6802,8 @@ static inline bool lock_defer_pending(struct file_lock *fl)
  */
 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;
@@ -6800,6 +6820,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) {
@@ -7914,8 +7936,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;
@@ -7924,6 +7946,8 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
        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;
@@ -8058,8 +8082,8 @@ static int check_lease_state(struct lease *lease, __le32 req_state)
 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;
@@ -8067,6 +8091,8 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
        __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);
@@ -8192,8 +8218,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: