Skip to content

Commit c8b5b7c

Browse files
namjaejeonSteve French
authored and
Steve French
committed
ksmbd: fix null pointer dereference in alloc_preauth_hash()
The Client send malformed smb2 negotiate request. ksmbd return error response. Subsequently, the client can send smb2 session setup even thought conn->preauth_info is not allocated. This patch add KSMBD_SESS_NEED_SETUP status of connection to ignore session setup request if smb2 negotiate phase is not complete. Cc: [email protected] Tested-by: Steve French <[email protected]> Reported-by: [email protected] # ZDI-CAN-26505 Signed-off-by: Namjae Jeon <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent bf21e29 commit c8b5b7c

File tree

3 files changed

+24
-5
lines changed

3 files changed

+24
-5
lines changed

fs/smb/server/connection.h

+11
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ enum {
2727
KSMBD_SESS_EXITING,
2828
KSMBD_SESS_NEED_RECONNECT,
2929
KSMBD_SESS_NEED_NEGOTIATE,
30+
KSMBD_SESS_NEED_SETUP,
3031
KSMBD_SESS_RELEASING
3132
};
3233

@@ -187,6 +188,11 @@ static inline bool ksmbd_conn_need_negotiate(struct ksmbd_conn *conn)
187188
return READ_ONCE(conn->status) == KSMBD_SESS_NEED_NEGOTIATE;
188189
}
189190

191+
static inline bool ksmbd_conn_need_setup(struct ksmbd_conn *conn)
192+
{
193+
return READ_ONCE(conn->status) == KSMBD_SESS_NEED_SETUP;
194+
}
195+
190196
static inline bool ksmbd_conn_need_reconnect(struct ksmbd_conn *conn)
191197
{
192198
return READ_ONCE(conn->status) == KSMBD_SESS_NEED_RECONNECT;
@@ -217,6 +223,11 @@ static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_conn *conn)
217223
WRITE_ONCE(conn->status, KSMBD_SESS_NEED_NEGOTIATE);
218224
}
219225

226+
static inline void ksmbd_conn_set_need_setup(struct ksmbd_conn *conn)
227+
{
228+
WRITE_ONCE(conn->status, KSMBD_SESS_NEED_SETUP);
229+
}
230+
220231
static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_conn *conn)
221232
{
222233
WRITE_ONCE(conn->status, KSMBD_SESS_NEED_RECONNECT);

fs/smb/server/mgmt/user_session.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -374,13 +374,13 @@ void destroy_previous_session(struct ksmbd_conn *conn,
374374
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT);
375375
err = ksmbd_conn_wait_idle_sess_id(conn, id);
376376
if (err) {
377-
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
377+
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
378378
goto out;
379379
}
380380

381381
ksmbd_destroy_file_table(&prev_sess->file_table);
382382
prev_sess->state = SMB2_SESSION_EXPIRED;
383-
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
383+
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
384384
ksmbd_launch_ksmbd_durable_scavenger();
385385
out:
386386
up_write(&conn->session_lock);

fs/smb/server/smb2pdu.c

+11-3
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
12491249
}
12501250

12511251
conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode);
1252-
ksmbd_conn_set_need_negotiate(conn);
1252+
ksmbd_conn_set_need_setup(conn);
12531253

12541254
err_out:
12551255
ksmbd_conn_unlock(conn);
@@ -1271,6 +1271,9 @@ static int alloc_preauth_hash(struct ksmbd_session *sess,
12711271
if (sess->Preauth_HashValue)
12721272
return 0;
12731273

1274+
if (!conn->preauth_info)
1275+
return -ENOMEM;
1276+
12741277
sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue,
12751278
PREAUTH_HASHVALUE_SIZE, KSMBD_DEFAULT_GFP);
12761279
if (!sess->Preauth_HashValue)
@@ -1674,6 +1677,11 @@ int smb2_sess_setup(struct ksmbd_work *work)
16741677

16751678
ksmbd_debug(SMB, "Received smb2 session setup request\n");
16761679

1680+
if (!ksmbd_conn_need_setup(conn) && !ksmbd_conn_good(conn)) {
1681+
work->send_no_response = 1;
1682+
return rc;
1683+
}
1684+
16771685
WORK_BUFFERS(work, req, rsp);
16781686

16791687
rsp->StructureSize = cpu_to_le16(9);
@@ -1909,7 +1917,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
19091917
if (try_delay) {
19101918
ksmbd_conn_set_need_reconnect(conn);
19111919
ssleep(5);
1912-
ksmbd_conn_set_need_negotiate(conn);
1920+
ksmbd_conn_set_need_setup(conn);
19131921
}
19141922
}
19151923
smb2_set_err_rsp(work);
@@ -2243,7 +2251,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
22432251
ksmbd_free_user(sess->user);
22442252
sess->user = NULL;
22452253
}
2246-
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE);
2254+
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP);
22472255

22482256
rsp->StructureSize = cpu_to_le16(4);
22492257
err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp));

0 commit comments

Comments
 (0)