git: 71a1539e3783 - main - inet6: fix a LOR between rip and rawinp

From: Mateusz Guzik <mjg_at_FreeBSD.org>
Date: Sun, 19 Dec 2021 14:43:09 UTC
The branch main has been updated by mjg:

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

commit 71a1539e378310120fede100b867ffa995fd9a7a
Author:     Mateusz Guzik <mjg@FreeBSD.org>
AuthorDate: 2021-12-16 14:11:42 +0000
Commit:     Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2021-12-19 14:43:04 +0000

    inet6: fix a LOR between rip and rawinp
    
    Running sys/netpfil/pf/fragmentation v6 results in:
    
    lock order reversal:
     1st 0xfffffe00050429a8 rip (rip, sleep mutex) @ /usr/src/sys/netinet6/raw_ip6.c:803
     2nd 0xfffff8009491e1d0 rawinp (rawinp, rw) @ /usr/src/sys/netinet6/raw_ip6.c:804
    lock order rawinp -> rip established at:
    0xffffffff8068e26a at witness_lock_order_add+0x28a
    0xffffffff8068d087 at witness_checkorder+0x627
    0xffffffff805a9f05 at __mtx_lock_flags+0x205
    0xffffffff808102e4 at in_pcballoc+0x204
    0xffffffff808d53c6 at rip6_attach+0x116
    0xffffffff806dc4e8 at socreate+0x368
    0xffffffff806eaedc at kern_socket+0xfc
    0xffffffff806eadcd at sys_socket+0x2d
    0xffffffff80abc774 at syscallenter+0x5c4
    0xffffffff80abbeeb at amd64_syscall+0x1b
     0xffffffff80a8044b at fast_syscall_common+0xf8
    lock order rip -> rawinp attempted at:
    0xffffffff8068dc2a at witness_checkorder+0x11ca
    0xffffffff805d1b7f at _rw_wlock_cookie+0x18f
    0xffffffff808d596c at rip6_connect+0x19c
    0xffffffff806e0842 at soconnectat+0x142
    0xffffffff806ebe36 at kern_connectat+0x136
    0xffffffff806ebcdf at sys_connect+0x4f
    0xffffffff80abc774 at syscallenter+0x5c4
    0xffffffff80abbeeb at amd64_syscall+0x1b
    0xffffffff80a8044b at fast_syscall_common+0xf8
    
    Reviewed by:    glebius
    Fixes:  de2d47842e880281 ("SMR protection for inpcbs")
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D33508
---
 sys/netinet6/raw_ip6.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index 5b1790151009..cb54d1268cef 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -800,24 +800,24 @@ rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
 	if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
 		return (error);
 
-	INP_INFO_WLOCK(&V_ripcbinfo);
 	INP_WLOCK(inp);
+	INP_INFO_WLOCK(&V_ripcbinfo);
 	/* Source address selection. XXX: need pcblookup? */
 	NET_EPOCH_ENTER(et);
 	error = in6_selectsrc_socket(addr, inp->in6p_outputopts,
 	    inp, so->so_cred, scope_ambiguous, &in6a, NULL);
 	NET_EPOCH_EXIT(et);
 	if (error) {
-		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&V_ripcbinfo);
+		INP_WUNLOCK(inp);
 		return (error);
 	}
 
 	inp->in6p_faddr = addr->sin6_addr;
 	inp->in6p_laddr = in6a;
 	soisconnected(so);
-	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&V_ripcbinfo);
+	INP_WUNLOCK(inp);
 	return (0);
 }