git: 2ccf6388ba60 - stable/13 - routing: add public rt_is_exportable() version to check if the route can be exported to userland when jailed.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Sun, 09 Apr 2023 13:53:14 UTC
The branch stable/13 has been updated by melifaro:

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

commit 2ccf6388ba60ab8f1acc697a1112d8891102f36f
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2023-03-26 08:19:56 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2023-04-09 13:52:55 +0000

    routing: add public rt_is_exportable() version to check if
     the route can be exported to userland when jailed.
    
    Differential Revision: https://reviews.freebsd.org/D39204
    MFC after:      2 weeks
    
    (cherry picked from commit 2cda6a2fb0d9473a53931dc2b0171af54dd79b04)
---
 sys/net/route/route_ctl.h     |  2 ++
 sys/net/route/route_rtentry.c | 24 ++++++++++++++++++++++++
 sys/net/rtsock.c              | 29 ++++-------------------------
 3 files changed, 30 insertions(+), 25 deletions(-)

diff --git a/sys/net/route/route_ctl.h b/sys/net/route/route_ctl.h
index e8560e681ddb..b65b64fcdaa0 100644
--- a/sys/net/route/route_ctl.h
+++ b/sys/net/route/route_ctl.h
@@ -121,6 +121,7 @@ void rib_foreach_table_walk_del(int family, rib_filter_f_t *filter_f, void *arg)
 
 struct nhop_object;
 struct nhgrp_object;
+struct ucred;
 
 const struct rtentry *rib_lookup_prefix(uint32_t fibnum, int family,
     const struct sockaddr *dst, const struct sockaddr *netmask,
@@ -133,6 +134,7 @@ bool rt_is_host(const struct rtentry *rt);
 sa_family_t rt_get_family(const struct rtentry *);
 struct nhop_object *rt_get_raw_nhop(const struct rtentry *rt);
 void rt_get_rnd(const struct rtentry *rt, struct route_nhop_data *rnd);
+bool rt_is_exportable(const struct rtentry *rt, struct ucred *cred);
 #ifdef INET
 struct in_addr;
 void rt_get_inet_prefix_plen(const struct rtentry *rt, struct in_addr *paddr,
diff --git a/sys/net/route/route_rtentry.c b/sys/net/route/route_rtentry.c
index 64900ae3ae39..7bf624f01540 100644
--- a/sys/net/route/route_rtentry.c
+++ b/sys/net/route/route_rtentry.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/socket.h>
+#include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/rmlock.h>
@@ -198,6 +199,29 @@ rt_get_rnd(const struct rtentry *rt, struct route_nhop_data *rnd)
 	rnd->rnd_weight = rt->rt_weight;
 }
 
+/*
+ * If the process in in jail w/o VNET, export only host routes for the
+ *  addresses assigned to the jail.
+ * Otherwise, allow exporting the entire table.
+ */
+bool
+rt_is_exportable(const struct rtentry *rt, struct ucred *cred)
+{
+	if (!rt_is_host(rt)) {
+		/*
+		 * Performance optimisation: only host routes are allowed
+		 * in the jail w/o vnet.
+		 */
+		if (jailed_without_vnet(cred))
+			return (false);
+	} else {
+		if (prison_if(cred, rt_key_const(rt)) != 0)
+			return (false);
+	}
+
+	return (true);
+}
+
 #ifdef INET
 /*
  * Stores IPv4 address and prefix length of @rt inside
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index fc9439602c13..0c6d856ed7ad 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -208,8 +208,6 @@ static int	update_rtm_from_rc(struct rt_addrinfo *info,
 static void	send_rtm_reply(struct socket *so, struct rt_msghdr *rtm,
 			struct mbuf *m, sa_family_t saf, u_int fibnum,
 			int rtm_errno);
-static bool	can_export_rte(struct ucred *td_ucred, bool rt_is_host,
-			const struct sockaddr *rt_dst);
 static void	rtsock_notify_event(uint32_t fibnum, const struct rib_cmd_info *rc);
 static void	rtsock_ifmsg(struct ifnet *ifp, int if_flags_mask);
 
@@ -1229,11 +1227,8 @@ route_output(struct mbuf *m, struct socket *so, ...)
 			senderr(error);
 		nh = rc.rc_nh_new;
 
-		if (!can_export_rte(curthread->td_ucred,
-		    info.rti_info[RTAX_NETMASK] == NULL,
-		    info.rti_info[RTAX_DST])) {
+		if (!rt_is_exportable(rc.rc_rt, curthread->td_ucred))
 			senderr(ESRCH);
-		}
 		break;
 
 	default:
@@ -2273,23 +2268,6 @@ rt_dispatch(struct mbuf *m, sa_family_t saf)
 	netisr_queue(NETISR_ROUTE, m);	/* mbuf is free'd on failure. */
 }
 
-/*
- * Checks if rte can be exported w.r.t jails/vnets.
- *
- * Returns true if it can, false otherwise.
- */
-static bool
-can_export_rte(struct ucred *td_ucred, bool rt_is_host,
-    const struct sockaddr *rt_dst)
-{
-
-	if ((!rt_is_host) ? jailed_without_vnet(td_ucred)
-	    : prison_if(td_ucred, rt_dst) != 0)
-		return (false);
-	return (true);
-}
-
-
 /*
  * This is used in dumping the kernel table via sysctl().
  */
@@ -2301,9 +2279,10 @@ sysctl_dumpentry(struct rtentry *rt, void *vw)
 
 	NET_EPOCH_ASSERT();
 
-	export_rtaddrs(rt, w->dst, w->mask);
-	if (!can_export_rte(w->w_req->td->td_ucred, rt_is_host(rt), w->dst))
+	if (!rt_is_exportable(rt, w->w_req->td->td_ucred))
 		return (0);
+
+	export_rtaddrs(rt, w->dst, w->mask);
 	nh = rt_get_raw_nhop(rt);
 #ifdef ROUTE_MPATH
 	if (NH_IS_NHGRP(nh)) {