| From foo@baz Sun Dec 31 11:13:15 CET 2017 |
| From: Gal Pressman <galp@mellanox.com> |
| Date: Mon, 4 Dec 2017 09:57:43 +0200 |
| Subject: net/mlx5e: Prevent possible races in VXLAN control flow |
| |
| From: Gal Pressman <galp@mellanox.com> |
| |
| |
| [ Upstream commit 0c1cc8b2215f5122ca614b5adca60346018758c3 ] |
| |
| When calling add/remove VXLAN port, a lock must be held in order to |
| prevent race scenarios when more than one add/remove happens at the |
| same time. |
| Fix by holding our state_lock (mutex) as done by all other parts of the |
| driver. |
| Note that the spinlock protecting the radix-tree is still needed in |
| order to synchronize radix-tree access from softirq context. |
| |
| Fixes: b3f63c3d5e2c ("net/mlx5e: Add netdev support for VXLAN tunneling") |
| Signed-off-by: Gal Pressman <galp@mellanox.com> |
| Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/ethernet/mellanox/mlx5/core/vxlan.c | 4 ++++ |
| 1 file changed, 4 insertions(+) |
| |
| --- a/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c |
| +++ b/drivers/net/ethernet/mellanox/mlx5/core/vxlan.c |
| @@ -88,6 +88,7 @@ static void mlx5e_vxlan_add_port(struct |
| struct mlx5e_vxlan *vxlan; |
| int err; |
| |
| + mutex_lock(&priv->state_lock); |
| vxlan = mlx5e_vxlan_lookup_port(priv, port); |
| if (vxlan) { |
| atomic_inc(&vxlan->refcount); |
| @@ -117,6 +118,7 @@ err_free: |
| err_delete_port: |
| mlx5e_vxlan_core_del_port_cmd(priv->mdev, port); |
| free_work: |
| + mutex_unlock(&priv->state_lock); |
| kfree(vxlan_work); |
| } |
| |
| @@ -130,6 +132,7 @@ static void mlx5e_vxlan_del_port(struct |
| struct mlx5e_vxlan *vxlan; |
| bool remove = false; |
| |
| + mutex_lock(&priv->state_lock); |
| spin_lock_bh(&vxlan_db->lock); |
| vxlan = radix_tree_lookup(&vxlan_db->tree, port); |
| if (!vxlan) |
| @@ -147,6 +150,7 @@ out_unlock: |
| mlx5e_vxlan_core_del_port_cmd(priv->mdev, port); |
| kfree(vxlan); |
| } |
| + mutex_unlock(&priv->state_lock); |
| kfree(vxlan_work); |
| } |
| |