Page MenuHomeFreeBSD

D20967.id59909.diff
No OneTemporary

D20967.id59909.diff

Index: sys/modules/mac_ipacl/Makefile
===================================================================
--- /dev/null
+++ sys/modules/mac_ipacl/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/security/mac_ipacl
+
+KMOD=mac_ipacl
+SRCS=mac_ipacl.c
+
+.include <bsd.kmod.mk>
Index: sys/netinet/in.c
===================================================================
--- sys/netinet/in.c
+++ sys/netinet/in.c
@@ -72,6 +72,10 @@
#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 thread *);
static int in_difaddr_ioctl(u_long, caddr_t, struct ifnet *, struct thread *);
@@ -372,6 +376,15 @@
/*
* See whether address already exist.
*/
+
+#ifdef MAC
+ /*Check if a MAC policy disallows setting the IPv4 address.*/
+ error = mac_inet_check_SIOCAIFADDR(td->td_ucred,
+ &addr->sin_addr, ifp);
+ if (error)
+ return (error);
+#endif
+
iaIsFirst = true;
ia = NULL;
NET_EPOCH_ENTER(et);
Index: sys/netinet6/in6.c
===================================================================
--- sys/netinet6/in6.c
+++ sys/netinet6/in6.c
@@ -112,6 +112,9 @@
#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
@@ -556,7 +559,14 @@
{
struct nd_prefixctl pr0;
struct nd_prefix *pr;
-
+
+#ifdef MAC
+ /*Check if a MAC policy disallows setting the IPv6 address.*/
+ error = mac_inet6_check_SIOCAIFADDR(td->td_ucred,
+ &sa6->sin6_addr, ifp);
+ if (error)
+ goto out;
+#endif
/*
* first, make or update the interface address structure,
* and link it to the list.
Index: sys/security/mac/mac_framework.h
===================================================================
--- sys/security/mac/mac_framework.h
+++ sys/security/mac/mac_framework.h
@@ -89,6 +89,9 @@
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 */
@@ -153,6 +156,12 @@
int mac_ifnet_ioctl_set(struct ucred *cred, struct ifreq *ifr,
struct ifnet *ifp);
+/*Checks if the IP address is allowed for the interface.*/
+int mac_inet_check_SIOCAIFADDR(struct ucred *cred,
+ const struct in_addr *ia, struct ifnet *ifp);
+int mac_inet6_check_SIOCAIFADDR(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);
Index: sys/security/mac/mac_inet.c
===================================================================
--- sys/security/mac/mac_inet.c
+++ sys/security/mac/mac_inet.c
@@ -108,6 +108,18 @@
return (0);
}
+
+/* Check with rules in module if the IPv4 address is allowed.*/
+int
+mac_inet_check_SIOCAIFADDR(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)
{
Index: sys/security/mac/mac_inet6.c
===================================================================
--- sys/security/mac/mac_inet6.c
+++ sys/security/mac/mac_inet6.c
@@ -173,6 +173,16 @@
q6->ip6q_label);
}
+/* Check with rules in module if the IPv4 address is allowed.*/
+int
+mac_inet6_check_SIOCAIFADDR(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)
{
Index: sys/security/mac/mac_policy.h
===================================================================
--- sys/security/mac/mac_policy.h
+++ sys/security/mac/mac_policy.h
@@ -100,6 +100,9 @@
struct vattr;
struct vnode;
+struct in_addr;
+struct in6_addr;
+
/*
* Policy module operations.
*/
@@ -238,6 +241,12 @@
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);
@@ -746,6 +755,9 @@
mpo_inpcb_destroy_label_t mpo_inpcb_destroy_label;
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;
Index: sys/security/mac_ipacl/Makefile
===================================================================
--- /dev/null
+++ sys/security/mac_ipacl/Makefile
@@ -0,0 +1,4 @@
+KMOD=mac_ipacl
+SRCS=mac_ipacl.c
+
+.include <bsd.kmod.mk>
Index: sys/security/mac_ipacl/design_notes.txt
===================================================================
--- /dev/null
+++ sys/security/mac_ipacl/design_notes.txt
@@ -0,0 +1,72 @@
+"Simplicity is the ultimate sophistication"
+------------------------
+|mac_ipacl Design Notes|
+------------------------
+
+Design Goals -
+------------
+1. Do we need to check the addresses per interface per vnet-jail or addresses per
+ vnet-jail?
+
+ The first one gives more flexibilty but increases complexity of policy table.
+ The first is more prefered over the second since it gives ability to restrict
+ the particular interface of a jail.
+
+2. Another question which increses complexity here is- Should jails be allowed to
+ create new interface(intefaces created after the policy has been loaded? and,
+ if yes, then how our module will react to the new interface?
+
+ I am not sure about this one. But the new interfaces shall not affect the host
+ until and unless they are connected to the host or other jail. So, they don't
+ have any effect but this issue should be dealt to prevent any design flaw/bugs.
+
+ New interfaces, by default, should not have any rights to set the IP address,
+ new rules(about the new interface) have to be applied by the host to provide
+ those rights.
+
+3. Another important step is to decide whether to allow all IP addresses or reject
+ all IP address when the MAC module is loaded?
+
+ I'm thinking to allow all address when the module is loaded and then tune it with
+ a sysctl variable to disallow all. The host can then specify IP address to allow
+ according to the Policy Table.
+
+4. The "Policy Table" may take-
+ a.) JID(or name of the jail) - the jail id/name for the jail for which the
+ restriction are to be applied, This identifies that jail.
+ b.) Network Interface - The network interface which are allowed to set the IP
+ address and/or which are not?
+ OR we can say, name of the interfaces that are allowed for setting their IP
+ c.) IP address/list of IP address which are allowed for particular interface.
+ d.) Network Prefix(A range of IP address) that is allowed to the jail.
+ e.) label to allow/reject? But depend on whether we started with all IP or NO IP.
+ f.) ?
+
+5. In policy, we may check the jail by passing the credential and where the thread is
+ and also if the thread's vnet and intefaces matches.
+
+6. How to name the jail in the policy?
+
+ I am thinking of using jid to name the jail in the policy. But another question
+ arises is how to find that jail with that jid. Search for the function that find
+ your prison with given jid. check prison_find(int jid), this will solve this problem
+
+7. should we also check for subnet the jail is choosing? If yes, then we also have to pass
+ the prefix to the framework.
+
+Points
+(To be kept in mind) -
+--------------------
+1. ioctl check calls should be kept generic. Although, currently we are only interested
+ in VIMAGE JAILS, but in future might need to extend the MAC module to host system,
+ et cetera.
+ So, the MAC calls should run for all cases, and checks related to jails and VNET
+ should be handled later in the Policy Module
+
+3. vnet should be checked from socket or interface and not from the thread. This means
+ we'd probably have to pass one of those in the policy as well.
+
+ Passing the interface ifnet to the policy will be more easy/appropriate, since only
+ it is available as arguement in in.c(in_aifaddr_ioctl) for our MAC checks. Alternatively
+ we could have moved our check to in_control() for ipv4 case like we have in IPv6 case,
+ for checking the vnet from socket.
Index: sys/security/mac_ipacl/mac_ipacl.c
===================================================================
--- /dev/null
+++ sys/security/mac_ipacl/mac_ipacl.c
@@ -0,0 +1,409 @@
+/* MAC policy module for limiting IP address to a VNET enabled jail. */
+
+#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, 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 {
+ struct in_addr ipv4;
+ struct in6_addr ipv6;
+ u_int8_t addr8[16];
+ u_int16_t addr16[8];
+ u_int32_t addr32[4];
+ } ipa; /* 128 bit address*/
+#define v4 ipa.ipv4
+#define v6 ipa.ipv6
+#define addr8 ipa.addr8
+#define addr16 ipa.addr16
+#define addr32 ipa.addr32
+};
+
+struct ip_rule {
+ int jid;
+ bool allow;
+ bool subnet_apply; /*rule applied on whole subnet*/
+ char if_name[IFNAMSIZ]; /*network interface name*/
+ 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 *jid, *allow, *if_name, *fam, *ip_addr, *mask, *p;
+ struct ip_rule *new;
+ int error, prefix, i;
+
+ error = 0;
+ new = malloc(sizeof(*new), M_IPACL, M_ZERO | M_WAITOK);
+ /* Should we support a jail wildcard? */
+ jid = strsep(&element, "@");
+ if (jid == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ new->jid = strtol(jid, &p, 10);
+ if (*p != '\0') {
+ error = EINVAL;
+ goto out;
+ }
+ allow = strsep(&element, "@");
+ if (allow == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ new->allow = strtol(allow, &p, 10);
+ if (*p != '\0') {
+ error = EINVAL;
+ goto out;
+ }
+ if_name = strsep(&element, "@");
+ if (sizeof(if_name) > IFNAMSIZ) {
+ error = EINVAL;
+ goto out;
+ }
+ /* Empty interface name is wildcard to all interfaces.*/
+ bzero(new->if_name, IFNAMSIZ);
+ bcopy(if_name, new->if_name, strlen(if_name));
+ fam = strsep(&element, "@");
+ if (fam == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ new->af = (strcmp(fam, "AF_INET") == 0) ? AF_INET :
+ (strcmp(fam, "AF_INET6") == 0) ? AF_INET6 : -1;
+ if (new->af == -1) {
+ error = EINVAL;
+ goto out;
+ }
+ ip_addr = strsep(&element, "@");
+ if (ip_addr == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ if (inet_pton(new->af, ip_addr, new->addr.addr32) != 1) {
+ error = EINVAL;
+ goto out;
+ }
+ mask = element;
+ if (mask == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ prefix = strtol(mask, &p, 10);
+ if (*p != '\0') {
+ error = EINVAL;
+ goto out;
+ }
+ /*Value -1 for prefix make policy applicable to individual IP only.*/
+ if (prefix == -1)
+ new->subnet_apply = false;
+ else {
+ new->subnet_apply = true;
+ if (new->af == AF_INET) {
+ if (prefix < 0 || prefix > 32) {
+ error = EINVAL;
+ goto out;
+ }
+ if (prefix == 0)
+ new->mask.addr32[0] = htonl(0);
+ else
+ new->mask.addr32[0] =
+ htonl(~((1 << (32 - prefix)) - 1));
+ new->addr.addr32[0] &= new->mask.addr32[0];
+ }
+ else {
+ if (prefix < 0 || prefix > 128) {
+ error = EINVAL;
+ goto out;
+ }
+ for (i = 0; prefix > 0; prefix -= 8, i++)
+ new->mask.addr8[i] =
+ prefix >= 8 ? 0xFF :
+ (u_int8_t)((0xFFU << (8 - prefix)) & 0xFFU);
+ for (i=0; i<16; i++)
+ new->addr.addr8[i] &= new->mask.addr8[i];
+ }
+ }
+out:
+ if (error != 0) {
+ free(new, M_IPACL);
+ *rule = NULL;
+ } else
+ *rule = new;
+ return (error);
+}
+
+/*
+ * 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;
+ error = parse_rule_element(element, &new);
+ if (error)
+ 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, 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, i;
+ bool same_subnet;
+ error = EPERM;
+
+ mtx_lock(&rule_mtx);
+
+ for (rule = TAILQ_FIRST(&rule_head);
+ rule != NULL;
+ rule = TAILQ_NEXT(rule, 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) {
+ 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;
+ 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;
+ default:
+ error = EINVAL;
+ }
+
+ if (rule->allow)
+ error = 0;
+ else
+ error = EPERM;
+ }
+
+ mtx_unlock(&rule_mtx);
+
+ return (error);
+}
+
+/* Feature request: Can we make this a sysctl policy as well defaulting
+ * to jails only, but if changed also applying to the base system?
+ */
+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;
+
+ /*function only when requested by a jail*/
+ if (!jailed(cred))
+ return 0;
+
+ /*check with the policy only when it is enforced for ipv4*/
+ if (ipacl_ipv4)
+ return rules_check(cred, &ip4_addr, ifp);
+
+ return 0;
+}
+
+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 scope id*/
+
+ /*function only when requested by a jail*/
+ if (!jailed(cred))
+ return 0;
+
+ /*check with the policy when it is enforced for ipv6*/
+ if (ipacl_ipv6)
+ return rules_check(cred, &ip6_addr, ifp);
+
+ return 0;
+}
+
+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);
Index: sys/security/mac_ipacl/notes.txt
===================================================================
--- /dev/null
+++ sys/security/mac_ipacl/notes.txt
@@ -0,0 +1,90 @@
+-----------------------------------
+Documentation Notes-
+IP Address access control policy
+
+1. 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.
+
+2. Its default behaviour is to deny all IP addresses if policy is enforced and allow/deny
+ IP(or subnets) according to rules specified with sysctl
+
+ Runtime Configuration-sysctl(8) MIB
+
+ security.mac.ipacl.ipv4: enforce the mac_ipacl for ipv4 addresses (default:1)
+
+ security.mac.ipacl.ipv6: enforce the mac_ipacl for ipv6 addresses (default:1)
+
+ security.mac.ipacl.rules:
+ jail_id@allow@interface@address_family@IP_addr@prefix_length[,jail_id@...]
+
+ jail_id: Describe the jail id of the jail for which the rule is written
+
+ allow: 1 for allow and 0 for deny. action to perform for the rule
+
+ interface: name of the interface the rule is enforced for. Interface is
+ left empty(ie, NULL) then it is a wildcard to enforce rule
+ for all interfaces.
+
+ address_family: Address family of the IP_addr. give input as AF_INET
+ or AF_INET6 string only
+
+ IP_addr: IP address(or subnet) to be allowed/deny. Action depend on the
+ prefix length
+
+ prefix_length: Prefix length of the subnet to be enforced by the policy.
+ -1 implies the policy is enforced for individual IP address.
+ For non-negative value, a range of IP address(present in subnet)
+ which calculated as subnet = IP_addr & mask
+3. Example-
+ a.)
+ sysctl security.mac.ipacl.ipv4=1
+ sysctl security.mac.ipacl.ipv6=0
+ sysctl security.mac.ipacl.rules=1@1@@AF_INET@169.254.123.123@-1
+ It allows only 169.254.123.123 IPv4 address for all interfaces(wildcard) of jail 1.
+ It allows all IPv6 address since policy is not enforced for IPv6.
+
+ b.)
+ sysctl security.mac.ipacl.ipv4=1
+ sysctl security.mac.ipacl.ipv6=1
+ sysctl security.mac.ipacl.rules=1@1@epair0b@AF_INET6@fe80::@32,1@0@epair0b@AF_INET6@fe80::abcd@-1
+ It deny all IPv4 address as policy is enforced but no rules are specified about it.
+ It allow all IPv6 address in the subnet- fe80::/32 except fe80::abcd for interface epair0b only
+ c.)
+ sysctl security.mac.ipacl.ipv4=1
+ sysctl security.mac.ipacl.ipv6=1
+ sysctl security.mac.ipacl.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
+ It allow IPv4 in the subnet 198.51.100.0/24 for jail 2 and all interfaces.
+ It allow IPv6 address in the subnet fc00::/7 but deny the subnet fc00::1111:2200/120, and allow
+ individual IP fc00::1111:2299 from the denied subnet for all interfaces in the jail 2
+
+4. Using the test scripts:
+ a.)
+ Test scripts are not completely automatic :( So, the user has to create
+ edit the scripts to enter the jid of the test jails and interface.
+ After editing the scripts run make && make install, which then install
+ the scripts in /usr/tests/sys/mac/ipacl.
+ you may also need to create that directory if it gives error.
+
+6. To discuss the limitation of the module and point to be kept in mind while
+ using it.
+ a.)
+ rules are checked in the same sequence they are given. If many rules are
+ there for a IP(or a set of IP), result depend on final rule.
+ b.)
+
+7. Future Works
+ a.)
+ 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.
+
+
+-------------------------------------
+Commands-
+1. kld
+ * kldstat
+ * kldload /usr/obj/usr/home/shivank/freebsd/amd64.amd64/sys/security/mac_ipacl/mac_ipacl.ko
+ * kldunload mac_ipacl
+2. make
+ * make obj depend all install #create obj in /boot/modules, can be loaded and unloaded by just name
+ * make -j 4 KERNCONF=VIMAGE kernel -DKERNFAST
Index: sys/security/mac_ipacl/tests/Makefile
===================================================================
--- /dev/null
+++ sys/security/mac_ipacl/tests/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/sys/mac/ipacl
+
+${PACKAGE}FILES+= ipacl_script.sh
+
+TAP_TESTS_SH+= ip4_test
+TAP_TESTS_SH+= ip6_test
+.for t in ${TAP_TESTS_SH}
+TEST_METADATA.$t+= required_user="root"
+TEST_METADATA.$t+= timeout="450"
+.endfor
+
+.include <bsd.test.mk>
Index: sys/security/mac_ipacl/tests/ip4_test.sh
===================================================================
--- /dev/null
+++ sys/security/mac_ipacl/tests/ip4_test.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+# $FreeBSD$
+
+dir=`dirname $0`
+. ${dir}/ipacl_script.sh
+
+echo "1..32"
+jid1=1
+jid2=3
+#run this script for epair0a and epair0b as of now
+#use ifconfig epair create to generate epair
+#epair0a = host #epair0b = jail 1
+# make sure to create second jail(jid=2) with epair1b
+
+#this script also tests that host remain unaffected in all cases
+if1_host="epair0a"
+if1_jail1="epair0b"
+if2_jail1="lo0"
+if1_jail2="epair1b"
+if2_jail2="lo0"
+
+# Verify effect of changing security.mac.ipacl.ipv4
+sysctl security.mac.ipacl.ipv4=0 >/dev/null
+exec_test ok ipv4 ${if1_host} '192.168.43.26' 16 0
+exec_test ok ipv4 ${if1_jail1} '192.168.43.26' 16 1
+exec_test ok ipv4 ${if1_host} '127.1.32.31' 24 0
+exec_test ok ipv4 ${if1_jail1} '198.18.0.12' 15 1
+
+sysctl security.mac.ipacl.ipv4=1 >/dev/null
+sysctl security.mac.ipacl.rules= >/dev/null
+
+exec_test ok ipv4 ${if1_host} '192.168.43.26' 16 0
+exec_test fl ipv4 ${if1_jail1} '192.168.43.26' 16 1
+exec_test ok ipv4 ${if1_host} '127.1.32.31' 24 0
+exec_test fl ipv4 ${if1_jail1} '198.18.0.12' 15 1
+
+# rule: jid@allow@interface_name@addr_family@ip_addr@subnet_mask
+sysctl security.mac.ipacl.rules=${jid1}@1@${if1_jail1}@AF_INET@192.168.42.2@-1,${jid2}@1@${if1_jail2}@AF_INET@127.1.32.1@-1,${jid2}@1@@AF_INET@198.18.0.1@15,${jid2}@0@@AF_INET@198.18.0.12@-1 >/dev/null
+
+# Verify if security.mac.ipacl.rules allow jail to set certain IPv4 address
+exec_test ok ipv4 ${if1_jail1} '192.168.42.2' 16 ${jid1}
+exec_test fl ipv4 ${if1_jail1} '192.168.42.3' 16 ${jid1}
+exec_test ok ipv4 ${if1_jail2} '127.1.32.1' 24 ${jid2}
+exec_test fl ipv4 ${if2_jail2} '127.1.32.1' 24 ${jid2}
+
+# Verify if scurity.mac.ipacl.rules allow jail to set any address in subnet
+exec_test ok ipv4 ${if1_jail2} '198.18.0.192' 15 ${jid2}
+exec_test ok ipv4 ${if1_jail2} '198.18.132.121' 15 ${jid2}
+exec_test fl ipv4 ${if1_jail2} '197.1.123.123' 15 ${jid2}
+exec_test fl ipv4 ${if1_jail2} '198.18.0.12' 15 ${jid2} #last rule disllow the ip in that subnet
+
+# Verify if security.mac.ipacl.rules (interface wildcard) allow jail to set certain IPv4 address
+exec_test ok ipv4 ${if2_jail2} '198.18.0.192' 15 ${jid2}
+exec_test ok ipv4 ${if2_jail2} '198.18.132.121' 15 ${jid2}
+exec_test fl ipv4 ${if2_jail2} '197.1.123.123' 15 ${jid2}
+exec_test fl ipv4 ${if2_jail2} '198.18.0.12' 15 ${jid2} #last rule disllow the ip in that subnet
+
+# Add more checks on subnet
+sysctl security.mac.ipacl.rules=${jid2}@1@@AF_INET@10.0.0.0@16,${jid2}@1@@AF_INET@10.12.0.0@16
+
+exec_test fl ipv4 ${if2_jail2} '10.1.0.0' 16 ${jid2}
+exec_test ok ipv4 ${if2_jail2} '10.0.10.10' 16 ${jid2}
+exec_test fl ipv4 ${if2_jail2} '10.13.0.0' 24 ${jid2}
+exec_test fl ipv4 ${if2_jail2} '10.11.0.10' 24 ${jid2} #last rule disllow the ip in that subnet
+
+sysctl security.mac.ipacl.rules=${jid1}@1@@AF_INET@169.254.0.0@16,${jid1}@0@@AF_INET@169.254.123.0@24,${jid1}@1@@AF_INET@169.254.123.123@-1,${jid1}@1@@AF_INET@198.51.100.0@24,${jid1}@0@@AF_INET@198.51.100.100@-1 >/dev/null
+# Add more tests from Link-Local space and Documentation(TEST-NET-3)
+exec_test ok ipv4 ${if1_jail1} '169.254.121.121' 16 ${jid1}
+exec_test fl ipv4 ${if1_jail1} '169.254.123.121' 16 ${jid1}
+exec_test ok ipv4 ${if1_jail1} '169.254.123.123' 16 ${jid1}
+exec_test fl ipv4 ${if1_jail1} '169.253.121.121' 16 ${jid1}
+
+exec_test ok ipv4 ${if2_jail1} '198.51.100.001' 24 ${jid1}
+exec_test ok ipv4 ${if2_jail1} '198.51.100.254' 24 ${jid1}
+exec_test fl ipv4 ${if1_jail1} '198.51.100.100' 24 ${jid1}
+exec_test fl ipv4 ${if1_jail1} '198.151.100.100' 24 ${jid1}
+
+sysctl security.mac.ipacl.rules= >/dev/null
Index: sys/security/mac_ipacl/tests/ip6_test.sh
===================================================================
--- /dev/null
+++ sys/security/mac_ipacl/tests/ip6_test.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+# $FreeBSD$
+
+dir=`dirname $0`
+. ${dir}/ipacl_script.sh
+
+echo "1..36"
+jid1=1
+jid2=3
+
+if1_host="epair0a"
+if1_jail1="epair0b"
+if2_jail1="lo0"
+if1_jail2="epair1b"
+if2_jail2="lo0"
+
+#run this script for epair0a and epair0b as of now
+#use ifconfig epair create to generate epair
+#epair0a = host #epair0b = jail 1
+# make sure to create second jail(jid=2) with epair1b
+
+#this script also tests that host remain unaffected in all cases
+
+# Verify effect of changing security.mac.ipacl.ipv4
+sysctl security.mac.ipacl.ipv6=0 >/dev/null
+exec_test ok ipv6 ${if1_host} '2001:db8::1111' 32 0
+exec_test ok ipv6 ${if1_jail1} '2001:db8::1112' 64 1
+exec_test ok ipv6 ${if1_host} '2001:2::abcd' 24 0
+exec_test ok ipv6 ${if1_jail1} '001:470:1e01:5ea::11' 48 1
+
+sysctl security.mac.ipacl.ipv6=1 >/dev/null
+sysctl security.mac.ipacl.rules= >/dev/null
+
+exec_test ok ipv6 ${if1_host} '2001:db8::1111' 32 0
+exec_test fl ipv6 ${if1_jail1} '2001:db8::1112' 64 1
+exec_test ok ipv6 ${if1_host} '2001:2::abcd' 24 0
+exec_test fl ipv6 ${if1_jail1} '001:470:1e01:5ea::11' 48 1
+
+# rule: jid@allow@interface_name@addr_family@ip_addr@subnet_mask
+sysctl security.mac.ipacl.rules=${jid1}@1@epair0b@AF_INET6@2001:db8::1111@-1,${jid2}@1@epair1b@AF_INET6@2001:2::1234:1234@-1,${jid2}@1@@AF_INET6@fe80::@32,${jid2}@0@@AF_INET6@fe80::abcd@-1 >/dev/null
+
+# Verify if security.mac.ipacl.rules allow jail to set certain IPv4 address
+exec_test ok ipv6 ${if1_jail1} '2001:db8::1111' 16 ${jid1}
+exec_test fl ipv6 ${if1_jail1} '2001:db8::1112' 16 ${jid1}
+exec_test ok ipv6 ${if1_jail2} '2001:2::1234:1234' 48 ${jid2}
+exec_test fl ipv6 ${if1_jail1} '2001:2::1234:1234' 48 ${jid1}
+
+# Verify if scurity.mac.ipacl.rules allow jail to set any address in subnet
+exec_test ok ipv6 ${if1_jail2} 'FE80::1101:1221' 15 ${jid2}
+exec_test ok ipv6 ${if1_jail2} 'FE80::abab' 15 ${jid2}
+exec_test ok ipv6 ${if1_jail2} 'FE80::1' 64 ${jid2}
+exec_test fl ipv6 ${if1_jail2} 'FE80::abcd' 15 ${jid2} #last rule disllow the ip in that subnet
+
+# Verify if security.mac.ipacl.rules (interface wildcard) allow jail to set certain IPv4 address
+exec_test ok ipv6 ${if2_jail2} 'FE80::1101:1221' 15 ${jid2}
+exec_test ok ipv6 ${if2_jail2} 'FE80::abab' 32 ${jid2}
+exec_test fl ipv6 ${if2_jail2} 'FE81::1' 64 ${jid2}
+exec_test fl ipv6 ${if2_jail2} 'FE80::abcd' 32 ${jid2} #last rule disllow the ip in that subnet
+
+
+# add more tests for subnet
+sysctl security.mac.ipacl.rules=${jid2}@1@@AF_INET6@2001:2::@48,${jid2}@1@@AF_INET6@2001:3::@32 >/dev/null
+exec_test fl ipv6 ${if2_jail2} '2001:2:0001::1' 64 ${jid2}
+exec_test fl ipv6 ${if2_jail2} '2001:2:1000::1' 32 ${jid2}
+exec_test ok ipv6 ${if2_jail2} '2001:3:0001::1' 64 ${jid2}
+exec_test fl ipv6 ${if2_jail2} '2001:4::1' 64 ${jid2}
+
+
+#add more tests of ULA address space
+#allow subnet fc00::/7 except subnet fc00::1111:22xx but allow fc00::1111:2281
+sysctl security.mac.ipacl.rules=${jid1}@1@@AF_INET6@fc00::@7,${jid1}@0@@AF_INET6@fc00::1111:2200@120,${jid1}@1@@AF_INET6@fc00::1111:2299@-1,${jid1}@1@@AF_INET6@2001:db8::@32,${jid1}@0@@AF_INET6@2001:db8::abcd@-1 >/dev/null
+exec_test ok ipv6 ${if1_jail1} 'fc00::0000:1234' 48 ${jid1}
+exec_test ok ipv6 ${if1_jail1} 'fc00::1112:1234' 48 ${jid1}
+exec_test fl ipv6 ${if1_jail1} 'f800::2222:2200' 48 ${jid1}
+exec_test fl ipv6 ${if1_jail1} 'f800::2222:22ff' 48 ${jid1}
+
+exec_test ok ipv6 ${if1_jail1} 'fc00::1111:2111' 64 ${jid1}
+exec_test fl ipv6 ${if1_jail1} 'fc00::1111:2211' 64 ${jid1}
+exec_test fl ipv6 ${if1_jail1} 'fc00::1111:22aa' 48 ${jid1}
+exec_test ok ipv6 ${if1_jail1} 'fc00::1111:2299' 48 ${jid1}
+
+#add more tests of documentation range IPV6
+exec_test ok ipv6 ${if1_jail1} '2001:db8:abcd:bcde:cdef:def1:ef12:f123' 32 ${jid1}
+exec_test ok ipv6 ${if1_jail1} '2001:db8:1111:2222:3333:4444:5555:6666' 32 ${jid1}
+exec_test fl ipv6 ${if1_jail1} '2000:db9:1111:2222:3333:4444:5555:6666' 32 ${jid1}
+exec_test fl ipv6 ${if2_jail1} '2001:db8::abcd' 32 ${jid1}
+
+sysctl security.mac.ipacl.rules= >/dev/null
Index: sys/security/mac_ipacl/tests/ipacl_script.sh
===================================================================
--- /dev/null
+++ sys/security/mac_ipacl/tests/ipacl_script.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+# $FreeBSD$
+
+sysctl security.mac.ipacl >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echo "1..0 # SKIP MAC_IPACL is unavailable."
+ exit 0
+fi
+
+if [ "$(id -u)" -ne 0 ]; then
+ echo "1..0 # SKIP testcases must be run as root"
+ exit 0
+fi
+
+ntest=1
+
+test_ip() {
+ local proto interface address prefix jid
+
+ proto=${1}
+ interface=${2}
+ address=${3}
+ prefix=${4}
+ jid=${5} #if jid = 0 then assume host
+
+ if [ "${proto}" = "ipv4" ]; then
+ if [ "${jid}" -eq 0 ]; then
+ echo | ifconfig ${interface} ${address}/${prefix} up
+ RetVal=$?
+ else
+ echo | jexec ${jid} ifconfig ${interface} ${address}/${prefix} up
+ RetVal=$?
+ fi
+ elif [ "${proto}" = "ipv6" ]; then
+ if [ "${jid}" -eq 0 ]; then
+ echo | ifconfig ${interface} inet6 ${address} prefixlen ${prefix}
+ RetVal=$?
+ else
+ echo | jexec ${jid} ifconfig ${interface} inet6 ${address} prefixlen ${prefix}
+ RetVal=$?
+ fi
+ fi
+ if [ ${RetVal} -eq 0 ]; then
+ echo ok
+ else
+ echo fl
+ fi
+
+}
+
+exec_test() {
+ local expect_with_rule proto interface address prefix jid
+ expect_with_rule=${1}
+ proto=${2}
+ interface=${3}
+ address=${4}
+ prefix=${5}
+ jid=${6}
+
+ out=$(test_ip "${proto}" "${interface}" "${address}" "${prefix}" "${jid}")
+ if [ "${out}" = "${expect_with_rule}" ]; then
+ echo "ok : PASS ${ntest}"
+ elif [ "${out}" = "ok" ] || [ "${out}" = "fl" ]; then
+ echo "not ok : FAIL ${ntest} # '${out}' != '${expect_with_rule}'"
+ else
+ echo "not ok : FAIL ${ntest} # unexpected output: '${out}'"
+ fi
+ : $(( ntest += 1 ))
+}

File Metadata

Mime Type
text/plain
Expires
Thu, Nov 27, 4:08 PM (6 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26258741
Default Alt Text
D20967.id59909.diff (32 KB)

Event Timeline