Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 08 Dec 2025 16:15:25 +0000
From:      Cy Schubert <cy@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: d9788eabffa4 - main - ipfilter: Restrict ipfilter within a jail
Message-ID:  <6936f99d.3ab3f.185d9547@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help

The branch main has been updated by cy:

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

commit d9788eabffa4b67fc534685fc3d9b8e3334af196
Author:     Cy Schubert <cy@FreeBSD.org>
AuthorDate: 2025-10-29 18:29:39 +0000
Commit:     Cy Schubert <cy@FreeBSD.org>
CommitDate: 2025-12-08 16:15:18 +0000

    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
---
 sbin/ipf/libipf/interror.c                    |  1 +
 sys/netpfil/ipfilter/netinet/fil.c            |  1 +
 sys/netpfil/ipfilter/netinet/ip_fil.h         |  1 +
 sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c | 15 +++++++++++++++
 sys/netpfil/ipfilter/netinet/mlfk_ipl.c       |  1 +
 5 files changed, 19 insertions(+)

diff --git a/sbin/ipf/libipf/interror.c b/sbin/ipf/libipf/interror.c
index 6d5391f58ba2..2bbecaa154e6 100644
--- a/sbin/ipf/libipf/interror.c
+++ b/sbin/ipf/libipf/interror.c
@@ -531,6 +531,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 0c5e22517dc4..242affeff000 100644
--- a/sys/netpfil/ipfilter/netinet/fil.c
+++ b/sys/netpfil/ipfilter/netinet/fil.c
@@ -9096,6 +9096,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 7b070f0d6867..24d4f9695322 100644
--- a/sys/netpfil/ipfilter/netinet/ip_fil.h
+++ b/sys/netpfil/ipfilter/netinet/ip_fil.h
@@ -1550,6 +1550,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 6eb6cf2a7a47..43b590cc0204 100644
--- a/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
+++ b/sys/netpfil/ipfilter/netinet/ip_fil_freebsd.c
@@ -88,6 +88,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>
@@ -254,6 +255,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 d558b2d24b2c..139fe1f766d3 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>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6936f99d.3ab3f.185d9547>