git: a306ed50ecd5 - main - inpcb: Restore missing validation of local addresses for jailed sockets

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 30 May 2023 19:30:08 UTC
The branch main has been updated by markj:

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

commit a306ed50ecd57f060a549c14bc53a60b34aaa6bb
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2023-05-30 19:15:48 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-05-30 19:15:48 +0000

    inpcb: Restore missing validation of local addresses for jailed sockets
    
    When looking up a listening socket, the SMR-protected lookup routine may
    return a jailed socket with no local address.  This happens when using
    classic jails with more than one IP address; in a single-IP classic
    jail, a bound socket's local address is always rewritten to be that of
    the jail.
    
    After commit 7b92493ab1d4, the lookup path failed to check whether the
    jail corresponding to a matched wildcard socket actually owns the
    address, and would return the match regardless.  Restore the omitted
    checks.
    
    Fixes:          7b92493ab1d4 ("inpcb: Avoid inp_cred dereferences in SMR-protected lookup")
    Reported by:    peter
    Reviewed by:    bz
    Differential Revision:  https://reviews.freebsd.org/D40268
---
 sys/netinet/in_pcb.c   | 6 ++++--
 sys/netinet6/in6_pcb.c | 6 ++++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 350d08360105..5fddff89dd0a 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -2254,8 +2254,10 @@ in_pcblookup_hash_wild_smr(struct inpcbinfo *pcbinfo, struct in_addr faddr,
 			continue;
 
 		if (__predict_true(inp_smr_lock(inp, lockflags))) {
-			if (__predict_true(in_pcblookup_wild_match(inp, laddr,
-			    lport) != INPLOOKUP_MATCH_NONE))
+			match = in_pcblookup_wild_match(inp, laddr, lport);
+			if (match != INPLOOKUP_MATCH_NONE &&
+			    prison_check_ip4_locked(inp->inp_cred->cr_prison,
+			    &laddr) == 0)
 				return (inp);
 			inp_unlock(inp, lockflags);
 		}
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index da7ed5ca79e0..43f567461598 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -1021,8 +1021,10 @@ in6_pcblookup_hash_wild_smr(struct inpcbinfo *pcbinfo,
 			continue;
 
 		if (__predict_true(inp_smr_lock(inp, lockflags))) {
-			if (__predict_true(in6_pcblookup_wild_match(inp, laddr,
-			    lport) != INPLOOKUP_MATCH_NONE))
+			match = in6_pcblookup_wild_match(inp, laddr, lport);
+			if (match != INPLOOKUP_MATCH_NONE &&
+			    prison_check_ip6_locked(inp->inp_cred->cr_prison,
+			    laddr) == 0)
 				return (inp);
 			inp_unlock(inp, lockflags);
 		}