git: ff99bfe3ef73 - stable/13 - inet6: protect address manipulation with a lock
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 10 May 2024 16:30:56 UTC
The branch stable/13 has been updated by zlei: URL: https://cgit.FreeBSD.org/src/commit/?id=ff99bfe3ef739a026e0cf554295774c8bf02d326 commit ff99bfe3ef739a026e0cf554295774c8bf02d326 Author: Mateusz Guzik <mjg@FreeBSD.org> AuthorDate: 2023-03-29 12:46:41 +0000 Commit: Zhenlei Huang <zlei@FreeBSD.org> CommitDate: 2024-05-10 16:27:07 +0000 inet6: protect address manipulation with a lock This is a total hack/bare minimum which follows inet4. Otherwise 2 threads removing the same address can easily crash. Reviewed by: kp Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D39317 (cherry picked from commit f5a365e51feea75d1e5ebc86c53808d8cae7b6d7) --- sys/netinet6/in6.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 946a49030920..acf04e1e56bb 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -163,6 +163,9 @@ static int in6_broadcast_ifa(struct ifnet *, struct in6_aliasreq *, #define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa)) #define ia62ifa(ia6) (&((ia6)->ia_ifa)) +static struct sx in6_control_sx; +SX_SYSINIT(in6_control_sx, &in6_control_sx, "in6_control"); + void in6_newaddrmsg(struct in6_ifaddr *ia, int cmd) { @@ -251,6 +254,7 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, int carp_attached = 0; int error; u_long ocmd = cmd; + bool control_locked = false; /* * Compat to make pre-10.x ifconfig(8) operable. @@ -406,6 +410,8 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, if (td != NULL && (error = prison_check_ip6(td->td_ucred, &sa6->sin6_addr)) != 0) return (error); + sx_xlock(&in6_control_sx); + control_locked = true; ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr); } else ia = NULL; @@ -710,6 +716,9 @@ aifaddr_out: error = 0; out: + if (control_locked) + sx_xunlock(&in6_control_sx); + if (ia != NULL) ifa_free(&ia->ia_ifa); return (error);