summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2025-10-29 11:29:39 -0700
committerCy Schubert <cy@FreeBSD.org>2026-01-04 19:40:11 -0800
commite3b9f73e126e5b75142c1efbd825da3f0944b49f (patch)
tree615c0a8e59c5d81c7d0544466274d7dda745cbf2
parentceda9eb20f3efe0cfa4a444a972b2a47fdde044c (diff)
ipfilter: Restrict ipfilter within a jail
Add a sysctl/tunable (net.inet.ipf.jail_allowed) to control whether a jail can manage its own ipfilter rules, pools, and settings. A jail's control over its own ipfilter rules and settings may not be desireable. The default is jail access to ipfilter is denied. The host system can stil manage a jail's rules by attaching the rules, using the on keyword, limiting the rule to the jail's interface. Or the sysctl/tunable can be enabled to allow a jail control over its own ipfilter rules and settings. Implementation note: Rather than store the jail_allowed variable, referenced by sysctl(9), in a global area, storing the variable in the ipfilter softc is consistent with ipfilter's use of its softc. Discussed with: emaste, jrm MFC after: 1 week Differential revision: https://reviews.freebsd.org/D53623 (cherry picked from commit d9788eabffa4b67fc534685fc3d9b8e3334af196)
-rw-r--r--sbin/ipf/libipf/interror.c1
-rw-r--r--sys/netpfil/ipfilter/netinet/fil.c1
-rw-r--r--sys/netpfil/ipfilter/netinet/ip_fil.h1
-rw-r--r--sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c15
-rw-r--r--sys/netpfil/ipfilter/netinet/mlfk_ipl.c1
5 files changed, 19 insertions, 0 deletions
diff --git a/sbin/ipf/libipf/interror.c b/sbin/ipf/libipf/interror.c
index 5619b24200d7..89f1e7f9ec3c 100644
--- a/sbin/ipf/libipf/interror.c
+++ b/sbin/ipf/libipf/interror.c
@@ -536,6 +536,7 @@ log" },
{ 130016, "finding pfil head failed" },
{ 130017, "ipfilter is already initialised and running" },
{ 130018, "ioctl denied in jail without VNET" },
+ { 130019, "ioctl denied in jail" },
};
diff --git a/sys/netpfil/ipfilter/netinet/fil.c b/sys/netpfil/ipfilter/netinet/fil.c
index 545ef657217d..786efca38232 100644
--- a/sys/netpfil/ipfilter/netinet/fil.c
+++ b/sys/netpfil/ipfilter/netinet/fil.c
@@ -9102,6 +9102,7 @@ ipf_main_soft_create(void *arg)
softc->ipf_icmpminfragmtu = 68;
softc->ipf_max_namelen = 128;
softc->ipf_flags = IPF_LOGGING;
+ softc->ipf_jail_allowed = 0;
#ifdef LARGE_NAT
softc->ipf_large_nat = 1;
diff --git a/sys/netpfil/ipfilter/netinet/ip_fil.h b/sys/netpfil/ipfilter/netinet/ip_fil.h
index 821d63664859..4bbb19c889bd 100644
--- a/sys/netpfil/ipfilter/netinet/ip_fil.h
+++ b/sys/netpfil/ipfilter/netinet/ip_fil.h
@@ -1552,6 +1552,7 @@ typedef struct ipf_main_softc_s {
u_int ipf_icmpacktimeout;
u_int ipf_iptimeout;
u_int ipf_large_nat;
+ u_int ipf_jail_allowed;
u_long ipf_ticks;
u_long ipf_userifqs;
u_long ipf_rb_no_mem;
diff --git a/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c b/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
index 89e5be506be2..a5f634247a1a 100644
--- a/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
+++ b/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
@@ -92,6 +92,7 @@ VNET_DEFINE(ipf_main_softc_t, ipfmain) = {
.ipf_running = -2,
};
#define V_ipfmain VNET(ipfmain)
+#define V0_ipfmain VNET_VNET(vnet0,ipfmain)
#include <sys/conf.h>
#include <net/pfil.h>
@@ -278,6 +279,20 @@ ipfioctl(struct cdev *dev, ioctlcmd_t cmd, caddr_t data,
return (EPERM);
}
+ /*
+ * Remember, the host system (with its vnet0) controls
+ * whether a jail is allowed to use ipfilter or not.
+ * The default is ipfilter cannot be used by a jail
+ * unless the sysctl allows it.
+ */
+ if (V0_ipfmain.ipf_jail_allowed == 0) {
+ if (jailed(p->p_cred)) {
+ V_ipfmain.ipf_interror = 130019;
+ CURVNET_RESTORE();
+ return (EOPNOTSUPP);
+ }
+ }
+
if (jailed_without_vnet(p->p_cred)) {
V_ipfmain.ipf_interror = 130018;
CURVNET_RESTORE();
diff --git a/sys/netpfil/ipfilter/netinet/mlfk_ipl.c b/sys/netpfil/ipfilter/netinet/mlfk_ipl.c
index 0edaf666ecd8..b11dea53029b 100644
--- a/sys/netpfil/ipfilter/netinet/mlfk_ipl.c
+++ b/sys/netpfil/ipfilter/netinet/mlfk_ipl.c
@@ -136,6 +136,7 @@ SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_chksrc, CTLFLAG_RW, &VNET_NAME(ipfmain.ip
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_minttl, CTLFLAG_RW, &VNET_NAME(ipfmain.ipf_minttl), 0, "");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, large_nat, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &VNET_NAME(ipfmain.ipf_large_nat), 0, "large_nat");
SYSCTL_IPF(_net_inet_ipf, OID_AUTO, fr_max_namelen, CTLFLAG_RWTUN, &VNET_NAME(ipfmain.ipf_max_namelen), 0, "max_namelen");
+SYSCTL_IPF(_net_inet_ipf, OID_AUTO, jail_allowed, CTLFLAG_RWTUN, &VNET_NAME(ipfmain.ipf_jail_allowed), 0, "jail_allowed");
#define CDEV_MAJOR 79
#include <sys/poll.h>