@@ -1914,14 +1914,16 @@ int smb2_sess_setup(struct ksmbd_work *work)
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);
@@ -2090,19 +2092,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;
@@ -2125,10 +2127,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);
@@ -2168,12 +2174,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)) {
@@ -5306,8 +5314,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);
@@ -5449,6 +5459,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);
@@ -6083,8 +6096,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;
@@ -6332,14 +6347,16 @@ int smb2_read(struct ksmbd_work *work)
*/
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;
@@ -6608,6 +6625,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);
@@ -6767,8 +6787,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;
@@ -6785,6 +6805,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) {
@@ -7898,8 +7920,8 @@ int smb2_ioctl(struct ksmbd_work *work)
*/
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;
@@ -7908,6 +7930,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;
@@ -8042,8 +8066,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;
@@ -8051,6 +8075,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);
@@ -8176,8 +8202,10 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
*/
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:
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. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> --- fs/smb/server/smb2pdu.c | 78 ++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 25 deletions(-)