mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 14:33:24 -04:00
svcrdma: Reject connection when transport allocation fails
handle_connect_req() returns without action when
svc_rdma_create_xprt() fails to allocate the new transport.
The CM core returns 0 for CONNECT_REQUEST events, so it does
not destroy the new rdma_cm_id. Each allocation failure under
memory pressure leaks one rdma_cm_id, and a remote peer driving
connection attempts can amplify this.
Reject the connection by returning a non-zero status from the
CM event handler, which tells the CM core to destroy the
orphaned cm_id.
Fixes: 377f9b2f45 ("rdma: SVCRDMA Core Transport Services")
Cc: stable@vger.kernel.org
Acked-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260527-rdma-follow-on-v1-4-1b09bd87b6cd@oracle.com
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
@@ -246,12 +246,16 @@ svc_rdma_parse_connect_private(struct svcxprt_rdma *newxprt,
|
||||
* structure for the listening endpoint.
|
||||
*
|
||||
* This function creates a new xprt for the new connection and enqueues it on
|
||||
* the accept queue for the listent xprt. When the listen thread is kicked, it
|
||||
* the accept queue for the listen xprt. When the listen thread is kicked, it
|
||||
* will call the recvfrom method on the listen xprt which will accept the new
|
||||
* connection.
|
||||
*
|
||||
* Return values:
|
||||
* %0: Do not destroy @new_cma_id
|
||||
* %1: Destroy @new_cma_id (allocation failure)
|
||||
*/
|
||||
static void handle_connect_req(struct rdma_cm_id *new_cma_id,
|
||||
struct rdma_conn_param *param)
|
||||
static int handle_connect_req(struct rdma_cm_id *new_cma_id,
|
||||
struct rdma_conn_param *param)
|
||||
{
|
||||
struct svcxprt_rdma *listen_xprt = new_cma_id->context;
|
||||
struct svcxprt_rdma *newxprt;
|
||||
@@ -261,7 +265,7 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id,
|
||||
listen_xprt->sc_xprt.xpt_net,
|
||||
ibdev_to_node(new_cma_id->device));
|
||||
if (!newxprt)
|
||||
return;
|
||||
return 1;
|
||||
newxprt->sc_cm_id = new_cma_id;
|
||||
new_cma_id->context = newxprt;
|
||||
svc_rdma_parse_connect_private(newxprt, param);
|
||||
@@ -295,6 +299,7 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id,
|
||||
|
||||
set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags);
|
||||
svc_xprt_enqueue(&listen_xprt->sc_xprt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,8 +323,7 @@ static int svc_rdma_listen_handler(struct rdma_cm_id *cma_id,
|
||||
|
||||
switch (event->event) {
|
||||
case RDMA_CM_EVENT_CONNECT_REQUEST:
|
||||
handle_connect_req(cma_id, &event->param.conn);
|
||||
break;
|
||||
return handle_connect_req(cma_id, &event->param.conn);
|
||||
case RDMA_CM_EVENT_ADDR_CHANGE:
|
||||
listen_id = svc_rdma_create_listen_id(cma_rdma->xpt_net,
|
||||
sap, cma_xprt);
|
||||
|
||||
Reference in New Issue
Block a user