Skip to content

Commit 536bb49

Browse files
namjaejeonsmfrench
authored andcommitted
ksmbd: fix out of bounds in init_smb2_rsp_hdr()
If client send smb2 negotiate request and then send smb1 negotiate request, init_smb2_rsp_hdr is called for smb1 negotiate request since need_neg is set to false. This patch ignore smb1 packets after ->need_neg is set to false. Reported-by: [email protected] # ZDI-CAN-21541 Signed-off-by: Namjae Jeon <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent e202a1e commit 536bb49

File tree

3 files changed

+18
-10
lines changed

3 files changed

+18
-10
lines changed

fs/smb/server/server.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ static void handle_ksmbd_work(struct work_struct *wk)
286286
static int queue_ksmbd_work(struct ksmbd_conn *conn)
287287
{
288288
struct ksmbd_work *work;
289+
int err;
289290

290291
work = ksmbd_alloc_work_struct();
291292
if (!work) {
@@ -297,7 +298,11 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
297298
work->request_buf = conn->request_buf;
298299
conn->request_buf = NULL;
299300

300-
ksmbd_init_smb_server(work);
301+
err = ksmbd_init_smb_server(work);
302+
if (err) {
303+
ksmbd_free_work_struct(work);
304+
return 0;
305+
}
301306

302307
ksmbd_conn_enqueue_request(work);
303308
atomic_inc(&conn->r_count);

fs/smb/server/smb_common.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -388,26 +388,29 @@ static struct smb_version_cmds smb1_server_cmds[1] = {
388388
[SMB_COM_NEGOTIATE_EX] = { .proc = smb1_negotiate, },
389389
};
390390

391-
static void init_smb1_server(struct ksmbd_conn *conn)
391+
static int init_smb1_server(struct ksmbd_conn *conn)
392392
{
393393
conn->ops = &smb1_server_ops;
394394
conn->cmds = smb1_server_cmds;
395395
conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
396+
return 0;
396397
}
397398

398-
void ksmbd_init_smb_server(struct ksmbd_work *work)
399+
int ksmbd_init_smb_server(struct ksmbd_work *work)
399400
{
400401
struct ksmbd_conn *conn = work->conn;
401402
__le32 proto;
402403

403-
if (conn->need_neg == false)
404-
return;
405-
406404
proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
405+
if (conn->need_neg == false) {
406+
if (proto == SMB1_PROTO_NUMBER)
407+
return -EINVAL;
408+
return 0;
409+
}
410+
407411
if (proto == SMB1_PROTO_NUMBER)
408-
init_smb1_server(conn);
409-
else
410-
init_smb3_11_server(conn);
412+
return init_smb1_server(conn);
413+
return init_smb3_11_server(conn);
411414
}
412415

413416
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,

fs/smb/server/smb_common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);
427427

428428
int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
429429

430-
void ksmbd_init_smb_server(struct ksmbd_work *work);
430+
int ksmbd_init_smb_server(struct ksmbd_work *work);
431431

432432
struct ksmbd_kstat;
433433
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,

0 commit comments

Comments
 (0)