Date: Mon, 12 Jul 2021 13:10:09 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: cd2c05d323d2 - main - ipoib: Fix for accessing uninitialized pointers and freed memory during attach and detach. Message-ID: <202107121310.16CDA9mQ098911@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by hselasky: URL: https://cgit.FreeBSD.org/src/commit/?id=cd2c05d323d272163d04dd94caabe018ca2d4dc5 commit cd2c05d323d272163d04dd94caabe018ca2d4dc5 Author: Hans Petter Selasky <hselasky@FreeBSD.org> AuthorDate: 2021-07-12 13:01:19 +0000 Commit: Hans Petter Selasky <hselasky@FreeBSD.org> CommitDate: 2021-07-12 13:01:19 +0000 ipoib: Fix for accessing uninitialized pointers and freed memory during attach and detach. Call infiniband_ifdetach() early to stop ifioctl(9) calls from user-space during device removal. Also make sure that ifioctl(9) calls are blocked from executing until the device is fully initialized. Ideally we would delay the infiniband_ifattach() call, but because part of the initialization is to update the link level address, that is not possible without more significant changes. MFC after: 1 week Reviewed by: kib Sponsored by: Mellanox Technologies // NVIDIA Networking --- sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c | 34 +++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c index b0f69842ac02..0982af9fb904 100644 --- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -278,7 +278,13 @@ ipoib_ioctl(struct ifnet *ifp, u_long command, caddr_t data) int error = 0; /* check if detaching */ - if (priv == NULL || priv->gone != 0) + if (priv == NULL) + return (ENXIO); + /* wait for device to become ready, if any */ + while (priv->gone == 2) + pause("W", 1); + /* check for device gone */ + if (priv->gone != 0) return (ENXIO); switch (command) { @@ -822,7 +828,7 @@ out: } static void -ipoib_detach(struct ipoib_dev_priv *priv) +ipoib_ifdetach(struct ipoib_dev_priv *priv) { struct ifnet *dev; @@ -830,6 +836,16 @@ ipoib_detach(struct ipoib_dev_priv *priv) if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { priv->gone = 1; infiniband_ifdetach(dev); + } +} + +static void +ipoib_detach(struct ipoib_dev_priv *priv) +{ + struct ifnet *dev; + + dev = priv->dev; + if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { if_free(dev); free_unr(ipoib_unrhdr, priv->unit); } else @@ -845,6 +861,7 @@ ipoib_dev_cleanup(struct ipoib_dev_priv *priv) /* Delete any child interfaces first */ list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) { + ipoib_ifdetach(cpriv); ipoib_dev_cleanup(cpriv); ipoib_detach(cpriv); } @@ -897,6 +914,7 @@ ipoib_intf_alloc(const char *name) return NULL; } dev->if_softc = priv; + priv->gone = 2; /* initializing */ priv->unit = alloc_unr(ipoib_unrhdr); if (priv->unit == -1) { if_free(dev); @@ -906,7 +924,7 @@ ipoib_intf_alloc(const char *name) if_initname(dev, name, priv->unit); dev->if_flags = IFF_BROADCAST | IFF_MULTICAST; - infiniband_ifattach(dev, NULL, priv->broadcastaddr); + infiniband_ifattach(priv->dev, NULL, priv->broadcastaddr); dev->if_init = ipoib_init; dev->if_ioctl = ipoib_ioctl; @@ -915,7 +933,7 @@ ipoib_intf_alloc(const char *name) dev->if_snd.ifq_maxlen = ipoib_sendq_size * 2; priv->dev = dev; - if_link_state_change(dev, LINK_STATE_DOWN); + if_link_state_change(priv->dev, LINK_STATE_DOWN); return dev->if_softc; } @@ -1000,7 +1018,7 @@ ipoib_add_port(const char *format, struct ib_device *hca, u8 port) hca->name, port, result); goto device_init_failed; } - memcpy(IF_LLADDR(priv->dev) + 4, priv->local_gid.raw, sizeof (union ib_gid)); + memcpy(IF_LLADDR(priv->dev) + 4, priv->local_gid.raw, sizeof(union ib_gid)); result = ipoib_dev_init(priv, hca, port); if (result < 0) { @@ -1022,12 +1040,15 @@ ipoib_add_port(const char *format, struct ib_device *hca, u8 port) } if_printf(priv->dev, "Attached to %s port %d\n", hca->name, port); + priv->gone = 0; /* ready */ + return priv->dev; event_failed: ipoib_dev_cleanup(priv); device_init_failed: + ipoib_ifdetach(priv); ipoib_detach(priv); alloc_mem_failed: @@ -1088,12 +1109,11 @@ ipoib_remove_one(struct ib_device *device, void *client_data) if (rdma_port_get_link_layer(device, priv->port) != IB_LINK_LAYER_INFINIBAND) continue; + ipoib_ifdetach(priv); ipoib_stop(priv); ib_unregister_event_handler(&priv->event_handler); - /* dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP); */ - flush_workqueue(ipoib_workqueue); ipoib_dev_cleanup(priv);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202107121310.16CDA9mQ098911>