FAILED: patch "[PATCH] svcrdma: Reject connection when transport allocation fails" failed to apply to 5.10-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 0944462247dcb7de7622cdaaadf5f05c52707dab
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090304-champion-prevent-c92a@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 0944462247dcb7de7622cdaaadf5f05c52707dab Mon Sep 17 00:00:00 2001
From: Chuck Lever <[email protected]>
Date: Wed, 27 May 2026 11:00:14 -0400
Subject: [PATCH] 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.
net/sunrpc/xprtrdma/svc_rdma_transport.c +10 -6
@@ -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);
Sasha Levin
maintainerPATCH 1/4 svcrdma: Allocate new transports on device's NUMA node
From: Chuck Lever <[email protected]>
[ Upstream commit fe2b401e55482cf90a0056209c8a232b2d39056c ]
The physical device's NUMA node ID is available when allocating an svc_xprt for an incoming connection. Use that value to ensure the svc_xprt structure is allocated on the NUMA node closest to the device.
Stable-dep-of: 0944462247dc ("svcrdma: Reject connection when transport allocation fails")
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +9 -9
@@ -64,7 +64,7 @@#define RPCDBG_FACILITY RPCDBG_SVCXPRTstatic struct svcxprt_rdma *svc_rdma_create_xprt (struct svc_serv *serv, -struct net *net); +struct net *net,int node); static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, struct net *net, struct sockaddr *sa, int salen,
@@ -126,14 +126,14 @@ static void qp_event_handler(struct ib_event *event, void *context) }static struct svcxprt_rdma *svc_rdma_create_xprt (struct svc_serv *serv, -struct net *net) +struct net *net,int node) { -struct svcxprt_rdma *cma_xprt =kzalloc (sizeof *cma_xprt,GFP_KERNEL ); +struct svcxprt_rdma *cma_xprt; -if (!cma_xprt) { -dprintk ("svcrdma: failed to create new transport\n" ); + cma_xprt =kzalloc_node (sizeof (*cma_xprt),GFP_KERNEL , node); +if (!cma_xprt)return NULL ; - } +svc_xprt_init (net, &svc_rdma_class, &cma_xprt->sc_xprt, serv);INIT_LIST_HEAD (&cma_xprt->sc_accept_q);INIT_LIST_HEAD (&cma_xprt->sc_rq_dto_q);
@@ -197,9 +197,9 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id,struct svcxprt_rdma *newxprt;struct sockaddr *sa; -/* Create a new transport */ newxprt =svc_rdma_create_xprt (listen_xprt->sc_xprt.xpt_server, - listen_xprt->sc_xprt.xpt_net); + listen_xprt->sc_xprt.xpt_net, +ibdev_to_node (new_cma_id->device));if (!newxprt)return ; newxprt->sc_cm_id = new_cma_id;
@@ -306,7 +306,7 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,if (sa->sa_family !=AF_INET && sa->sa_family !=AF_INET6 )return ERR_PTR (-EAFNOSUPPORT ); - cma_xprt =svc_rdma_create_xprt (serv, net); + cma_xprt =svc_rdma_create_xprt (serv, net,NUMA_NO_NODE );if (!cma_xprt)return ERR_PTR (-ENOMEM );set_bit (XPT_LISTENER , &cma_xprt->sc_xprt.xpt_flags);
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/4 svcrdma: Refactor the creation of listener CMA ID
From: Chuck Lever <[email protected]>
[ Upstream commit 283d28546234b1764a0a37cb3df30cc3321c75b4 ]
In a moment, I will add a second consumer of CMA ID creation in svcrdma. Refactor so this code can be reused.
Stable-dep-of: 0944462247dc ("svcrdma: Reject connection when transport allocation fails")
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 67 ++++++++++++++---------- 1 file changed, 40 insertions(+), 27 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +40 -27
@@ -65,6 +65,8 @@static struct svcxprt_rdma *svc_rdma_create_xprt (struct svc_serv *serv,struct net *net,int node); +static int svc_rdma_listen_handler (struct rdma_cm_id *cma_id, +struct rdma_cm_event *event); static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, struct net *net, struct sockaddr *sa, int salen,
@@ -125,6 +127,41 @@ static void qp_event_handler(struct ib_event *event, void *context) } } +static struct rdma_cm_id * +svc_rdma_create_listen_id (struct net *net,struct sockaddr *sap, +void *context) +{ +struct rdma_cm_id *listen_id; +int ret; + + listen_id =rdma_create_id (net, svc_rdma_listen_handler, context, +RDMA_PS_TCP ,IB_QPT_RC ); +if (IS_ERR (listen_id)) +return listen_id; + +/* Allow both IPv4 and IPv6 sockets to bind a single port +* at the same time. +*/ +#if IS_ENABLED (CONFIG_IPV6 ) + ret =rdma_set_afonly (listen_id,1 ); +if (ret) + goto out_destroy; +#endif + ret =rdma_bind_addr (listen_id, sap); +if (ret) + goto out_destroy; + + ret =rdma_listen (listen_id,RPCRDMA_LISTEN_BACKLOG ); +if (ret) + goto out_destroy; + +return listen_id; + +out_destroy: +rdma_destroy_id (listen_id); +return ERR_PTR (ret); +} +static struct svcxprt_rdma *svc_rdma_create_xprt (struct svc_serv *serv,struct net *net,int node) {
@@ -302,7 +339,6 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, {struct rdma_cm_id *listen_id;struct svcxprt_rdma *cma_xprt; -int ret;if (sa->sa_family !=AF_INET && sa->sa_family !=AF_INET6 )return ERR_PTR (-EAFNOSUPPORT );
@@ -312,30 +348,13 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,set_bit (XPT_LISTENER , &cma_xprt->sc_xprt.xpt_flags);strcpy (cma_xprt->sc_xprt.xpt_remotebuf,"listener" ); - listen_id =rdma_create_id (net, svc_rdma_listen_handler, cma_xprt, -RDMA_PS_TCP ,IB_QPT_RC ); + listen_id =svc_rdma_create_listen_id (net, sa, cma_xprt);if (IS_ERR (listen_id)) { - ret =PTR_ERR (listen_id); - goto err0; +kfree (cma_xprt); +return (struct svc_xprt *)listen_id; } - -/* Allow both IPv4 and IPv6 sockets to bind a single port -* at the same time. -*/ -#if IS_ENABLED (CONFIG_IPV6 ) - ret =rdma_set_afonly (listen_id,1 ); -if (ret) - goto err1; -#endif - ret =rdma_bind_addr (listen_id, sa); -if (ret) - goto err1; cma_xprt->sc_cm_id = listen_id; - ret =rdma_listen (listen_id,RPCRDMA_LISTEN_BACKLOG ); -if (ret) - goto err1; -/* * We need to use the address from the cm_id in case the * caller specified 0 for the port number.
@@ -344,12 +363,6 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,svc_xprt_set_local (&cma_xprt->sc_xprt, sa, salen);return &cma_xprt->sc_xprt; - - err1: -rdma_destroy_id (listen_id); - err0: -kfree (cma_xprt); -return ERR_PTR (ret); }/*
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/4 svcrdma: Handle ADDR_CHANGE CM event properly
In reply to Sasha LevinFrom: Chuck Lever <[email protected]>
[ Upstream commit d1b586e75ec619dde1af47e21a41a6b1b51874c2 ]
Sagi tells me that when a bonded device reports an address change, the consumer must destroy its listener IDs and create new ones.
See commit a032e4f6d60d ("nvmet-rdma: fix bonding failover possible NULL deref").
Stable-dep-of: 0944462247dc ("svcrdma: Reject connection when transport allocation fails")
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +15 -1
@@ -281,17 +281,31 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id,* * Return values: * %0: Do not destroy @cma_id -* %1: Destroy @cma_id (never returned here) +* %1: Destroy @cma_id * * NB: There is never a DEVICE_REMOVAL event for INADDR_ANY listeners. */ static int svc_rdma_listen_handler (struct rdma_cm_id *cma_id,struct rdma_cm_event *event) { +struct sockaddr *sap = (struct sockaddr *)&cma_id->route.addr.src_addr; +struct svcxprt_rdma *cma_xprt = cma_id->context; +struct svc_xprt *cma_rdma = &cma_xprt->sc_xprt; +struct rdma_cm_id *listen_id; +switch (event->event) {case RDMA_CM_EVENT_CONNECT_REQUEST :handle_connect_req (cma_id, &event->param.conn);break ; +case RDMA_CM_EVENT_ADDR_CHANGE : + listen_id =svc_rdma_create_listen_id (cma_rdma->xpt_net, + sap, cma_xprt); +if (IS_ERR (listen_id)) { +pr_err ("Listener dead, address change failed for device %s\n" , + cma_id->device->name); + }else + cma_xprt->sc_cm_id = listen_id; +return 1 ;default :break ; }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 4/4 svcrdma: Reject connection when transport allocation fails
In reply to Sasha LevinFrom: Chuck Lever <[email protected]>
[ Upstream commit 0944462247dcb7de7622cdaaadf5f05c52707dab ]
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.
--- net/sunrpc/xprtrdma/svc_rdma_transport.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_transport.c +10 -6
@@ -223,12 +223,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;
@@ -238,7 +242,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);
@@ -272,6 +276,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 ; }/**
@@ -295,8 +300,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);
Signature · 1 line
2.53.0