Date: Wed, 12 Dec 2018 12:22:40 +0000 (UTC) From: Hans Petter Selasky <hselasky@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r341934 - in stable/11/sys/dev/mlx5: . mlx5_core Message-ID: <201812121222.wBCCMeEv080057@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hselasky Date: Wed Dec 12 12:22:40 2018 New Revision: 341934 URL: https://svnweb.freebsd.org/changeset/base/341934 Log: MFC r341560: mlx5: Fix use-after-free in self-healing flow When the mlx5 health mechanism detects a problem while the driver is in the middle of init_one or remove_one, the driver needs to prevent the health mechanism from scheduling future work; if future work is scheduled, there is a problem with use-after-free: the system WQ tries to run the work item (which has been freed) at the scheduled future time. Prevent this by disabling work item scheduling in the health mechanism when the driver is in the middle of init_one() or remove_one(). Sponsored by: Mellanox Technologies Modified: stable/11/sys/dev/mlx5/driver.h stable/11/sys/dev/mlx5/mlx5_core/mlx5_health.c stable/11/sys/dev/mlx5/mlx5_core/mlx5_main.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/dev/mlx5/driver.h ============================================================================== --- stable/11/sys/dev/mlx5/driver.h Wed Dec 12 12:22:28 2018 (r341933) +++ stable/11/sys/dev/mlx5/driver.h Wed Dec 12 12:22:40 2018 (r341934) @@ -897,7 +897,7 @@ void mlx5_unmap_free_uar(struct mlx5_core_dev *mdev, s void mlx5_health_cleanup(struct mlx5_core_dev *dev); int mlx5_health_init(struct mlx5_core_dev *dev); void mlx5_start_health_poll(struct mlx5_core_dev *dev); -void mlx5_stop_health_poll(struct mlx5_core_dev *dev); +void mlx5_stop_health_poll(struct mlx5_core_dev *dev, bool disable_health); void mlx5_drain_health_wq(struct mlx5_core_dev *dev); void mlx5_drain_health_recovery(struct mlx5_core_dev *dev); void mlx5_trigger_health_work(struct mlx5_core_dev *dev); Modified: stable/11/sys/dev/mlx5/mlx5_core/mlx5_health.c ============================================================================== --- stable/11/sys/dev/mlx5/mlx5_core/mlx5_health.c Wed Dec 12 12:22:28 2018 (r341933) +++ stable/11/sys/dev/mlx5/mlx5_core/mlx5_health.c Wed Dec 12 12:22:40 2018 (r341934) @@ -516,9 +516,17 @@ void mlx5_start_health_poll(struct mlx5_core_dev *dev) round_jiffies(jiffies + MLX5_HEALTH_POLL_INTERVAL)); } -void mlx5_stop_health_poll(struct mlx5_core_dev *dev) +void mlx5_stop_health_poll(struct mlx5_core_dev *dev, bool disable_health) { struct mlx5_core_health *health = &dev->priv.health; + unsigned long flags; + + if (disable_health) { + spin_lock_irqsave(&health->wq_lock, flags); + set_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags); + set_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags); + spin_unlock_irqrestore(&health->wq_lock, flags); + } del_timer_sync(&health->timer); } Modified: stable/11/sys/dev/mlx5/mlx5_core/mlx5_main.c ============================================================================== --- stable/11/sys/dev/mlx5/mlx5_core/mlx5_main.c Wed Dec 12 12:22:28 2018 (r341933) +++ stable/11/sys/dev/mlx5/mlx5_core/mlx5_main.c Wed Dec 12 12:22:40 2018 (r341934) @@ -1089,7 +1089,7 @@ err_cleanup_once: mlx5_cleanup_once(dev); err_stop_poll: - mlx5_stop_health_poll(dev); + mlx5_stop_health_poll(dev, boot); if (mlx5_cmd_teardown_hca(dev)) { device_printf((&dev->pdev->dev)->bsddev, "ERR: ""tear_down_hca failed, skip cleanup\n"); goto out_err; @@ -1141,7 +1141,7 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, mlx5_disable_msix(dev); if (cleanup) mlx5_cleanup_once(dev); - mlx5_stop_health_poll(dev); + mlx5_stop_health_poll(dev, cleanup); err = mlx5_cmd_teardown_hca(dev); if (err) { device_printf((&dev->pdev->dev)->bsddev, "ERR: ""tear_down_hca failed, skip cleanup\n"); @@ -1387,6 +1387,12 @@ static int mlx5_try_fast_unload(struct mlx5_core_dev * mlx5_core_dbg(dev, "Device in internal error state, giving up\n"); return -EAGAIN; } + + /* Panic tear down fw command will stop the PCI bus communication + * with the HCA, so the health polll is no longer needed. + */ + mlx5_drain_health_wq(dev); + mlx5_stop_health_poll(dev, false); err = mlx5_cmd_force_teardown_hca(dev); if (err) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201812121222.wBCCMeEv080057>