git: ed86cf0121f9 - stable/12 - ipfilter: Support only jails in VNET

From: Cy Schubert <cy_at_FreeBSD.org>
Date: Thu, 14 Jul 2022 21:31:56 UTC
The branch stable/12 has been updated by cy:

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

commit ed86cf0121f9a28e754f605c5be6c6576cde6c64
Author:     Cy Schubert <cy@FreeBSD.org>
AuthorDate: 2022-03-17 18:05:05 +0000
Commit:     Cy Schubert <cy@FreeBSD.org>
CommitDate: 2022-07-14 13:26:47 +0000

    ipfilter: Support only jails in VNET
    
    Jails without VNET have complete access to the ipfilter rules, NAT,
    pools and logs. This is insecure. Only allow jails to manipulate
    ipfilter rules, NAT tables and ippools if the jail has its own VNET.
    Otherwise a jail can affect the global system.
    
    This patch brings ipfilter in line with ipfw's support of VNET jails and
    non-support of non-VNET jails.
    
    (cherry picked from commit c47db49ba4aa7e74afe22591a62fbda95317932d)
---
 sbin/ipf/libipf/interror.c                    |  4 +++-
 sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c |  7 +++++++
 sys/netpfil/ipfilter/netinet/ip_nat.c         |  9 +++++++++
 sys/netpfil/ipfilter/netinet/mlfk_ipl.c       | 12 ++++++++++++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/sbin/ipf/libipf/interror.c b/sbin/ipf/libipf/interror.c
index ca97254cb382..994fb9d2b320 100644
--- a/sbin/ipf/libipf/interror.c
+++ b/sbin/ipf/libipf/interror.c
@@ -17,7 +17,7 @@ typedef	struct	{
 
 static ipf_error_entry_t *find_error(int);
 
-#define	IPF_NUM_ERRORS	475
+#define	IPF_NUM_ERRORS	477
 
 /*
  * NO REUSE OF NUMBERS!
@@ -355,6 +355,7 @@ log" },
 	{	60073,	"unknown lookup group for next address (ipv6)" },
 	{	60074,	"unknown next address type (ipv6)" },
 	{	60075,	"one object at a time must be copied" },
+	{	60076,	"NAT ioctl denied in jail without VNET" },
 /* -------------------------------------------------------------------------- */
 	{	70001,	"incorrect object size to get pool stats" },
 	{	70002,	"could not malloc memory for new pool node" },
@@ -516,6 +517,7 @@ log" },
 	{	130015,	"ipf_init_all failed" },
 	{	130016,	"finding pfil head failed" },
 	{	130017,	"ipfilter is already initialised and running" },
+	{	130018,	"ioctl denied in jail without VNET" },
 };
 
 
diff --git a/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c b/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
index 8202fd8b9a0c..fe2b5946fab9 100644
--- a/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
+++ b/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
@@ -44,6 +44,7 @@ static const char rcsid[] = "@(#)$Id$";
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_fib.h>
+#include <netinet/in_pcb.h>
 #include <netinet/in_var.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
@@ -291,6 +292,12 @@ ipfioctl(struct cdev *dev, ioctlcmd_t cmd, caddr_t data,
 		return (EPERM);
 	}
 
+	if (jailed_without_vnet(p->p_cred)) {
+		V_ipfmain.ipf_interror = 130018;
+		CURVNET_RESTORE();
+		return (EOPNOTSUPP);
+	}
+
 	unit = GET_MINOR(dev);
 	if ((IPL_LOGMAX < unit) || (unit < 0)) {
 		V_ipfmain.ipf_interror = 130002;
diff --git a/sys/netpfil/ipfilter/netinet/ip_nat.c b/sys/netpfil/ipfilter/netinet/ip_nat.c
index f448ce19b46a..835a1b3f848e 100644
--- a/sys/netpfil/ipfilter/netinet/ip_nat.c
+++ b/sys/netpfil/ipfilter/netinet/ip_nat.c
@@ -42,6 +42,9 @@ struct file;
 #include <sys/socket.h>
 #if defined(_KERNEL)
 # include <sys/systm.h>
+# if defined(__FreeBSD__)
+#  include <sys/jail.h>
+# endif
 # if !defined(__SVR4)
 #  include <sys/mbuf.h>
 # endif
@@ -999,6 +1002,12 @@ ipf_nat_ioctl(ipf_main_softc_t *softc, caddr_t data, ioctlcmd_t cmd,
 		IPFERROR(60001);
 		return (EPERM);
 	}
+# if defined(__FreeBSD__)
+	if (jailed_without_vnet(curthread->td_ucred)) {
+		IPFERROR(60076);
+		return (EOPNOTSUPP);
+	}
+# endif
 #endif
 
 	getlock = (mode & NAT_LOCKHELD) ? 0 : 1;
diff --git a/sys/netpfil/ipfilter/netinet/mlfk_ipl.c b/sys/netpfil/ipfilter/netinet/mlfk_ipl.c
index 36ddc29453be..0b37dab558aa 100644
--- a/sys/netpfil/ipfilter/netinet/mlfk_ipl.c
+++ b/sys/netpfil/ipfilter/netinet/mlfk_ipl.c
@@ -369,6 +369,9 @@ sysctl_ipf_int ( SYSCTL_HANDLER_ARGS )
 static int
 sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS )
 {
+	if (jailed_without_vnet(curthread->td_ucred))
+		return (0);
+
 	ipf_nat_softc_t *nat_softc;
 
 	nat_softc = V_ipfmain.ipf_nat_soft;
@@ -380,6 +383,9 @@ sysctl_ipf_int_nat ( SYSCTL_HANDLER_ARGS )
 static int
 sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS )
 {
+	if (jailed_without_vnet(curthread->td_ucred))
+		return (0);
+
 	ipf_state_softc_t *state_softc;
 
 	state_softc = V_ipfmain.ipf_state_soft;
@@ -391,6 +397,9 @@ sysctl_ipf_int_state ( SYSCTL_HANDLER_ARGS )
 static int
 sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS )
 {
+	if (jailed_without_vnet(curthread->td_ucred))
+		return (0);
+
 	ipf_auth_softc_t *auth_softc;
 
 	auth_softc = V_ipfmain.ipf_auth_soft;
@@ -402,6 +411,9 @@ sysctl_ipf_int_auth ( SYSCTL_HANDLER_ARGS )
 static int
 sysctl_ipf_int_frag ( SYSCTL_HANDLER_ARGS )
 {
+	if (jailed_without_vnet(curthread->td_ucred))
+		return (0);
+
 	ipf_frag_softc_t *frag_softc;
 
 	frag_softc = V_ipfmain.ipf_frag_soft;