Blob Blame History Raw
From: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Subject: mlx5: kabi protect lag_mp
Patch-mainline: Never, kABI workaround
References: git-fixes

Commits 27b0420fd959 ("net/mlx5e: Lag, Fix use-after-free in fib event
handler") and 4a2a664ed879 ("net/mlx5e: Lag, Don't skip fib events on
current dst") extend struct lag_mp, which breaks KABI. Since lag_mp
is embedded into struct mlx5_lag we introduce a new struct holding
the new fields, place them kabi protected inside struct mlx5_lag and
change all code referencing them.

Signed-off-by: homas Bogendoerfer <tbogendoerfer@suse.de>

---
 drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h |    3 +
 drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c  |   38 ++++++++++++----------
 drivers/net/ethernet/mellanox/mlx5/core/lag/mp.h  |   15 +++++---
 3 files changed, 33 insertions(+), 23 deletions(-)

--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
@@ -54,6 +54,9 @@ struct mlx5_lag {
 	struct notifier_block     nb;
 	struct lag_mp             lag_mp;
 	struct mlx5_lag_port_sel  port_sel;
+#ifndef __GENKSYMS__
+	struct lag_mp_fib         lag_mp_fib;
+#endif
 };
 
 static inline struct mlx5_lag *
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
@@ -100,12 +100,15 @@ static void mlx5_lag_fib_event_flush(str
 	flush_workqueue(mp->wq);
 }
 
-static void mlx5_lag_fib_set(struct lag_mp *mp, struct fib_info *fi, u32 dst, int dst_len)
+static void mlx5_lag_fib_set(struct mlx5_lag *ldev, struct fib_info *fi, u32 dst, int dst_len)
 {
-	mp->fib.mfi = fi;
-	mp->fib.priority = fi->fib_priority;
-	mp->fib.dst = dst;
-	mp->fib.dst_len = dst_len;
+	struct lag_mp *mp = &ldev->lag_mp;
+	struct lag_mp_fib *mp_fib = &ldev->lag_mp_fib;
+
+	mp->mfi = fi;
+	mp_fib->priority = fi->fib_priority;
+	mp_fib->dst = dst;
+	mp_fib->dst_len = dst_len;
 }
 
 struct mlx5_fib_event_work {
@@ -123,21 +126,22 @@ static void mlx5_lag_fib_route_event(str
 {
 	struct fib_info *fi = fen_info->fi;
 	struct lag_mp *mp = &ldev->lag_mp;
+	struct lag_mp_fib *mp_fib = &ldev->lag_mp_fib;
 	struct fib_nh *fib_nh0, *fib_nh1;
 	unsigned int nhs;
 
 	/* Handle delete event */
 	if (event == FIB_EVENT_ENTRY_DEL) {
 		/* stop track */
-		if (mp->fib.mfi == fi)
-			mp->fib.mfi = NULL;
+		if (mp->mfi == fi)
+			mp->mfi = NULL;
 		return;
 	}
 
 	/* Handle multipath entry with lower priority value */
-	if (mp->fib.mfi && mp->fib.mfi != fi &&
-	    (mp->fib.dst != fen_info->dst || mp->fib.dst_len != fen_info->dst_len) &&
-	    fi->fib_priority >= mp->fib.priority)
+	if (mp->mfi && mp->mfi != fi &&
+	    (mp_fib->dst != fen_info->dst || mp_fib->dst_len != fen_info->dst_len) &&
+	    fi->fib_priority >= mp_fib->priority)
 		return;
 
 	/* Handle add/replace event */
@@ -153,7 +157,7 @@ static void mlx5_lag_fib_route_event(str
 
 			i++;
 			mlx5_lag_set_port_affinity(ldev, i);
-			mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len);
+			mlx5_lag_fib_set(ldev, fi, fen_info->dst, fen_info->dst_len);
 		}
 
 		return;
@@ -175,7 +179,7 @@ static void mlx5_lag_fib_route_event(str
 	}
 
 	/* First time we see multipath route */
-	if (!mp->fib.mfi && !__mlx5_lag_is_active(ldev)) {
+	if (!mp->mfi && !__mlx5_lag_is_active(ldev)) {
 		struct lag_tracker tracker;
 
 		tracker = ldev->tracker;
@@ -183,7 +187,7 @@ static void mlx5_lag_fib_route_event(str
 	}
 
 	mlx5_lag_set_port_affinity(ldev, MLX5_LAG_NORMAL_AFFINITY);
-	mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len);
+	mlx5_lag_fib_set(ldev, fi, fen_info->dst, fen_info->dst_len);
 }
 
 static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev,
@@ -194,7 +198,7 @@ static void mlx5_lag_fib_nexthop_event(s
 	struct lag_mp *mp = &ldev->lag_mp;
 
 	/* Check the nh event is related to the route */
-	if (!mp->fib.mfi || mp->fib.mfi != fi)
+	if (!mp->mfi || mp->mfi != fi)
 		return;
 
 	/* nh added/removed */
@@ -323,7 +327,7 @@ void mlx5_lag_mp_reset(struct mlx5_lag *
 	/* Clear mfi, as it might become stale when a route delete event
 	 * has been missed, see mlx5_lag_fib_route_event().
 	 */
-	ldev->lag_mp.fib.mfi = NULL;
+	ldev->lag_mp.mfi = NULL;
 }
 
 int mlx5_lag_mp_init(struct mlx5_lag *ldev)
@@ -334,7 +338,7 @@ int mlx5_lag_mp_init(struct mlx5_lag *ld
 	/* always clear mfi, as it might become stale when a route delete event
 	 * has been missed
 	 */
-	mp->fib.mfi = NULL;
+	mp->mfi = NULL;
 
 	if (mp->fib_nb.notifier_call)
 		return 0;
@@ -364,5 +368,5 @@ void mlx5_lag_mp_cleanup(struct mlx5_lag
 	unregister_fib_notifier(&init_net, &mp->fib_nb);
 	destroy_workqueue(mp->wq);
 	mp->fib_nb.notifier_call = NULL;
-	mp->fib.mfi = NULL;
+	mp->mfi = NULL;
 }
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.h
@@ -15,15 +15,18 @@ enum mlx5_lag_port_affinity {
 
 struct lag_mp {
 	struct notifier_block     fib_nb;
-	struct {
-		const void        *mfi; /* used in tracking fib events */
-		u32               priority;
-		u32               dst;
-		int               dst_len;
-	} fib;
+	struct fib_info           *mfi; /* used in tracking fib events */
 	struct workqueue_struct   *wq;
 };
 
+#ifndef __GENKSYMS__
+struct lag_mp_fib {
+	u32               priority;
+	u32               dst;
+	int               dst_len;
+};
+#endif
+
 #ifdef CONFIG_MLX5_ESWITCH
 
 void mlx5_lag_mp_reset(struct mlx5_lag *ldev);