git: fadbb6f85a2e - main - lagg: remove use of net epoch in the ioctl paths

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Mon, 06 May 2024 22:27:52 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=fadbb6f85a2ea6d804c12848e3fcfdb6f62fc039

commit fadbb6f85a2ea6d804c12848e3fcfdb6f62fc039
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2024-05-06 22:25:53 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2024-05-06 22:27:32 +0000

    lagg: remove use of net epoch in the ioctl paths
    
    Rely on LAGG_SLOCK() instead.  The use of network epoch(9) here was added
    in 6573d7580b851 (later tidied by 87bf9b9cbeebc) as a large sweep that
    blindly substituted blocking kernel primitives with epoch(9).  In these
    particular code paths use of epoch(9) is incorrect and doesn't provide any
    protection against a stale pointer.  Recent fix 48698ead6ff0, which should
    actually have removed the epoch use, created a potential sleeping in epoch
    problem.
---
 sys/net/if_lagg.c | 33 +++++++++++----------------------
 1 file changed, 11 insertions(+), 22 deletions(-)

diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 1f169ee32696..bb882ac819ad 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -1015,7 +1015,6 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport)
 static int
 lagg_port_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 {
-	struct epoch_tracker et;
 	struct lagg_reqport *rp = (struct lagg_reqport *)data;
 	struct lagg_softc *sc;
 	struct lagg_port *lp = NULL;
@@ -1040,17 +1039,13 @@ lagg_port_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 			break;
 		}
 
-		NET_EPOCH_ENTER(et);
-		if ((lp = ifp->if_lagg) == NULL || lp->lp_softc != sc) {
-			error = ENOENT;
-			NET_EPOCH_EXIT(et);
-			break;
-		}
-
 		LAGG_SLOCK(sc);
-		lagg_port2req(lp, rp);
+		if (__predict_true((lp = ifp->if_lagg) != NULL &&
+		    lp->lp_softc == sc))
+			lagg_port2req(lp, rp);
+		else
+			error = ENOENT;	/* XXXGL: can happen? */
 		LAGG_SUNLOCK(sc);
-		NET_EPOCH_EXIT(et);
 		break;
 
 	case SIOCSIFCAP:
@@ -1350,7 +1345,6 @@ lagg_stop(struct lagg_softc *sc)
 static int
 lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 {
-	struct epoch_tracker et;
 	struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc;
 	struct lagg_reqall *ra = (struct lagg_reqall *)data;
 	struct lagg_reqopts *ro = (struct lagg_reqopts *)data;
@@ -1600,21 +1594,16 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 			break;
 		}
 
-		NET_EPOCH_ENTER(et);
-		if ((lp = (struct lagg_port *)tpif->if_lagg) == NULL ||
-		    lp->lp_softc != sc) {
-			error = ENOENT;
-			NET_EPOCH_EXIT(et);
-			if_rele(tpif);
-			break;
-		}
-
 		LAGG_SLOCK(sc);
-		lagg_port2req(lp, rp);
+		if (__predict_true((lp = tpif->if_lagg) != NULL &&
+		    lp->lp_softc == sc))
+			lagg_port2req(lp, rp);
+		else
+			error = ENOENT;	/* XXXGL: can happen? */
 		LAGG_SUNLOCK(sc);
-		NET_EPOCH_EXIT(et);
 		if_rele(tpif);
 		break;
+
 	case SIOCSLAGGPORT:
 		error = priv_check(td, PRIV_NET_LAGG);
 		if (error)