git: 48698ead6ff0 - main - lagg: wrap lagg_port2req() into LAGG_SLOCK()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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;