diff --git a/net/rds/ib.c b/net/rds/ib.c index 786f39169bc1..4ea9838d090c 100644 --- a/net/rds/ib.c +++ b/net/rds/ib.c @@ -414,13 +414,14 @@ static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr, bool isv4; isv4 = ipv6_addr_v4mapped(addr); - /* Create a CMA ID and try to bind it. This catches both - * IB and iWARP capable NICs. - */ + /* Create a CMA ID restricted to IB devices and try to bind it. */ cm_id = rdma_create_id(&init_net, rds_rdma_cm_event_handler, NULL, RDMA_PS_TCP, IB_QPT_RC); if (IS_ERR(cm_id)) return PTR_ERR(cm_id); + ret = rdma_restrict_node_type(cm_id, RDMA_NODE_IB_CA); + if (ret) + goto out; if (isv4) { memset(&sin, 0, sizeof(sin)); @@ -473,12 +474,9 @@ static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr, #endif } - /* rdma_bind_addr will only succeed for IB & iWARP devices */ + /* the restriction above means this only succeeds for IB devices */ ret = rdma_bind_addr(cm_id, sa); - /* due to this, we will claim to support iWARP devices unless we - check node_type. */ - if (ret || !cm_id->device || - cm_id->device->node_type != RDMA_NODE_IB_CA) + if (ret || !cm_id->device) ret = -EADDRNOTAVAIL; rdsdebug("addr %pI6c%%%u ret %d node type %d\n", diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 3ebe13d00953..3ed03ad32812 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c @@ -999,6 +999,18 @@ int rds_ib_conn_path_connect(struct rds_conn_path *cp) goto out; } + /* rds_ib_laddr_check() only vouched for the local address being + * on an IB device; the address resolution below picks the device + * on its own, so restrict it to the same kind. + */ + ret = rdma_restrict_node_type(ic->i_cm_id, RDMA_NODE_IB_CA); + if (ret) { + rdsdebug("rdma_restrict_node_type() failed: %d\n", ret); + rdma_destroy_id(ic->i_cm_id); + ic->i_cm_id = NULL; + goto out; + } + rdsdebug("created cm id %p for conn %p\n", ic->i_cm_id, conn); if (ipv6_addr_v4mapped(&conn->c_faddr)) { diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c index b15cf316b23a..91ff1dde26af 100644 --- a/net/rds/rdma_transport.c +++ b/net/rds/rdma_transport.c @@ -210,6 +210,14 @@ static int rds_rdma_listen_init_common(rdma_cm_event_handler handler, return ret; } + /* Only the IB transport is left, so only listen on IB devices */ + ret = rdma_restrict_node_type(cm_id, RDMA_NODE_IB_CA); + if (ret) { + pr_err("RDS/RDMA: failed to setup listener, rdma_restrict_node_type() returned %d\n", + ret); + goto out; + } + /* * XXX I bet this binds the cm_id to a device. If we want to support * fail-over we'll have to take this into consideration.