mirror of
https://github.com/torvalds/linux.git
synced 2026-07-29 18:51:21 +02:00
RDMA/siw: Fix endpoint/socket association handling
Disassociating a socket from an endpoint via siw_socket_disassoc() may
release the last reference on that endpoint and free it. Therefore, don't
clear the endpoints socket pointer after calling that function, but
within.
This fixes a:
BUG: KASAN: slab-use-after-free in siw_cm_work_handler (drivers/infiniband/sw/siw/siw_cm.c:1053 drivers/infiniband/sw/siw/siw_cm.c:1075)
which occurred after processing a malformed MPA request during connection
establishment, causing the new endpoint to be closed.
Fixes: 6c52fdc244 ("rdma/siw: connection management")
Link: https://patch.msgid.link/r/20260604160808.30948-1-bernard.metzler@linux.dev
Reported-by: Shuangpeng Bai <shuangpeng.kernel@gmail.com>
Signed-off-by: Bernard Metzler <bernard.metzler@linux.dev>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
parent
1521d560b7
commit
ea4f6f6c53
|
|
@ -138,6 +138,7 @@ static void siw_socket_disassoc(struct socket *s)
|
|||
cep = sk_to_cep(sk);
|
||||
if (cep) {
|
||||
siw_sk_restore_upcalls(sk, cep);
|
||||
cep->sock = NULL;
|
||||
siw_cep_put(cep);
|
||||
} else {
|
||||
pr_warn("siw: cannot restore sk callbacks: no ep\n");
|
||||
|
|
@ -418,10 +419,11 @@ static void siw_free_cm_id(struct siw_cep *cep)
|
|||
|
||||
static void siw_destroy_cep_sock(struct siw_cep *cep)
|
||||
{
|
||||
if (cep->sock) {
|
||||
siw_socket_disassoc(cep->sock);
|
||||
sock_release(cep->sock);
|
||||
cep->sock = NULL;
|
||||
struct socket *s = cep->sock;
|
||||
|
||||
if (s) {
|
||||
siw_socket_disassoc(s);
|
||||
sock_release(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1050,7 +1052,6 @@ static void siw_accept_newconn(struct siw_cep *cep)
|
|||
if (new_s) {
|
||||
siw_socket_disassoc(new_s);
|
||||
sock_release(new_s);
|
||||
new_cep->sock = NULL;
|
||||
}
|
||||
siw_dbg_cep(cep, "error %d\n", rv);
|
||||
}
|
||||
|
|
@ -1202,6 +1203,8 @@ static void siw_cm_work_handler(struct work_struct *w)
|
|||
WARN(1, "Undefined CM work type: %d\n", work->type);
|
||||
}
|
||||
if (release_cep) {
|
||||
struct socket *s = cep->sock;
|
||||
|
||||
siw_dbg_cep(cep,
|
||||
"release: timer=%s, QP[%u]\n",
|
||||
cep->mpa_timer ? "y" : "n",
|
||||
|
|
@ -1227,10 +1230,9 @@ static void siw_cm_work_handler(struct work_struct *w)
|
|||
cep->qp = NULL;
|
||||
siw_qp_put(qp);
|
||||
}
|
||||
if (cep->sock) {
|
||||
siw_socket_disassoc(cep->sock);
|
||||
sock_release(cep->sock);
|
||||
cep->sock = NULL;
|
||||
if (s) {
|
||||
siw_socket_disassoc(s);
|
||||
sock_release(s);
|
||||
}
|
||||
if (cep->cm_id) {
|
||||
siw_free_cm_id(cep);
|
||||
|
|
@ -1561,7 +1563,6 @@ int siw_connect(struct iw_cm_id *id, struct iw_cm_conn_param *params)
|
|||
if (cep) {
|
||||
siw_socket_disassoc(s);
|
||||
sock_release(s);
|
||||
cep->sock = NULL;
|
||||
|
||||
cep->qp = NULL;
|
||||
|
||||
|
|
@ -1937,7 +1938,6 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
|
|||
siw_cep_set_inuse(cep);
|
||||
|
||||
siw_free_cm_id(cep);
|
||||
cep->sock = NULL;
|
||||
siw_socket_disassoc(s);
|
||||
cep->state = SIW_EPSTATE_CLOSED;
|
||||
|
||||
|
|
@ -1959,6 +1959,7 @@ static void siw_drop_listeners(struct iw_cm_id *id)
|
|||
*/
|
||||
list_for_each_safe(p, tmp, (struct list_head *)id->provider_data) {
|
||||
struct siw_cep *cep = list_entry(p, struct siw_cep, listenq);
|
||||
struct socket *s = cep->sock;
|
||||
|
||||
list_del(p);
|
||||
|
||||
|
|
@ -1967,10 +1968,9 @@ static void siw_drop_listeners(struct iw_cm_id *id)
|
|||
siw_cep_set_inuse(cep);
|
||||
|
||||
siw_free_cm_id(cep);
|
||||
if (cep->sock) {
|
||||
siw_socket_disassoc(cep->sock);
|
||||
sock_release(cep->sock);
|
||||
cep->sock = NULL;
|
||||
if (s) {
|
||||
siw_socket_disassoc(s);
|
||||
sock_release(s);
|
||||
}
|
||||
cep->state = SIW_EPSTATE_CLOSED;
|
||||
siw_cep_set_free_and_put(cep);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user