mac_ipacl: new MAC policy module to limit jail/vnet IP configuration
The mac_ipacl policy module enables fine-grained control over IP address configuration within VNET jails from the base system. It allows the root user to define rules governing IP addresses for jails and their interfaces using the sysctl interface. Requested by: multiple Sponsored by: Google, Inc. (GSoC 2019) MFC after: 2 months Reviewed by: bz, dch (both earlier versions) Differential Revision: https://reviews.freebsd.org/D20967
This commit is contained in:
parent
a1b6757313
commit
215bab7924
@ -815,6 +815,8 @@
|
||||
mac
|
||||
bsdextended
|
||||
..
|
||||
ipacl
|
||||
..
|
||||
portacl
|
||||
..
|
||||
..
|
||||
|
@ -292,6 +292,7 @@ MAN= aac.4 \
|
||||
mac_bsdextended.4 \
|
||||
mac_ddb.4 \
|
||||
mac_ifoff.4 \
|
||||
mac_ipacl.4 \
|
||||
mac_lomac.4 \
|
||||
mac_mls.4 \
|
||||
mac_none.4 \
|
||||
|
@ -30,7 +30,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 10, 2023
|
||||
.Dd July 25, 2023
|
||||
.Dt MAC 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -57,6 +57,7 @@ Currently, the following MAC policy modules are shipped with
|
||||
.It Xr mac_bsdextended 4 Ta "File system firewall" Ta no Ta any time
|
||||
.It Xr mac_ddb 4 Ta "ddb(4) interface restrictions" Ta no Ta any time
|
||||
.It Xr mac_ifoff 4 Ta "Interface silencing" Ta no Ta any time
|
||||
.It Xr mac_ipacl 4 Ta "IP Address access control" Ta no Ta any time
|
||||
.It Xr mac_lomac 4 Ta "Low-Watermark MAC policy" Ta yes Ta boot only
|
||||
.It Xr mac_mls 4 Ta "Confidentiality policy" Ta yes Ta boot only
|
||||
.It Xr mac_ntpd 4 Ta "Non-root NTP Daemon policy" Ta no Ta any time
|
||||
@ -205,6 +206,7 @@ man page.
|
||||
.Xr mac_bsdextended 4 ,
|
||||
.Xr mac_ddb 4 ,
|
||||
.Xr mac_ifoff 4 ,
|
||||
.Xr mac_ipacl 4 ,
|
||||
.Xr mac_lomac 4 ,
|
||||
.Xr mac_mls 4 ,
|
||||
.Xr mac_none 4 ,
|
||||
|
166
share/man/man4/mac_ipacl.4
Normal file
166
share/man/man4/mac_ipacl.4
Normal file
@ -0,0 +1,166 @@
|
||||
.\" Copyright (c) 2019, 2023 Shivank Garg <shivank@FreeBSD.org>
|
||||
.\"
|
||||
.\" This code was developed as a Google Summer of Code 2019 project
|
||||
.\" under the guidance of Bjoern A. Zeeb.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 25, 2023
|
||||
.Dt MAC_IPACL 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mac_ipacl
|
||||
.Nd "IP Address access control policy"
|
||||
.Sh SYNOPSIS
|
||||
Add the following lines in your kernel configuration file to compile the
|
||||
IP address access control policy into your kernel:
|
||||
.Bd -ragged -offset indent
|
||||
.Cd "options MAC"
|
||||
.Cd "options MAC_IPACL"
|
||||
.Ed
|
||||
.Pp
|
||||
To load the mac_ipacl policy module at boot time, add the
|
||||
following line in your kernel configuration file:
|
||||
.Bd -ragged -offset indent
|
||||
.Cd "options MAC"
|
||||
.Ed
|
||||
.Pp
|
||||
and in
|
||||
.Xr loader.conf 5 add:
|
||||
.Pp
|
||||
.Dl "mac_ipacl_load=""YES"""
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
policy allows the root of the host to use the
|
||||
.Xr sysctl 8
|
||||
interface to limit the
|
||||
.Xr VNET 9
|
||||
jail's ability to set IPv4 and IPv6 addresses.
|
||||
So, the host can
|
||||
define rules for jails and their interfaces about IP addresses
|
||||
with
|
||||
.Xr sysctl 8
|
||||
MIBs.
|
||||
.Pp
|
||||
Its default behavior is to deny all IP addresses for the jail if
|
||||
.Nm
|
||||
policy is enforced and allow/deny IP (or subnets) according to the
|
||||
.Va security.mac.ipacl.rules
|
||||
string specified with
|
||||
.Xr sysctl 8
|
||||
.Ss Runtime Configuration
|
||||
The following
|
||||
.Xr sysctl 8
|
||||
MIBs are used to control enforcement and behavior of this MAC Policy.
|
||||
.Bl -tag -width indent
|
||||
.It Va security.mac.ipacl.ipv4
|
||||
Enforce
|
||||
.Nm
|
||||
for IPv4 addresses.
|
||||
(Default: 1).
|
||||
.It Va security.mac.ipacl.ipv6
|
||||
Enforce
|
||||
.Nm
|
||||
for IPv6 addresses.
|
||||
(Default: 1).
|
||||
.It Va security.mac.ipacl.rules
|
||||
The IP address access control list is specified in the following format:
|
||||
.Pp
|
||||
.Sm off
|
||||
.D1 jid , allow , interface , addr_family , IP_addr / prefix Op @ jid , ...
|
||||
.Sm on
|
||||
.Bl -tag -width "interface"
|
||||
.It jid
|
||||
Describe the jail id of the jail for which the rule is written.
|
||||
.It allow
|
||||
1 for allow and 0 for deny.
|
||||
Decides action performed for the rule.
|
||||
.It interface
|
||||
Name of the interface the rule is enforced for.
|
||||
If the interface is left empty then it is a wildcard to enforce the
|
||||
rule for all interfaces.
|
||||
.It addr_family
|
||||
Address family of the IP_addr.
|
||||
The input to be given as AF_INET or AF_INET6
|
||||
string only.
|
||||
.It IP_addr
|
||||
IP address (or subnet) to be allowed/denied.
|
||||
Action depends on the prefix length.
|
||||
.It prefix
|
||||
Prefix length of the subnet to be enforced by the policy.
|
||||
-1 implies the policy is enforced for the individual IP address.
|
||||
For a non-negative value, a range of IP addresses (present in subnet)
|
||||
which is calculated as subnet = IP_addr & mask.
|
||||
.El
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
Behavior of the
|
||||
.Nm
|
||||
policy module for different inputs of sysctl variable:
|
||||
.Bl -tag -width "1."
|
||||
.It 1.
|
||||
Assign ipv4=1, ipv6=0 and rules="1,1,,AF_INET,169.254.123.123/-1"
|
||||
.Pp
|
||||
It allow only 169.254.123.123 IPv4 address for all interfaces (wildcard) of jail 1.
|
||||
It allows all IPv6 addresses since the policy is not enforced for IPv6.
|
||||
.It 2.
|
||||
Assign ipv4=1, ipv6=1 and rules="1,1,epair0b,AF_INET6,fe80::/32@1,0,epair0b,AF_INET6,fe80::abcd/-1"
|
||||
.Pp
|
||||
It denies all IPv4 addresses as the policy is enforced but no rules are specified
|
||||
about it.
|
||||
It allows all IPv6 addresses in subnet fe80::/32 except
|
||||
fe80::abcd for interface epair0b only.
|
||||
.It 3.
|
||||
Assign ipv4=1, ipv6=1, rules="2,1,,AF_INET6,fc00::/7@2,0,,AF_INET6,fc00::1111:2200/120@2,1,,AF_INET6,fc00::1111:2299/-1@1,1,,AF_INET,198.51.100.0/24"
|
||||
.Pp
|
||||
It allows IPv4 in subnet 198.51.100.0/24 for jail 2 and
|
||||
all interfaces.
|
||||
It allows IPv6 addresses in subnet fc00::/7 but
|
||||
denies subnet fc00::1111:2200/120, and allows individual IP
|
||||
fc00::1111:2299 from the denied subnet for all interfaces in jail 2.
|
||||
.El
|
||||
Please refer to mac/ipacl tests-framework for wide variety of examples on using
|
||||
the ipacl module.
|
||||
.Sh LIMITATIONS/PRECAUTIONS
|
||||
In the case where multiple rules are applicable to an IP address or
|
||||
a set of IP addresses, the rule that is defined later in the list
|
||||
determines the outcome, disregarding any previous rule for that IP
|
||||
address.
|
||||
.Sh FUTURE WORKS
|
||||
Rules are given with sysctl interface which gets very complex to give them
|
||||
all in command line.
|
||||
It has to be simplified with a better way to input those rules.
|
||||
.Sh SEE ALSO
|
||||
.Xr mac 4 ,
|
||||
.Xr mac 9
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Nm
|
||||
policy module was developed as a Google Summer of Code Project in 2019
|
||||
by
|
||||
.An -nosplit
|
||||
.An "Shivank Garg" Aq Mt shivank@FreeBSD.org
|
||||
under the guidance of
|
||||
.An "Bjoern A. Zeeb" Aq Mt bz@FreeBSD.org .
|
@ -1232,6 +1232,7 @@ options MAC_BIBA
|
||||
options MAC_BSDEXTENDED
|
||||
options MAC_DDB
|
||||
options MAC_IFOFF
|
||||
options MAC_IPACL
|
||||
options MAC_LOMAC
|
||||
options MAC_MLS
|
||||
options MAC_NONE
|
||||
|
@ -5147,6 +5147,7 @@ security/mac_bsdextended/mac_bsdextended.c optional mac_bsdextended
|
||||
security/mac_bsdextended/ugidfw_system.c optional mac_bsdextended
|
||||
security/mac_bsdextended/ugidfw_vnode.c optional mac_bsdextended
|
||||
security/mac_ifoff/mac_ifoff.c optional mac_ifoff
|
||||
security/mac_ipacl/mac_ipacl.c optional mac_ipacl
|
||||
security/mac_lomac/mac_lomac.c optional mac_lomac
|
||||
security/mac_mls/mac_mls.c optional mac_mls
|
||||
security/mac_none/mac_none.c optional mac_none
|
||||
|
@ -158,6 +158,7 @@ MAC_BIBA opt_dontuse.h
|
||||
MAC_BSDEXTENDED opt_dontuse.h
|
||||
MAC_DDB opt_dontuse.h
|
||||
MAC_IFOFF opt_dontuse.h
|
||||
MAC_IPACL opt_dontuse.h
|
||||
MAC_LOMAC opt_dontuse.h
|
||||
MAC_MLS opt_dontuse.h
|
||||
MAC_NONE opt_dontuse.h
|
||||
|
@ -225,6 +225,7 @@ SUBDIR= \
|
||||
${_mac_bsdextended} \
|
||||
${_mac_ddb} \
|
||||
${_mac_ifoff} \
|
||||
${_mac_ipacl} \
|
||||
${_mac_lomac} \
|
||||
${_mac_mls} \
|
||||
${_mac_none} \
|
||||
@ -581,6 +582,7 @@ _mac_bsdextended= mac_bsdextended
|
||||
_mac_ddb= mac_ddb
|
||||
.endif
|
||||
_mac_ifoff= mac_ifoff
|
||||
_mac_ipacl= mac_ipacl
|
||||
_mac_lomac= mac_lomac
|
||||
_mac_mls= mac_mls
|
||||
_mac_none= mac_none
|
||||
|
9
sys/modules/mac_ipacl/Makefile
Normal file
9
sys/modules/mac_ipacl/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/security/mac_ipacl
|
||||
|
||||
KMOD= mac_ipacl
|
||||
SRCS= mac_ipacl.c
|
||||
SRCS+= opt_inet.h opt_inet6.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -77,6 +77,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
|
||||
#ifdef MAC
|
||||
#include <security/mac/mac_framework.h>
|
||||
#endif
|
||||
|
||||
static int in_aifaddr_ioctl(u_long, caddr_t, struct ifnet *, struct ucred *);
|
||||
static int in_difaddr_ioctl(u_long, caddr_t, struct ifnet *, struct ucred *);
|
||||
static int in_gifaddr_ioctl(u_long, caddr_t, struct ifnet *, struct ucred *);
|
||||
@ -487,6 +491,13 @@ in_aifaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct ucred *cred
|
||||
if (vhid != 0 && carp_attach_p == NULL)
|
||||
return (EPROTONOSUPPORT);
|
||||
|
||||
#ifdef MAC
|
||||
/* Check if a MAC policy disallows setting the IPv4 address. */
|
||||
error = mac_inet_check_add_addr(cred, &addr->sin_addr, ifp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* See whether address already exist.
|
||||
*/
|
||||
|
@ -115,6 +115,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet6/in6_fib.h>
|
||||
#include <netinet6/in6_pcb.h>
|
||||
|
||||
#ifdef MAC
|
||||
#include <security/mac/mac_framework.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* struct in6_ifreq and struct ifreq must be type punnable for common members
|
||||
* of ifr_ifru to allow accessors to be shared.
|
||||
@ -567,6 +571,12 @@ in6_control_ioctl(u_long cmd, void *data,
|
||||
break;
|
||||
|
||||
case SIOCAIFADDR_IN6:
|
||||
#ifdef MAC
|
||||
/* Check if a MAC policy disallows setting the IPv6 address. */
|
||||
error = mac_inet6_check_add_addr(cred, &sa6->sin6_addr, ifp);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
#endif
|
||||
error = in6_addifaddr(ifp, ifra, ia);
|
||||
ia = NULL;
|
||||
break;
|
||||
|
@ -90,6 +90,9 @@ struct vattr;
|
||||
struct vnode;
|
||||
struct vop_setlabel_args;
|
||||
|
||||
struct in_addr;
|
||||
struct in6_addr;
|
||||
|
||||
#include <sys/acl.h> /* XXX acl_type_t */
|
||||
#include <sys/types.h> /* accmode_t */
|
||||
|
||||
@ -191,6 +194,12 @@ int mac_ifnet_ioctl_get(struct ucred *cred, struct ifreq *ifr,
|
||||
int mac_ifnet_ioctl_set(struct ucred *cred, struct ifreq *ifr,
|
||||
struct ifnet *ifp);
|
||||
|
||||
/* Check if the IP address is allowed for the interface. */
|
||||
int mac_inet_check_add_addr(struct ucred *cred,
|
||||
const struct in_addr *ia, struct ifnet *ifp);
|
||||
int mac_inet6_check_add_addr(struct ucred *cred,
|
||||
const struct in6_addr *ia6, struct ifnet *ifp);
|
||||
|
||||
int mac_inpcb_check_deliver(struct inpcb *inp, struct mbuf *m);
|
||||
int mac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp);
|
||||
void mac_inpcb_create(struct socket *so, struct inpcb *inp);
|
||||
|
@ -108,6 +108,17 @@ mac_inpcb_init(struct inpcb *inp, int flag)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Check with rules in module if the IPv4 address is allowed. */
|
||||
int
|
||||
mac_inet_check_add_addr(struct ucred *cred, const struct in_addr *ia,
|
||||
struct ifnet *ifp)
|
||||
{
|
||||
int error;
|
||||
|
||||
MAC_POLICY_CHECK(ip4_check_jail, cred, ia, ifp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static struct label *
|
||||
mac_ipq_label_alloc(int flag)
|
||||
{
|
||||
|
@ -173,6 +173,17 @@ mac_ip6q_update(struct mbuf *m, struct ip6q *q6)
|
||||
q6->ip6q_label);
|
||||
}
|
||||
|
||||
/* Check with rules in module if the IPv6 address is allowed. */
|
||||
int
|
||||
mac_inet6_check_add_addr(struct ucred *cred, const struct in6_addr *ia6,
|
||||
struct ifnet *ifp)
|
||||
{
|
||||
int error;
|
||||
|
||||
MAC_POLICY_CHECK(ip6_check_jail, cred, ia6, ifp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
mac_netinet6_nd6_send(struct ifnet *ifp, struct mbuf *m)
|
||||
{
|
||||
|
@ -104,6 +104,9 @@ struct ucred;
|
||||
struct vattr;
|
||||
struct vnode;
|
||||
|
||||
struct in_addr;
|
||||
struct in6_addr;
|
||||
|
||||
/*
|
||||
* Policy module operations.
|
||||
*/
|
||||
@ -248,6 +251,12 @@ typedef void (*mpo_ip6q_reassemble)(struct ip6q *q6, struct label *q6label,
|
||||
typedef void (*mpo_ip6q_update_t)(struct mbuf *m, struct label *mlabel,
|
||||
struct ip6q *q6, struct label *q6label);
|
||||
|
||||
/* Policy ops checking IPv4 and IPv6 address for ipacl. */
|
||||
typedef int (*mpo_ip4_check_jail_t)(struct ucred *cred,
|
||||
const struct in_addr *ia, struct ifnet *ifp);
|
||||
typedef int (*mpo_ip6_check_jail_t)(struct ucred *cred,
|
||||
const struct in6_addr *ia6, struct ifnet *ifp);
|
||||
|
||||
typedef void (*mpo_ipq_create_t)(struct mbuf *m, struct label *mlabel,
|
||||
struct ipq *q, struct label *qlabel);
|
||||
typedef void (*mpo_ipq_destroy_label_t)(struct label *label);
|
||||
@ -762,6 +771,9 @@ struct mac_policy_ops {
|
||||
mpo_inpcb_init_label_t mpo_inpcb_init_label;
|
||||
mpo_inpcb_sosetlabel_t mpo_inpcb_sosetlabel;
|
||||
|
||||
mpo_ip4_check_jail_t mpo_ip4_check_jail;
|
||||
mpo_ip6_check_jail_t mpo_ip6_check_jail;
|
||||
|
||||
mpo_ip6q_create_t mpo_ip6q_create;
|
||||
mpo_ip6q_destroy_label_t mpo_ip6q_destroy_label;
|
||||
mpo_ip6q_init_label_t mpo_ip6q_init_label;
|
||||
|
453
sys/security/mac_ipacl/mac_ipacl.c
Normal file
453
sys/security/mac_ipacl/mac_ipacl.c
Normal file
@ -0,0 +1,453 @@
|
||||
/*-
|
||||
* Copyright (c) 2003-2004 Networks Associates Technology, Inc.
|
||||
* Copyright (c) 2006 SPARTA, Inc.
|
||||
* Copyright (c) 2019, 2023 Shivank Garg <shivank@FreeBSD.org>
|
||||
*
|
||||
* This software was developed for the FreeBSD Project by Network
|
||||
* Associates Laboratories, the Security Research Division of Network
|
||||
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
|
||||
* as part of the DARPA CHATS research program.
|
||||
*
|
||||
* This software was enhanced by SPARTA ISSO under SPAWAR contract
|
||||
* N66001-04-C-6019 ("SEFOS").
|
||||
*
|
||||
* This code was developed as a Google Summer of Code 2019 project
|
||||
* under the guidance of Bjoern A. Zeeb.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* The IP address access control policy module - mac_ipacl allows the root of
|
||||
* the host to limit the VNET jail's privileges of setting IPv4 and IPv6
|
||||
* addresses via sysctl(8) interface. So, the host can define rules for jails
|
||||
* and their interfaces about IP addresses.
|
||||
* sysctl(8) is to be used to modify the rules string in following format-
|
||||
* "jail_id,allow,interface,address_family,IP_addr/prefix_length[@jail_id,...]"
|
||||
*/
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/jail.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet6/scope6_var.h>
|
||||
|
||||
#include <security/mac/mac_policy.h>
|
||||
|
||||
SYSCTL_DECL(_security_mac);
|
||||
|
||||
static SYSCTL_NODE(_security_mac, OID_AUTO, ipacl, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
|
||||
"TrustedBSD mac_ipacl policy controls");
|
||||
|
||||
#ifdef INET
|
||||
static int ipacl_ipv4 = 1;
|
||||
SYSCTL_INT(_security_mac_ipacl, OID_AUTO, ipv4, CTLFLAG_RWTUN,
|
||||
&ipacl_ipv4, 0, "Enforce mac_ipacl for IPv4 addresses");
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
static int ipacl_ipv6 = 1;
|
||||
SYSCTL_INT(_security_mac_ipacl, OID_AUTO, ipv6, CTLFLAG_RWTUN,
|
||||
&ipacl_ipv6, 0, "Enforce mac_ipacl for IPv6 addresses");
|
||||
#endif
|
||||
|
||||
static MALLOC_DEFINE(M_IPACL, "ipacl_rule", "Rules for mac_ipacl");
|
||||
|
||||
#define MAC_RULE_STRING_LEN 1024
|
||||
|
||||
struct ipacl_addr {
|
||||
union {
|
||||
#ifdef INET
|
||||
struct in_addr ipv4;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct in6_addr ipv6;
|
||||
#endif
|
||||
u_int8_t addr8[16];
|
||||
u_int16_t addr16[8];
|
||||
u_int32_t addr32[4];
|
||||
} ipa; /* 128 bit address*/
|
||||
#ifdef INET
|
||||
#define v4 ipa.ipv4
|
||||
#endif
|
||||
#ifdef INET6
|
||||
#define v6 ipa.ipv6
|
||||
#endif
|
||||
#define addr8 ipa.addr8
|
||||
#define addr16 ipa.addr16
|
||||
#define addr32 ipa.addr32
|
||||
};
|
||||
|
||||
struct ip_rule {
|
||||
int jid;
|
||||
bool allow;
|
||||
bool subnet_apply; /* Apply rule on whole subnet. */
|
||||
char if_name[IFNAMSIZ];
|
||||
int af; /* Address family. */
|
||||
struct ipacl_addr addr;
|
||||
struct ipacl_addr mask;
|
||||
TAILQ_ENTRY(ip_rule) r_entries;
|
||||
};
|
||||
|
||||
static struct mtx rule_mtx;
|
||||
static TAILQ_HEAD(rulehead, ip_rule) rule_head;
|
||||
static char rule_string[MAC_RULE_STRING_LEN];
|
||||
|
||||
static void
|
||||
destroy_rules(struct rulehead *head)
|
||||
{
|
||||
struct ip_rule *rule;
|
||||
|
||||
while ((rule = TAILQ_FIRST(head)) != NULL) {
|
||||
TAILQ_REMOVE(head, rule, r_entries);
|
||||
free(rule, M_IPACL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipacl_init(struct mac_policy_conf *conf)
|
||||
{
|
||||
mtx_init(&rule_mtx, "rule_mtx", NULL, MTX_DEF);
|
||||
TAILQ_INIT(&rule_head);
|
||||
}
|
||||
|
||||
static void
|
||||
ipacl_destroy(struct mac_policy_conf *conf)
|
||||
{
|
||||
mtx_destroy(&rule_mtx);
|
||||
destroy_rules(&rule_head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: parsing routines are destructive on the passed string.
|
||||
*/
|
||||
static int
|
||||
parse_rule_element(char *element, struct ip_rule *rule)
|
||||
{
|
||||
char *tok, *p;
|
||||
int prefix;
|
||||
#ifdef INET6
|
||||
int i;
|
||||
#endif
|
||||
|
||||
/* Should we support a jail wildcard? */
|
||||
tok = strsep(&element, ",");
|
||||
if (tok == NULL)
|
||||
return (EINVAL);
|
||||
rule->jid = strtol(tok, &p, 10);
|
||||
if (*p != '\0')
|
||||
return (EINVAL);
|
||||
tok = strsep(&element, ",");
|
||||
if (tok == NULL)
|
||||
return (EINVAL);
|
||||
rule->allow = strtol(tok, &p, 10);
|
||||
if (*p != '\0')
|
||||
return (EINVAL);
|
||||
tok = strsep(&element, ",");
|
||||
if (strlen(tok) + 1 > IFNAMSIZ)
|
||||
return (EINVAL);
|
||||
/* Empty interface name is wildcard to all interfaces. */
|
||||
strlcpy(rule->if_name, tok, strlen(tok) + 1);
|
||||
tok = strsep(&element, ",");
|
||||
if (tok == NULL)
|
||||
return (EINVAL);
|
||||
rule->af = (strcmp(tok, "AF_INET") == 0) ? AF_INET :
|
||||
(strcmp(tok, "AF_INET6") == 0) ? AF_INET6 : -1;
|
||||
if (rule->af == -1)
|
||||
return (EINVAL);
|
||||
tok = strsep(&element, "/");
|
||||
if (tok == NULL)
|
||||
return (EINVAL);
|
||||
if (inet_pton(rule->af, tok, rule->addr.addr32) != 1)
|
||||
return (EINVAL);
|
||||
tok = element;
|
||||
if (tok == NULL)
|
||||
return (EINVAL);
|
||||
prefix = strtol(tok, &p, 10);
|
||||
if (*p != '\0')
|
||||
return (EINVAL);
|
||||
/* Value -1 for prefix make policy applicable to individual IP only. */
|
||||
if (prefix == -1)
|
||||
rule->subnet_apply = false;
|
||||
else {
|
||||
rule->subnet_apply = true;
|
||||
switch (rule->af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (prefix < 0 || prefix > 32)
|
||||
return (EINVAL);
|
||||
|
||||
if (prefix == 0)
|
||||
rule->mask.addr32[0] = htonl(0);
|
||||
else
|
||||
rule->mask.addr32[0] =
|
||||
htonl(~((1 << (32 - prefix)) - 1));
|
||||
rule->addr.addr32[0] &= rule->mask.addr32[0];
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (prefix < 0 || prefix > 128)
|
||||
return (EINVAL);
|
||||
|
||||
for (i = 0; prefix > 0; prefix -= 8, i++)
|
||||
rule->mask.addr8[i] = prefix >= 8 ? 0xFF :
|
||||
(u_int8_t)((0xFFU << (8 - prefix)) & 0xFFU);
|
||||
for (i = 0; i < 16; i++)
|
||||
rule->addr.addr8[i] &= rule->mask.addr8[i];
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Format of Rule- jid,allow,interface_name,addr_family,ip_addr/subnet_mask
|
||||
* Example: sysctl security.mac.ipacl.rules=1,1,epair0b,AF_INET,192.0.2.2/24
|
||||
*/
|
||||
static int
|
||||
parse_rules(char *string, struct rulehead *head)
|
||||
{
|
||||
struct ip_rule *new;
|
||||
char *element;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
while ((element = strsep(&string, "@")) != NULL) {
|
||||
if (strlen(element) == 0)
|
||||
continue;
|
||||
|
||||
new = malloc(sizeof(*new), M_IPACL, M_ZERO | M_WAITOK);
|
||||
error = parse_rule_element(element, new);
|
||||
if (error != 0) {
|
||||
free(new, M_IPACL);
|
||||
goto out;
|
||||
}
|
||||
TAILQ_INSERT_TAIL(head, new, r_entries);
|
||||
}
|
||||
out:
|
||||
if (error != 0)
|
||||
destroy_rules(head);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_rules(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
char *string, *copy_string, *new_string;
|
||||
struct rulehead head, save_head;
|
||||
int error;
|
||||
|
||||
new_string = NULL;
|
||||
if (req->newptr != NULL) {
|
||||
new_string = malloc(MAC_RULE_STRING_LEN, M_IPACL,
|
||||
M_WAITOK | M_ZERO);
|
||||
mtx_lock(&rule_mtx);
|
||||
strcpy(new_string, rule_string);
|
||||
mtx_unlock(&rule_mtx);
|
||||
string = new_string;
|
||||
} else
|
||||
string = rule_string;
|
||||
|
||||
error = sysctl_handle_string(oidp, string, MAC_RULE_STRING_LEN, req);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if (req->newptr != NULL) {
|
||||
copy_string = strdup(string, M_IPACL);
|
||||
TAILQ_INIT(&head);
|
||||
error = parse_rules(copy_string, &head);
|
||||
free(copy_string, M_IPACL);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
TAILQ_INIT(&save_head);
|
||||
mtx_lock(&rule_mtx);
|
||||
TAILQ_CONCAT(&save_head, &rule_head, r_entries);
|
||||
TAILQ_CONCAT(&rule_head, &head, r_entries);
|
||||
strcpy(rule_string, string);
|
||||
mtx_unlock(&rule_mtx);
|
||||
destroy_rules(&save_head);
|
||||
}
|
||||
out:
|
||||
if (new_string != NULL)
|
||||
free(new_string, M_IPACL);
|
||||
return (error);
|
||||
}
|
||||
SYSCTL_PROC(_security_mac_ipacl, OID_AUTO, rules,
|
||||
CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
|
||||
0, sysctl_rules, "A", "IP ACL Rules");
|
||||
|
||||
static int
|
||||
rules_check(struct ucred *cred,
|
||||
struct ipacl_addr *ip_addr, struct ifnet *ifp)
|
||||
{
|
||||
struct ip_rule *rule;
|
||||
int error;
|
||||
#ifdef INET6
|
||||
int i;
|
||||
bool same_subnet;
|
||||
#endif
|
||||
|
||||
error = EPERM;
|
||||
|
||||
mtx_lock(&rule_mtx);
|
||||
|
||||
/*
|
||||
* In the case where multiple rules are applicable to an IP address or
|
||||
* a set of IP addresses, the rule that is defined later in the list
|
||||
* determines the outcome, disregarding any previous rule for that IP
|
||||
* address.
|
||||
* Walk the policy rules list in reverse order until rule applicable
|
||||
* to the requested IP address is found.
|
||||
*/
|
||||
TAILQ_FOREACH_REVERSE(rule, &rule_head, rulehead, r_entries) {
|
||||
/* Skip if current rule applies to different jail. */
|
||||
if (cred->cr_prison->pr_id != rule->jid)
|
||||
continue;
|
||||
|
||||
if (strcmp(rule->if_name, "\0") &&
|
||||
strcmp(rule->if_name, ifp->if_xname))
|
||||
continue;
|
||||
|
||||
switch (rule->af) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
if (rule->subnet_apply) {
|
||||
if (rule->addr.v4.s_addr !=
|
||||
(ip_addr->v4.s_addr & rule->mask.v4.s_addr))
|
||||
continue;
|
||||
} else
|
||||
if (ip_addr->v4.s_addr != rule->addr.v4.s_addr)
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (rule->subnet_apply) {
|
||||
same_subnet = true;
|
||||
for (i = 0; i < 16; i++)
|
||||
if (rule->addr.v6.s6_addr[i] !=
|
||||
(ip_addr->v6.s6_addr[i] &
|
||||
rule->mask.v6.s6_addr[i])) {
|
||||
same_subnet = false;
|
||||
break;
|
||||
}
|
||||
if (!same_subnet)
|
||||
continue;
|
||||
} else
|
||||
if (bcmp(&rule->addr, ip_addr,
|
||||
sizeof(*ip_addr)))
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rule->allow)
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
mtx_unlock(&rule_mtx);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Feature request: Can we make this sysctl policy apply to jails by default,
|
||||
* but also allow it to be changed to apply to the base system?
|
||||
*/
|
||||
#ifdef INET
|
||||
static int
|
||||
ipacl_ip4_check_jail(struct ucred *cred,
|
||||
const struct in_addr *ia, struct ifnet *ifp)
|
||||
{
|
||||
struct ipacl_addr ip4_addr;
|
||||
|
||||
ip4_addr.v4 = *ia;
|
||||
|
||||
if (!jailed(cred))
|
||||
return (0);
|
||||
|
||||
/* Checks with the policy only when it is enforced for ipv4. */
|
||||
if (ipacl_ipv4)
|
||||
return rules_check(cred, &ip4_addr, ifp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef INET6
|
||||
static int
|
||||
ipacl_ip6_check_jail(struct ucred *cred,
|
||||
const struct in6_addr *ia6, struct ifnet *ifp)
|
||||
{
|
||||
struct ipacl_addr ip6_addr;
|
||||
|
||||
ip6_addr.v6 = *ia6; /* Make copy to not alter the original. */
|
||||
in6_clearscope(&ip6_addr.v6); /* Clear the scope id. */
|
||||
|
||||
if (!jailed(cred))
|
||||
return (0);
|
||||
|
||||
/* Checks with the policy when it is enforced for ipv6. */
|
||||
if (ipacl_ipv6)
|
||||
return rules_check(cred, &ip6_addr, ifp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct mac_policy_ops ipacl_ops =
|
||||
{
|
||||
.mpo_init = ipacl_init,
|
||||
.mpo_destroy = ipacl_destroy,
|
||||
#ifdef INET
|
||||
.mpo_ip4_check_jail = ipacl_ip4_check_jail,
|
||||
#endif
|
||||
#ifdef INET6
|
||||
.mpo_ip6_check_jail = ipacl_ip6_check_jail,
|
||||
#endif
|
||||
};
|
||||
|
||||
MAC_POLICY_SET(&ipacl_ops, mac_ipacl, "TrustedBSD MAC/ipacl",
|
||||
MPC_LOADTIME_FLAG_UNLOADOK, NULL);
|
@ -3,6 +3,7 @@
|
||||
TESTSDIR= ${TESTSBASE}/sys/mac
|
||||
|
||||
TESTS_SUBDIRS+= bsdextended
|
||||
TESTS_SUBDIRS+= ipacl
|
||||
TESTS_SUBDIRS+= portacl
|
||||
|
||||
.include <bsd.test.mk>
|
||||
|
11
tests/sys/mac/ipacl/Makefile
Normal file
11
tests/sys/mac/ipacl/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PACKAGE= tests
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/sys/mac/ipacl
|
||||
|
||||
ATF_TESTS_SH+= ipacl_test
|
||||
|
||||
${PACKAGE}FILES+= utils.subr
|
||||
|
||||
.include <bsd.test.mk>
|
282
tests/sys/mac/ipacl/ipacl_test.sh
Normal file
282
tests/sys/mac/ipacl/ipacl_test.sh
Normal file
@ -0,0 +1,282 @@
|
||||
#-
|
||||
# Copyright (c) 2019, 2023 Shivank Garg <shivank@FreeBSD.org>
|
||||
#
|
||||
# This code was developed as a Google Summer of Code 2019 project
|
||||
# under the guidance of Bjoern A. Zeeb.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
. $(atf_get_srcdir)/utils.subr
|
||||
|
||||
atf_test_case "ipacl_v4" "cleanup"
|
||||
|
||||
ipacl_v4_head()
|
||||
{
|
||||
atf_set descr 'basic test for ipacl on IPv4 addresses'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
ipacl_v4_body()
|
||||
{
|
||||
ipacl_test_init
|
||||
|
||||
epairA=$(vnet_mkepair)
|
||||
epairB=$(vnet_mkepair)
|
||||
epairC=$(vnet_mkepair)
|
||||
|
||||
vnet_mkjail A ${epairA}b
|
||||
vnet_mkjail B ${epairB}b ${epairC}b
|
||||
|
||||
jidA=$(jls -j A -s jid | grep -o -E '[0-9]+')
|
||||
jidB=$(jls -j B -s jid | grep -o -E '[0-9]+')
|
||||
|
||||
# The ipacl policy module is not enforced for IPv4.
|
||||
sysctl security.mac.ipacl.ipv4=0
|
||||
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 192.0.2.2/24 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 203.0.113.254/24 up
|
||||
|
||||
# The ipacl policy module is enforced for IPv4 and prevent all
|
||||
# jails from setting their IPv4 address.
|
||||
sysctl security.mac.ipacl.ipv4=1
|
||||
sysctl security.mac.ipacl.rules=
|
||||
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 192.0.2.2/24 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 203.0.113.254/24 up
|
||||
|
||||
rule="${jidA},1,${epairA}b,AF_INET,192.0.2.42/-1@"
|
||||
rule="${rule}${jidB},1,${epairB}b,AF_INET,198.51.100.12/-1@"
|
||||
rule="${rule}${jidB},1,,AF_INET,203.0.113.1/24@"
|
||||
rule="${rule}${jidB},0,,AF_INET,203.0.113.9/-1"
|
||||
sysctl security.mac.ipacl.rules="${rule}"
|
||||
|
||||
# Verify if it allows jail to set only certain IPv4 address.
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 192.0.2.42/24 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 192.0.2.43/24 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairB}b 198.51.100.12/24 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b 198.51.100.12/24 up
|
||||
|
||||
# Verify if the module allow jail to set any address in subnet.
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairB}b 203.0.113.19/24 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairB}b 203.0.113.241/24 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairB}b 198.18.0.1/24 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairB}b 203.0.113.9/24 up
|
||||
|
||||
# Check wildcard for interfaces.
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b 203.0.113.20/24 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b 203.0.113.242/24 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b 198.18.0.1/24 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b 203.0.113.9/24 up
|
||||
|
||||
rule="${jidA},1,,AF_INET,198.18.0.0/15@"
|
||||
rule="${rule}${jidA},0,,AF_INET,198.18.23.0/24@"
|
||||
rule="${rule}${jidA},1,,AF_INET,198.18.23.1/-1@"
|
||||
rule="${rule}${jidA},1,,AF_INET,198.51.100.0/24@"
|
||||
rule="${rule}${jidA},0,,AF_INET,198.51.100.100/-1"
|
||||
sysctl security.mac.ipacl.rules="${rule}"
|
||||
|
||||
# Tests from Benchamarking and Documentation(TEST-NET-3).
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 198.18.0.1/24 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 198.18.23.2/24 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 198.18.23.1/22 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 198.18.23.3/24 up
|
||||
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 198.51.100.001/24 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 198.51.100.254/24 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 198.51.100.100/24 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b 203.0.113.1/24 up
|
||||
|
||||
# Reset rules OID.
|
||||
sysctl security.mac.ipacl.rules=
|
||||
}
|
||||
|
||||
ipacl_v4_cleanup()
|
||||
{
|
||||
ipacl_test_cleanup
|
||||
}
|
||||
|
||||
atf_test_case "ipacl_v6" "cleanup"
|
||||
|
||||
ipacl_v6_head()
|
||||
{
|
||||
atf_set descr 'basic test for ipacl on IPv6 addresses'
|
||||
atf_set require.user root
|
||||
}
|
||||
|
||||
ipacl_v6_body()
|
||||
{
|
||||
ipacl_test_init
|
||||
|
||||
epairA=$(vnet_mkepair)
|
||||
epairB=$(vnet_mkepair)
|
||||
epairC=$(vnet_mkepair)
|
||||
|
||||
vnet_mkjail A ${epairA}b
|
||||
vnet_mkjail B ${epairB}b ${epairC}b
|
||||
|
||||
jidA=$(jls -j A -s jid | grep -o -E '[0-9]+')
|
||||
jidB=$(jls -j B -s jid | grep -o -E '[0-9]+')
|
||||
|
||||
# The ipacl policy module is not enforced for IPv6.
|
||||
sysctl security.mac.ipacl.ipv6=0
|
||||
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 2001:2::abcd/48 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 2001:2::5ea:11/48 up
|
||||
|
||||
# The ipacl policy module is enforced for IPv6 and prevent all
|
||||
# jails from setting their IPv6 address.
|
||||
sysctl security.mac.ipacl.ipv6=1
|
||||
sysctl security.mac.ipacl.rules=
|
||||
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 2001:2::abcd/48 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 2001:2::5ea:11/48 up
|
||||
|
||||
rule="${jidA},1,${epairA}b,AF_INET6,2001:db8::1111/-1@"
|
||||
rule="${rule}${jidB},1,${epairB}b,AF_INET6,2001:2::1234:1234/-1@"
|
||||
rule="${rule}${jidB},1,,AF_INET6,fe80::/32@"
|
||||
rule="${rule}${jidB},0,,AF_INET6,fe80::abcd/-1"
|
||||
sysctl security.mac.ipacl.rules="${rule}"
|
||||
|
||||
# Verify if it allows jail to set only certain IPv6 address.
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 2001:db8::1111/64 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 2001:db8::1112/64 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairB}b inet6 2001:2::1234:1234/48 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 2001:2::1234:1234/48 up
|
||||
|
||||
# Verify if the module allow jail set any address in subnet.
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairB}b inet6 FE80::1101:1221/15 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairB}b inet6 FE80::abab/15 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairB}b inet6 FE80::1/64 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairB}b inet6 FE80::abcd/15 up
|
||||
|
||||
# Check wildcard for interfaces.
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b inet6 FE80::1101:1221/15 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b inet6 FE80::abab/32 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b inet6 FE81::1/64 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b inet6 FE80::abcd/32 up
|
||||
|
||||
rule="${jidB},1,,AF_INET6,2001:2::/48@"
|
||||
rule="${rule}${jidB},1,,AF_INET6,2001:3::/32"
|
||||
sysctl security.mac.ipacl.rules="${rule}"
|
||||
|
||||
# Tests when subnet is allowed.
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b inet6 2001:2:0001::1/64 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b inet6 2001:2:1000::1/32 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b inet6 2001:3:0001::1/64 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec B ifconfig ${epairC}b inet6 2001:4::1/64 up
|
||||
|
||||
# More tests of ULA address space.
|
||||
rule="${jidA},1,,AF_INET6,fc00::/7@"
|
||||
rule="${rule}${jidA},0,,AF_INET6,fc00::1111:2200/120@"
|
||||
rule="${rule}${jidA},1,,AF_INET6,fc00::1111:2299/-1@"
|
||||
rule="${rule}${jidA},1,,AF_INET6,2001:db8::/32@"
|
||||
rule="${rule}${jidA},0,,AF_INET6,2001:db8::abcd/-1"
|
||||
sysctl security.mac.ipacl.rules="${rule}"
|
||||
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 fc00::0000:1234/48 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 fc00::0000:1234/48 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 f800::2222:2200/48 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 f800::2222:22ff/48 up
|
||||
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 fc00::1111:2111/64 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 fc00::1111:2211/64 up
|
||||
atf_check -s not-exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 fc00::1111:22aa/48 up
|
||||
atf_check -s exit:0 -e ignore \
|
||||
jexec A ifconfig ${epairA}b inet6 fc00::1111:2299/48 up
|
||||
|
||||
# More tests from IPv6 documentation range.
|
||||
atf_check -s exit:0 -e ignore jexec A ifconfig \
|
||||
${epairA}b inet6 2001:db8:abcd:bcde:cdef:def1:ef12:f123/32 up
|
||||
atf_check -s exit:0 -e ignore jexec A ifconfig \
|
||||
${epairA}b inet6 2001:db8:1111:2222:3333:4444:5555:6666/32 up
|
||||
atf_check -s not-exit:0 -e ignore jexec A ifconfig \
|
||||
${epairA}b inet6 2001:ab9:1111:2222:3333:4444:5555:6666/32 up
|
||||
atf_check -s not-exit:0 -e ignore jexec A ifconfig \
|
||||
${epairA}b inet6 2001:db8::abcd/32 up
|
||||
|
||||
# Reset rules OID.
|
||||
sysctl security.mac.ipacl.rules=
|
||||
}
|
||||
|
||||
ipacl_v6_cleanup()
|
||||
{
|
||||
ipacl_test_cleanup
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case "ipacl_v4"
|
||||
atf_add_test_case "ipacl_v6"
|
||||
}
|
18
tests/sys/mac/ipacl/utils.subr
Normal file
18
tests/sys/mac/ipacl/utils.subr
Normal file
@ -0,0 +1,18 @@
|
||||
# $FreeBSD$
|
||||
# Utility functions for mac_ipacl tests
|
||||
|
||||
. $(atf_get_srcdir)/../../common/vnet.subr
|
||||
|
||||
ipacl_test_init()
|
||||
{
|
||||
vnet_init
|
||||
|
||||
if ! kldstat -q -m mac_ipacl; then
|
||||
atf_skip "mac_ipacl is not loaded"
|
||||
fi
|
||||
}
|
||||
|
||||
ipacl_test_cleanup()
|
||||
{
|
||||
vnet_cleanup
|
||||
}
|
Loading…
Reference in New Issue
Block a user