aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2023-03-26 08:19:56 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2023-04-09 13:52:55 +0000
commit2ccf6388ba60ab8f1acc697a1112d8891102f36f (patch)
treecd5066be9b79c92e37488a335182264cc4e1eab1
parent2e3c94b70d31a7e62a69d345510ac00c787eb875 (diff)
downloadsrc-2ccf6388ba60ab8f1acc697a1112d8891102f36f.tar.gz
src-2ccf6388ba60ab8f1acc697a1112d8891102f36f.zip
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)
-rw-r--r--sys/net/route/route_ctl.h2
-rw-r--r--sys/net/route/route_rtentry.c24
-rw-r--r--sys/net/rtsock.c29
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:
@@ -2274,23 +2269,6 @@ rt_dispatch(struct mbuf *m, sa_family_t saf)
}
/*
- * 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().
*/
static int
@@ -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)) {