git: 48698ead6ff0 - main - lagg: wrap lagg_port2req() into LAGG_SLOCK()

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Sat, 24 Feb 2024 01:57:14 UTC
The branch main has been updated by glebius:

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

commit 48698ead6ff0640098e6aecdd5cbf6ea8f5ac177
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2024-02-24 01:56:46 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2024-02-24 01:56:46 +0000

    lagg: wrap lagg_port2req() into LAGG_SLOCK()
    
    Although a port addition is coded in a sequence where first all softc
    information is fulfilled and only then it is attached to the lagg, we
    still need a locking primitive to guarantee cache invalidation.  Panic
    observed in the wild shows that lacp_portreq() called via
    lagg_port_ioctl(SIOCGLAGGPORT) immediately after port creation may see
    lp->lp_psc as NULL and panic.  In the core file we will see valid data
    all around.  A race via lagg_ioctl() wasn't observed but potentially
    is possible.
    
    Differential Revision:  https://reviews.freebsd.org/D43501
---
 sys/net/if_lagg.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 9746d4115bc6..554d8c2c1bcb 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -83,8 +83,10 @@ MODULE_DEPEND(if_lagg, netmap, 1, 1, 1);
 #define	LAGG_SX_DESTROY(_sc)	sx_destroy(&(_sc)->sc_sx)
 #define	LAGG_XLOCK(_sc)		sx_xlock(&(_sc)->sc_sx)
 #define	LAGG_XUNLOCK(_sc)	sx_xunlock(&(_sc)->sc_sx)
-#define	LAGG_SXLOCK_ASSERT(_sc)	sx_assert(&(_sc)->sc_sx, SA_LOCKED)
 #define	LAGG_XLOCK_ASSERT(_sc)	sx_assert(&(_sc)->sc_sx, SA_XLOCKED)
+#define	LAGG_SLOCK(_sc)		sx_slock(&(_sc)->sc_sx)
+#define	LAGG_SUNLOCK(_sc)	sx_sunlock(&(_sc)->sc_sx)
+#define	LAGG_SXLOCK_ASSERT(_sc)	sx_assert(&(_sc)->sc_sx, SA_LOCKED)
 
 /* Special flags we should propagate to the lagg ports. */
 static struct {
@@ -1044,7 +1046,9 @@ lagg_port_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 			break;
 		}
 
+		LAGG_SLOCK(sc);
 		lagg_port2req(lp, rp);
+		LAGG_SUNLOCK(sc);
 		NET_EPOCH_EXIT(et);
 		break;
 
@@ -1581,7 +1585,9 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 			break;
 		}
 
+		LAGG_SLOCK(sc);
 		lagg_port2req(lp, rp);
+		LAGG_SUNLOCK(sc);
 		NET_EPOCH_EXIT(et);
 		if_rele(tpif);
 		break;