Re: [PATCH net v2] net: rds: fix uninitialized trans dereference in CM event handler
Allison Henderson <[email protected]>
| Newsgroups | org.kernel.vger.linux-rdma,org.kernel.vger.linux-kernel,org.kernel.vger.netdev,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
On Tue, 2026-08-25 at 10:12 +0800, Aohan Mei wrote: > From: Aohan Mei <[email protected]> > > rds_rdma_cm_event_handler_cmn() assigns trans only when the RDMA > device is an InfiniBand CA (RDMA_NODE_IB_CA). On any other device > type, e.g. an iWARP RNIC such as siw, trans stays uninitialized, but > the event switch dereferences it: unconditionally in the > RDMA_CM_EVENT_CONNECT_REQUEST case via trans->cm_handle_connect(), > and (with a connection context) in the ROUTE_RESOLVED and > ESTABLISHED cases. > > An RDS listener on an iWARP device therefore crashes the kernel as > soon as a connect request arrives: with CONFIG_INIT_STACK_ALL_ZERO > the wild load becomes a NULL dereference at offset 0xa0 > (&trans->cm_handle_connect) in the iw_cm_wq workqueue. > > GCC masks the bug in default builds by folding the uninitialized > load into &rds_ib_transport; Clang-built kernels take the real > uninitialized path and oops. > > The iWARP transport was dropped long ago and IB is the only > transport left, so make that explicit: initialize trans to > &rds_ib_transport at declaration, drop the conditional assignment, > and reject events from non-IB devices before the event switch. > > Fixes: dcdede0406d3 ("RDS: Drop stale iWARP RDMA transport") > Reported-by: TencentOS Corvus AI <[email protected]> > Cc: [email protected] > Assisted-by: CodeBuddy:Kimi-K3 > Signed-off-by: Aohan Mei <[email protected]> This looks good to me. Thanks for the quick response. Reviewed-by: Allison Henderson <[email protected]> > --- > v2: > - Enforce the IB transport directly instead of NULL-guarding trans, > as suggested by Allison Henderson. > v1: https://lore.kernel.org/netdev/[email protected] > net/rds/rdma_transport.c | 11 +++++++---- > 1 file changed, 7 insertions(+), 4 deletions(-) > > diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c > index b15cf316b23a..2c5481f1fcb4 100644 > --- a/net/rds/rdma_transport.c > +++ b/net/rds/rdma_transport.c > @@ -52,7 +52,7 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, > { > /* this can be null in the listening path */ > struct rds_connection *conn = cm_id->context; > - struct rds_transport *trans; > + struct rds_transport *trans = &rds_ib_transport; > int ret = 0; > int *err; > u8 len; > @@ -60,9 +60,6 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, > rdsdebug("conn %p id %p handling event %u (%s)\n", conn, cm_id, > event->event, rdma_event_msg(event->event)); > > - if (cm_id->device->node_type == RDMA_NODE_IB_CA) > - trans = &rds_ib_transport; > - > /* Prevent shutdown from tearing down the connection > * while we're executing. */ > if (conn) { > @@ -80,6 +77,12 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, > } > } > > + /* Only the IB transport is supported. */ > + if (cm_id->device->node_type != RDMA_NODE_IB_CA) { > + ret = 1; > + goto out; > + } > + > switch (event->event) { > case RDMA_CM_EVENT_CONNECT_REQUEST: > ret = trans->cm_handle_connect(cm_id, event, isv6);