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

From: Gleb Smirnoff <glebius_at_freebsd.org>
Date: Sun, 19 Dec 2021 16:10:54 UTC
On Sun, Dec 19, 2021 at 02:43:09PM +0000, Mateusz Guzik wrote:
M> commit 71a1539e378310120fede100b867ffa995fd9a7a
M> Author:     Mateusz Guzik <mjg@FreeBSD.org>
M> AuthorDate: 2021-12-16 14:11:42 +0000
M> Commit:     Mateusz Guzik <mjg@FreeBSD.org>
M> CommitDate: 2021-12-19 14:43:04 +0000
M> 
M>     inet6: fix a LOR between rip and rawinp
M>     
M>     Running sys/netpfil/pf/fragmentation v6 results in:
M>     
M>     lock order reversal:
M>      1st 0xfffffe00050429a8 rip (rip, sleep mutex) @ /usr/src/sys/netinet6/raw_ip6.c:803
M>      2nd 0xfffff8009491e1d0 rawinp (rawinp, rw) @ /usr/src/sys/netinet6/raw_ip6.c:804
...
M> --- a/sys/netinet6/raw_ip6.c
M> +++ b/sys/netinet6/raw_ip6.c
M> @@ -800,24 +800,24 @@ rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
M>  	if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
M>  		return (error);
M>  
M> -	INP_INFO_WLOCK(&V_ripcbinfo);
M>  	INP_WLOCK(inp);
M> +	INP_INFO_WLOCK(&V_ripcbinfo);
M>  	/* Source address selection. XXX: need pcblookup? */
M>  	NET_EPOCH_ENTER(et);
M>  	error = in6_selectsrc_socket(addr, inp->in6p_outputopts,
M>  	    inp, so->so_cred, scope_ambiguous, &in6a, NULL);
M>  	NET_EPOCH_EXIT(et);
M>  	if (error) {
M> -		INP_WUNLOCK(inp);
M>  		INP_INFO_WUNLOCK(&V_ripcbinfo);
M> +		INP_WUNLOCK(inp);
M>  		return (error);
M>  	}
M>  
M>  	inp->in6p_faddr = addr->sin6_addr;
M>  	inp->in6p_laddr = in6a;
M>  	soisconnected(so);
M> -	INP_WUNLOCK(inp);
M>  	INP_INFO_WUNLOCK(&V_ripcbinfo);
M> +	INP_WUNLOCK(inp);
M>  	return (0);

I actually see no reason for INP_INFO_WLOCK() in this function. That's why it
was missed by my commit. I'm 99% sure that epoch protection is enough for
in6_selectsrc_socket(). But I will leave that to IPv6 experts.

-- 
Gleb Smirnoff