ksmbd: fix null pointer dereference in alloc_preauth_hash()
commit c8b5b7c5da
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>
This commit is contained in:
parent
ce807c4c88
commit
cce57cd8c5
|
@ -27,6 +27,7 @@ enum {
|
|||
KSMBD_SESS_EXITING,
|
||||
KSMBD_SESS_NEED_RECONNECT,
|
||||
KSMBD_SESS_NEED_NEGOTIATE,
|
||||
KSMBD_SESS_NEED_SETUP,
|
||||
KSMBD_SESS_RELEASING
|
||||
};
|
||||
|
||||
|
@ -195,6 +196,11 @@ static inline bool ksmbd_conn_need_negotiate(struct ksmbd_conn *conn)
|
|||
return READ_ONCE(conn->status) == KSMBD_SESS_NEED_NEGOTIATE;
|
||||
}
|
||||
|
||||
static inline bool ksmbd_conn_need_setup(struct ksmbd_conn *conn)
|
||||
{
|
||||
return READ_ONCE(conn->status) == KSMBD_SESS_NEED_SETUP;
|
||||
}
|
||||
|
||||
static inline bool ksmbd_conn_need_reconnect(struct ksmbd_conn *conn)
|
||||
{
|
||||
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)
|
|||
WRITE_ONCE(conn->status, KSMBD_SESS_NEED_NEGOTIATE);
|
||||
}
|
||||
|
||||
static inline void ksmbd_conn_set_need_setup(struct ksmbd_conn *conn)
|
||||
{
|
||||
WRITE_ONCE(conn->status, KSMBD_SESS_NEED_SETUP);
|
||||
}
|
||||
|
||||
static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_conn *conn)
|
||||
{
|
||||
WRITE_ONCE(conn->status, KSMBD_SESS_NEED_RECONNECT);
|
||||
|
|
|
@ -373,12 +373,12 @@ void destroy_previous_session(struct ksmbd_conn *conn,
|
|||
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_RECONNECT);
|
||||
err = ksmbd_conn_wait_idle_sess_id(conn, id);
|
||||
if (err) {
|
||||
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
|
||||
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
|
||||
goto out;
|
||||
}
|
||||
ksmbd_destroy_file_table(&prev_sess->file_table);
|
||||
prev_sess->state = SMB2_SESSION_EXPIRED;
|
||||
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_NEGOTIATE);
|
||||
ksmbd_all_conn_set_status(id, KSMBD_SESS_NEED_SETUP);
|
||||
out:
|
||||
up_write(&conn->session_lock);
|
||||
up_write(&sessions_table_lock);
|
||||
|
|
|
@ -1252,7 +1252,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
|
|||
}
|
||||
|
||||
conn->srv_sec_mode = le16_to_cpu(rsp->SecurityMode);
|
||||
ksmbd_conn_set_need_negotiate(conn);
|
||||
ksmbd_conn_set_need_setup(conn);
|
||||
|
||||
err_out:
|
||||
if (rc)
|
||||
|
@ -1273,6 +1273,9 @@ static int alloc_preauth_hash(struct ksmbd_session *sess,
|
|||
if (sess->Preauth_HashValue)
|
||||
return 0;
|
||||
|
||||
if (!conn->preauth_info)
|
||||
return -ENOMEM;
|
||||
|
||||
sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue,
|
||||
PREAUTH_HASHVALUE_SIZE, GFP_KERNEL);
|
||||
if (!sess->Preauth_HashValue)
|
||||
|
@ -1688,6 +1691,11 @@ int smb2_sess_setup(struct ksmbd_work *work)
|
|||
|
||||
ksmbd_debug(SMB, "Received request for session setup\n");
|
||||
|
||||
if (!ksmbd_conn_need_setup(conn) && !ksmbd_conn_good(conn)) {
|
||||
work->send_no_response = 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
WORK_BUFFERS(work, req, rsp);
|
||||
|
||||
rsp->StructureSize = cpu_to_le16(9);
|
||||
|
@ -1919,7 +1927,7 @@ out_err:
|
|||
if (try_delay) {
|
||||
ksmbd_conn_set_need_reconnect(conn);
|
||||
ssleep(5);
|
||||
ksmbd_conn_set_need_negotiate(conn);
|
||||
ksmbd_conn_set_need_setup(conn);
|
||||
}
|
||||
}
|
||||
smb2_set_err_rsp(work);
|
||||
|
@ -2249,7 +2257,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
|
|||
ksmbd_free_user(sess->user);
|
||||
sess->user = NULL;
|
||||
}
|
||||
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE);
|
||||
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP);
|
||||
|
||||
rsp->StructureSize = cpu_to_le16(4);
|
||||
err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp));
|
||||
|
|
Loading…
Reference in New Issue