Browse Source

[ipoib] Fix a race when chain-loading undionly.kpxe in IPoIB

The Infiniband link status change callback ipoib_link_state_changed()
may be called while the IPoIB device is closed, in which case there
will not be an IPoIB queue pair to be joined to the IPv4 broadcast
group.  This leads to NULL pointer dereferences in ib_mcast_attach()
and ib_mcast_detach().

Fix by not attempting to join (or leave) the broadcast group unless we
actually have an IPoIB queue pair.

Signed-off-by: Wissam Shoukair <wissams@mellanox.com>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Wissam Shoukair 9 years ago
parent
commit
eb8df9a046
3 changed files with 17 additions and 2 deletions
  1. 5
    2
      src/drivers/net/ipoib.c
  2. 6
    0
      src/net/infiniband.c
  3. 6
    0
      src/net/infiniband/ib_mcast.c

+ 5
- 2
src/drivers/net/ipoib.c View File

@@ -791,7 +791,8 @@ static void ipoib_link_state_changed ( struct ib_device *ibdev ) {
791 791
 	int rc;
792 792
 
793 793
 	/* Leave existing broadcast group */
794
-	ipoib_leave_broadcast_group ( ipoib );
794
+	if ( ipoib->qp )
795
+		ipoib_leave_broadcast_group ( ipoib );
795 796
 
796 797
 	/* Update MAC address based on potentially-new GID prefix */
797 798
 	memcpy ( &ipoib->mac.gid.s.prefix, &ibdev->gid.s.prefix,
@@ -806,7 +807,7 @@ static void ipoib_link_state_changed ( struct ib_device *ibdev ) {
806 807
 	netdev_link_err ( netdev, ( rc ? rc : -EINPROGRESS_JOINING ) );
807 808
 
808 809
 	/* Join new broadcast group */
809
-	if ( ib_is_open ( ibdev ) && ib_link_ok ( ibdev ) &&
810
+	if ( ib_is_open ( ibdev ) && ib_link_ok ( ibdev ) && ipoib->qp &&
810 811
 	     ( ( rc = ipoib_join_broadcast_group ( ipoib ) ) != 0 ) ) {
811 812
 		DBGC ( ipoib, "IPoIB %p could not rejoin broadcast group: "
812 813
 		       "%s\n", ipoib, strerror ( rc ) );
@@ -894,7 +895,9 @@ static void ipoib_close ( struct net_device *netdev ) {
894 895
 
895 896
 	/* Tear down the queues */
896 897
 	ib_destroy_qp ( ibdev, ipoib->qp );
898
+	ipoib->qp = NULL;
897 899
 	ib_destroy_cq ( ibdev, ipoib->cq );
900
+	ipoib->cq = NULL;
898 901
 
899 902
 	/* Close IB device */
900 903
 	ib_close ( ibdev );

+ 6
- 0
src/net/infiniband.c View File

@@ -718,6 +718,9 @@ int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
718 718
 	struct ib_multicast_gid *mgid;
719 719
 	int rc;
720 720
 
721
+	/* Sanity check */
722
+	assert ( qp != NULL );
723
+
721 724
 	/* Add to software multicast GID list */
722 725
 	mgid = zalloc ( sizeof ( *mgid ) );
723 726
 	if ( ! mgid ) {
@@ -751,6 +754,9 @@ void ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
751 754
 		       union ib_gid *gid ) {
752 755
 	struct ib_multicast_gid *mgid;
753 756
 
757
+	/* Sanity check */
758
+	assert ( qp != NULL );
759
+
754 760
 	/* Remove from hardware multicast GID list */
755 761
 	ibdev->op->mcast_detach ( ibdev, qp, gid );
756 762
 

+ 6
- 0
src/net/infiniband/ib_mcast.c View File

@@ -150,6 +150,9 @@ int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
150 150
 	DBGC ( ibdev, "IBDEV %p QPN %lx joining " IB_GID_FMT "\n",
151 151
 	       ibdev, qp->qpn, IB_GID_ARGS ( gid ) );
152 152
 
153
+	/* Sanity check */
154
+	assert ( qp != NULL );
155
+
153 156
 	/* Initialise structure */
154 157
 	membership->qp = qp;
155 158
 	memcpy ( &membership->gid, gid, sizeof ( membership->gid ) );
@@ -199,6 +202,9 @@ void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
199 202
 	DBGC ( ibdev, "IBDEV %p QPN %lx leaving " IB_GID_FMT "\n",
200 203
 	       ibdev, qp->qpn, IB_GID_ARGS ( gid ) );
201 204
 
205
+	/* Sanity check */
206
+	assert ( qp != NULL );
207
+
202 208
 	/* Detach from multicast GID */
203 209
 	ib_mcast_detach ( ibdev, qp, &membership->gid );
204 210
 

Loading…
Cancel
Save