Skip to content

Commit cce57cd

Browse files
namjaejeongregkh
authored andcommitted
ksmbd: fix null pointer dereference in alloc_preauth_hash()
commit c8b5b7c upstream. 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: stable@vger.kernel.org Tested-by: Steve French <stfrench@microsoft.com> Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-26505 Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Jan Alexander Preissler <akendo@akendo.eu> Signed-off-by: Sujana Subramaniam <sujana.subramaniam@sap.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent ce807c4 commit cce57cd

3 files changed

Lines changed: 24 additions & 5 deletions

File tree

fs/smb/server/connection.h

Lines changed: 11 additions & 0 deletions
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

@@ -195,6 +196,11 @@ static inline bool ksmbd_conn_need_negotiate(struct ksmbd_conn *conn)
195196
return READ_ONCE(conn->status) == KSMBD_SESS_NEED_NEGOTIATE;
196197
}
197198

199+
static inline bool ksmbd_conn_need_setup(struct ksmbd_conn *conn)
200+
{
201+
return READ_ONCE(conn->status) == KSMBD_SESS_NEED_SETUP;
202+
}
203+
198204
static inline bool ksmbd_conn_need_reconnect(struct ksmbd_conn *conn)
199205
{
200206
return READ_ONCE(conn->status) == KSMBD_SESS_NEED_RECONNECT;
@@ -225,6 +231,11 @@ static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_conn *conn)
225231
WRITE_ONCE(conn->status, KSMBD_SESS_NEED_NEGOTIATE);
226232
}
227233

234+
static inline void ksmbd_conn_set_need_setup(struct ksmbd_conn *conn)
235+
{
236+
WRITE_ONCE(conn->status, KSMBD_SESS_NEED_SETUP);
237+
}
238+
228239
static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_conn *conn)
229240
{
230241
WRITE_ONCE(conn->status, KSMBD_SESS_NEED_RECONNECT);

fs/smb/server/mgmt/user_session.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,12 +373,12 @@ void destroy_previous_session(struct ksmbd_conn *conn,
373373
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT);
374374
err = ksmbd_conn_wait_idle_sess_id(conn, id);
375375
if (err) {
376-
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
376+
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
377377
goto out;
378378
}
379379
ksmbd_destroy_file_table(&prev_sess->file_table);
380380
prev_sess->state = SMB2_SESSION_EXPIRED;
381-
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
381+
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
382382
out:
383383
up_write(&conn->session_lock);
384384
up_write(&sessions_table_lock);

fs/smb/server/smb2pdu.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,7 +1252,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
12521252
}
12531253

12541254
conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode);
1255-
ksmbd_conn_set_need_negotiate(conn);
1255+
ksmbd_conn_set_need_setup(conn);
12561256

12571257
err_out:
12581258
if (rc)
@@ -1273,6 +1273,9 @@ static int alloc_preauth_hash(struct ksmbd_session *sess,
12731273
if (sess->Preauth_HashValue)
12741274
return 0;
12751275

1276+
if (!conn->preauth_info)
1277+
return -ENOMEM;
1278+
12761279
sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue,
12771280
PREAUTH_HASHVALUE_SIZE, GFP_KERNEL);
12781281
if (!sess->Preauth_HashValue)
@@ -1688,6 +1691,11 @@ int smb2_sess_setup(struct ksmbd_work *work)
16881691

16891692
ksmbd_debug(SMB, "Received request for session setup\n");
16901693

1694+
if (!ksmbd_conn_need_setup(conn) && !ksmbd_conn_good(conn)) {
1695+
work->send_no_response = 1;
1696+
return rc;
1697+
}
1698+
16911699
WORK_BUFFERS(work, req, rsp);
16921700

16931701
rsp->StructureSize = cpu_to_le16(9);
@@ -1919,7 +1927,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
19191927
if (try_delay) {
19201928
ksmbd_conn_set_need_reconnect(conn);
19211929
ssleep(5);
1922-
ksmbd_conn_set_need_negotiate(conn);
1930+
ksmbd_conn_set_need_setup(conn);
19231931
}
19241932
}
19251933
smb2_set_err_rsp(work);
@@ -2249,7 +2257,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
22492257
ksmbd_free_user(sess->user);
22502258
sess->user = NULL;
22512259
}
2252-
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE);
2260+
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP);
22532261

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

0 commit comments

Comments
 (0)