summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_jail.c
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2010-01-17 12:57:11 +0000
committerbz <bz@FreeBSD.org>2010-01-17 12:57:11 +0000
commitd80ba03e3c55996b4cbd43c63798a30f830c08c3 (patch)
tree2b602932505487bf20c4f34fd4d2c8c7b7e2dc5e /sys/kern/kern_jail.c
parentb89a432ee1889ec29b188c301b5171234c9247bc (diff)
downloadFreeBSD-src-d80ba03e3c55996b4cbd43c63798a30f830c08c3.zip
FreeBSD-src-d80ba03e3c55996b4cbd43c63798a30f830c08c3.tar.gz
Add ip4.saddrsel/ip4.nosaddrsel (and equivalent for ip6) to control
whether to use source address selection (default) or the primary jail address for unbound outgoing connections. This is intended to be used by people upgrading from single-IP jails to multi-IP jails but not having to change firewall rules, application ACLs, ... but to force their connections (unless otherwise changed) to the primry jail IP they had been used for years, as well as for people prefering to implement similar policies. Note that for IPv6, if configured incorrectly, this might lead to scope violations, which single-IPv6 jails could as well, as by the design of jails. [1] Reviewed by: jamie, hrs (ipv6 part) Pointed out by: hrs [1] MFC After: 2 weeks Asked for by: Jase Thew (bazerka beardz.net)
Diffstat (limited to 'sys/kern/kern_jail.c')
-rw-r--r--sys/kern/kern_jail.c110
1 files changed, 108 insertions, 2 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 8ad22ca..379ff78 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -77,6 +77,21 @@ __FBSDID("$FreeBSD$");
MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
+/* Keep struct prison prison0 and some code in kern_jail_set() readable. */
+#ifdef INET
+#ifdef INET6
+#define _PR_IP_SADDRSEL PR_IP4_SADDRSEL|PR_IP6_SADDRSEL
+#else
+#define _PR_IP_SADDRSEL PR_IP4_SADDRSEL
+#endif
+#else /* !INET */
+#ifdef INET6
+#define _PR_IP_SADDRSEL PR_IP6_SADDRSEL
+#else
+#define _PR_IP_SADDRSEL 0
+#endif
+#endif
+
/* prison0 describes what is "real" about the system. */
struct prison prison0 = {
.pr_id = 0,
@@ -89,9 +104,9 @@ struct prison prison0 = {
.pr_hostuuid = DEFAULT_HOSTUUID,
.pr_children = LIST_HEAD_INITIALIZER(prison0.pr_children),
#ifdef VIMAGE
- .pr_flags = PR_HOST|PR_VNET,
+ .pr_flags = PR_HOST|PR_VNET|_PR_IP_SADDRSEL,
#else
- .pr_flags = PR_HOST,
+ .pr_flags = PR_HOST|_PR_IP_SADDRSEL,
#endif
.pr_allow = PR_ALLOW_ALL,
};
@@ -129,10 +144,22 @@ static int prison_restrict_ip6(struct prison *pr, struct in6_addr *newip6);
*/
static char *pr_flag_names[] = {
[0] = "persist",
+#ifdef INET
+ [7] = "ip4.saddrsel",
+#endif
+#ifdef INET6
+ [8] = "ip6.saddrsel",
+#endif
};
static char *pr_flag_nonames[] = {
[0] = "nopersist",
+#ifdef INET
+ [7] = "ip4.nosaddrsel",
+#endif
+#ifdef INET6
+ [8] = "ip6.nosaddrsel",
+#endif
};
struct jailsys_flags {
@@ -1199,6 +1226,9 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
#endif
}
#endif
+ /* Source address selection is always on by default. */
+ pr->pr_flags |= _PR_IP_SADDRSEL;
+
pr->pr_securelevel = ppr->pr_securelevel;
pr->pr_allow = JAIL_DEFAULT_ALLOW & ppr->pr_allow;
pr->pr_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS;
@@ -2659,6 +2689,41 @@ prison_get_ip4(struct ucred *cred, struct in_addr *ia)
}
/*
+ * Return 1 if we should do proper source address selection or are not jailed.
+ * We will return 0 if we should bypass source address selection in favour
+ * of the primary jail IPv4 address. Only in this case *ia will be updated and
+ * returned in NBO.
+ * Return EAFNOSUPPORT, in case this jail does not allow IPv4.
+ */
+int
+prison_saddrsel_ip4(struct ucred *cred, struct in_addr *ia)
+{
+ struct prison *pr;
+ struct in_addr lia;
+ int error;
+
+ KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
+ KASSERT(ia != NULL, ("%s: ia is NULL", __func__));
+
+ if (!jailed(cred))
+ return (1);
+
+ pr = cred->cr_prison;
+ if (pr->pr_flags & PR_IP4_SADDRSEL)
+ return (1);
+
+ lia.s_addr = INADDR_ANY;
+ error = prison_get_ip4(cred, &lia);
+ if (error)
+ return (error);
+ if (lia.s_addr == INADDR_ANY)
+ return (1);
+
+ ia->s_addr = lia.s_addr;
+ return (0);
+}
+
+/*
* Return true if pr1 and pr2 have the same IPv4 address restrictions.
*/
int
@@ -2964,6 +3029,41 @@ prison_get_ip6(struct ucred *cred, struct in6_addr *ia6)
}
/*
+ * Return 1 if we should do proper source address selection or are not jailed.
+ * We will return 0 if we should bypass source address selection in favour
+ * of the primary jail IPv6 address. Only in this case *ia will be updated and
+ * returned in NBO.
+ * Return EAFNOSUPPORT, in case this jail does not allow IPv6.
+ */
+int
+prison_saddrsel_ip6(struct ucred *cred, struct in6_addr *ia6)
+{
+ struct prison *pr;
+ struct in6_addr lia6;
+ int error;
+
+ KASSERT(cred != NULL, ("%s: cred is NULL", __func__));
+ KASSERT(ia6 != NULL, ("%s: ia6 is NULL", __func__));
+
+ if (!jailed(cred))
+ return (1);
+
+ pr = cred->cr_prison;
+ if (pr->pr_flags & PR_IP6_SADDRSEL)
+ return (1);
+
+ lia6 = in6addr_any;
+ error = prison_get_ip6(cred, &lia6);
+ if (error)
+ return (error);
+ if (IN6_IS_ADDR_UNSPECIFIED(&lia6))
+ return (1);
+
+ bcopy(&lia6, ia6, sizeof(struct in6_addr));
+ return (0);
+}
+
+/*
* Return true if pr1 and pr2 have the same IPv6 address restrictions.
*/
int
@@ -4116,12 +4216,18 @@ SYSCTL_JAIL_PARAM_SYS_NODE(ip4, CTLFLAG_RDTUN,
"Jail IPv4 address virtualization");
SYSCTL_JAIL_PARAM_STRUCT(_ip4, addr, CTLFLAG_RW, sizeof(struct in_addr),
"S,in_addr,a", "Jail IPv4 addresses");
+SYSCTL_JAIL_PARAM(_ip4, saddrsel, CTLTYPE_INT | CTLFLAG_RW,
+ "B", "Do (not) use IPv4 source address selection rather than the "
+ "primary jail IPv4 address.");
#endif
#ifdef INET6
SYSCTL_JAIL_PARAM_SYS_NODE(ip6, CTLFLAG_RDTUN,
"Jail IPv6 address virtualization");
SYSCTL_JAIL_PARAM_STRUCT(_ip6, addr, CTLFLAG_RW, sizeof(struct in6_addr),
"S,in6_addr,a", "Jail IPv6 addresses");
+SYSCTL_JAIL_PARAM(_ip6, saddrsel, CTLTYPE_INT | CTLFLAG_RW,
+ "B", "Do (not) use IPv6 source address selection rather than the "
+ "primary jail IPv6 address.");
#endif
SYSCTL_JAIL_PARAM_NODE(allow, "Jail permission flags");
OpenPOWER on IntegriCloud