core-extra/kernel/freebsd/imunes-8.0-RELEASE.diff
2013-08-29 14:21:13 +00:00

372 lines
11 KiB
Diff

# This patch is from http://imunes.net/imunes-8.0-RC3.diff
#
# This patch enables per-node directories, persistent hub/switch nodes, traffic
# snooping for wireshark, and disallows vlan interfaces within a jail.
diff -drup src-org/sys/kern/vfs_lookup.c src/sys/kern/vfs_lookup.c
--- src-org/sys/kern/vfs_lookup.c 2009-10-25 01:10:29.000000000 +0000
+++ src/sys/kern/vfs_lookup.c 2009-11-11 12:46:02.000000000 +0000
@@ -59,6 +59,8 @@ __FBSDID("$FreeBSD: src/sys/kern/vfs_loo
#include <sys/ktrace.h>
#endif
+#include <net/vnet.h>
+
#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
@@ -72,6 +74,19 @@ SDT_PROBE_DEFINE3(vfs, namei, lookup, en
"unsigned long");
SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *");
+#ifdef VIMAGE
+#define IMUNES_SYMLINK_HACK
+#endif
+
+#ifdef IMUNES_SYMLINK_HACK
+static VNET_DEFINE(int, morphing_symlinks);
+#define V_morphing_symlinks VNET(morphing_symlinks)
+
+SYSCTL_VNET_INT(_vfs, OID_AUTO, morphing_symlinks, CTLFLAG_RW,
+ &VNET_NAME(morphing_symlinks), 0,
+ "Resolve @ to vimage name in symlinks");
+#endif
+
/*
* Allocation zone for namei
*/
@@ -333,6 +348,44 @@ namei(struct nameidata *ndp)
error = ENOENT;
break;
}
+#ifdef IMUNES_SYMLINK_HACK
+ /*
+ * If the symbolic link includes a special character '@',
+ * and V_morphing_symlinks is set, substitute the first
+ * occurence of '@' with full path to jail / vimage name.
+ * If the full path includes subhierarchies, s/./\// when
+ * expanding '@' to jail / vimage name.
+ *
+ * XXX revisit buffer length checking.
+ */
+ CURVNET_SET_QUIET(TD_TO_VNET(curthread));
+ if (V_morphing_symlinks) {
+ char *sp = strchr(cp, '@');
+
+ if (sp) {
+ char *vname = td->td_ucred->cr_prison->pr_name;
+ int vnamelen = strlen(vname);
+ int i;
+
+ if (vnamelen >= auio.uio_resid) {
+ if (ndp->ni_pathlen > 1)
+ uma_zfree(namei_zone, cp);
+ error = ENAMETOOLONG;
+ CURVNET_RESTORE();
+ break;
+ }
+ bcopy(sp + 1, sp + vnamelen,
+ linklen - (sp - cp));
+ bcopy(td->td_ucred->cr_prison->pr_name,
+ sp, vnamelen);
+ linklen += (vnamelen - 1);
+ for (i = 0; i < vnamelen; i++)
+ if (sp[i] == '.')
+ sp[i] = '/';
+ }
+ }
+ CURVNET_RESTORE();
+#endif
if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
if (ndp->ni_pathlen > 1)
uma_zfree(namei_zone, cp);
diff -drup src-org/sys/net/bpf.c src/sys/net/bpf.c
--- src-org/sys/net/bpf.c 2009-10-25 01:10:29.000000000 +0000
+++ src/sys/net/bpf.c 2009-11-11 12:46:02.000000000 +0000
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/sys/net/bpf.c,v
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
+#include <sys/ctype.h>
#include <sys/fcntl.h>
#include <sys/jail.h>
#include <sys/malloc.h>
@@ -1435,9 +1436,34 @@ bpf_setif(struct bpf_d *d, struct ifreq
struct bpf_if *bp;
struct ifnet *theywant;
+#define XVNET_BPF_SNOOPING
+#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING)
+ struct vnet *target_vnet = curvnet;
+ char *c;
+
+ /* Attempt to attach to an ifnet in a foreign vnet, specified as @ */
+ c = rindex(ifr->ifr_name, '@');
+ if ( c != NULL ) {
+ struct prison *target_pr;
+
+ *c++ = 0;
+ if (!isascii(*c) && !isdigit(*c))
+ return ENXIO;
+ target_pr = prison_find_name(curthread->td_ucred->cr_prison, c);
+ if (target_pr == NULL)
+ return ENXIO;
+ target_vnet = target_pr->pr_vnet;
+ }
+ CURVNET_SET_QUIET(target_vnet);
+#endif
+
theywant = ifunit(ifr->ifr_name);
- if (theywant == NULL || theywant->if_bpf == NULL)
+ if (theywant == NULL || theywant->if_bpf == NULL) {
+#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING)
+ CURVNET_RESTORE();
+#endif
return (ENXIO);
+ }
bp = theywant->if_bpf;
@@ -1477,6 +1503,9 @@ bpf_setif(struct bpf_d *d, struct ifreq
BPFD_LOCK(d);
reset_d(d);
BPFD_UNLOCK(d);
+#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING)
+ CURVNET_RESTORE();
+#endif
return (0);
}
diff -drup src-org/sys/net/if.c src/sys/net/if.c
--- src-org/sys/net/if.c 2009-10-25 01:10:29.000000000 +0000
+++ src/sys/net/if.c 2009-11-11 12:46:02.000000000 +0000
@@ -813,6 +813,14 @@ if_detach_internal(struct ifnet *ifp, in
struct ifnet *iter;
int found = 0;
+ /*
+ * Detach from any vlan, bridge or lagg ifnets linked to us.
+ * A small though unlikely window for a race from here to ifp
+ * unlinking from ifnet list is possible, hence we repeat the
+ * procedure once again further bellow. XXX.
+ */
+ EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
+
IFNET_WLOCK();
TAILQ_FOREACH(iter, &V_ifnet, if_link)
if (iter == ifp) {
diff -drup src-org/sys/net/if_llatbl.c src/sys/net/if_llatbl.c
--- src-org/sys/net/if_llatbl.c 2009-10-25 01:10:29.000000000 +0000
+++ src/sys/net/if_llatbl.c 2009-11-11 12:53:49.000000000 +0000
@@ -57,11 +57,14 @@ __FBSDID("$FreeBSD: src/sys/net/if_llatb
MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables");
-static SLIST_HEAD(, lltable) lltables = SLIST_HEAD_INITIALIZER(lltables);
+static VNET_DEFINE(SLIST_HEAD(, lltable), lltables);
+#define V_lltables VNET(lltables)
extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *,
u_char *);
+static void vnet_lltable_init(void);
+
struct rwlock lltable_rwlock;
RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock");
@@ -75,7 +78,7 @@ lltable_sysctl_dumparp(int af, struct sy
int error = 0;
LLTABLE_RLOCK();
- SLIST_FOREACH(llt, &lltables, llt_link) {
+ SLIST_FOREACH(llt, &V_lltables, llt_link) {
if (llt->llt_af == af) {
error = llt->llt_dump(llt, wr);
if (error != 0)
@@ -157,7 +160,7 @@ lltable_free(struct lltable *llt)
KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
LLTABLE_WLOCK();
- SLIST_REMOVE(&lltables, llt, lltable, llt_link);
+ SLIST_REMOVE(&V_lltables, llt, lltable, llt_link);
LLTABLE_WUNLOCK();
for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
@@ -180,7 +183,7 @@ lltable_drain(int af)
register int i;
LLTABLE_RLOCK();
- SLIST_FOREACH(llt, &lltables, llt_link) {
+ SLIST_FOREACH(llt, &V_lltables, llt_link) {
if (llt->llt_af != af)
continue;
@@ -202,7 +205,7 @@ lltable_prefix_free(int af, struct socka
struct lltable *llt;
LLTABLE_RLOCK();
- SLIST_FOREACH(llt, &lltables, llt_link) {
+ SLIST_FOREACH(llt, &V_lltables, llt_link) {
if (llt->llt_af != af)
continue;
@@ -232,7 +235,7 @@ lltable_init(struct ifnet *ifp, int af)
LIST_INIT(&llt->lle_head[i]);
LLTABLE_WLOCK();
- SLIST_INSERT_HEAD(&lltables, llt, llt_link);
+ SLIST_INSERT_HEAD(&V_lltables, llt, llt_link);
LLTABLE_WUNLOCK();
return (llt);
@@ -302,7 +305,7 @@ lla_rt_output(struct rt_msghdr *rtm, str
/* XXX linked list may be too expensive */
LLTABLE_RLOCK();
- SLIST_FOREACH(llt, &lltables, llt_link) {
+ SLIST_FOREACH(llt, &V_lltables, llt_link) {
if (llt->llt_af == dst->sa_family &&
llt->llt_ifp == ifp)
break;
@@ -367,3 +370,12 @@ lla_rt_output(struct rt_msghdr *rtm, str
return (error);
}
+
+static void
+vnet_lltable_init()
+{
+
+ SLIST_INIT(&V_lltables);
+}
+VNET_SYSINIT(vnet_lltable_init, SI_SUB_PSEUDO, SI_ORDER_FIRST, vnet_lltable_init, NULL);
+
diff -drup src-org/sys/net/if_vlan.c src/sys/net/if_vlan.c
--- src-org/sys/net/if_vlan.c 2009-10-25 01:10:29.000000000 +0000
+++ src/sys/net/if_vlan.c 2009-11-11 12:46:02.000000000 +0000
@@ -1359,6 +1359,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd
error = copyin(ifr->ifr_data, &vlr, sizeof(vlr));
if (error)
break;
+#ifdef VIMAGE
+ if (ifp->if_home_vnet != ifp->if_vnet) {
+ error = EPERM;
+ break;
+ }
+#endif
if (vlr.vlr_parent[0] == '\0') {
vlan_unconfig(ifp);
break;
@@ -1386,6 +1392,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd
case SIOCGETVLAN:
bzero(&vlr, sizeof(vlr));
+#ifdef VIMAGE
+ if (ifp->if_home_vnet != ifp->if_vnet) {
+ error = EPERM;
+ break;
+ }
+#endif
VLAN_LOCK();
if (TRUNK(ifv) != NULL) {
strlcpy(vlr.vlr_parent, PARENT(ifv)->if_xname,
diff -drup src-org/sys/netgraph/ng_bridge.c src/sys/netgraph/ng_bridge.c
--- src-org/sys/netgraph/ng_bridge.c 2009-10-25 01:10:29.000000000 +0000
+++ src/sys/netgraph/ng_bridge.c 2009-11-11 12:46:02.000000000 +0000
@@ -105,6 +105,7 @@ struct ng_bridge_private {
u_int numBuckets; /* num buckets in table */
u_int hashMask; /* numBuckets - 1 */
int numLinks; /* num connected links */
+ int persistent; /* can exist w/o any hooks */
struct callout timer; /* one second periodic timer */
};
typedef struct ng_bridge_private *priv_p;
@@ -345,13 +346,13 @@ static int
ng_bridge_newhook(node_p node, hook_p hook, const char *name)
{
const priv_p priv = NG_NODE_PRIVATE(node);
+ int linkNum = -1;
/* Check for a link hook */
if (strncmp(name, NG_BRIDGE_HOOK_LINK_PREFIX,
strlen(NG_BRIDGE_HOOK_LINK_PREFIX)) == 0) {
const char *cp;
char *eptr;
- u_long linkNum;
cp = name + strlen(NG_BRIDGE_HOOK_LINK_PREFIX);
if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0'))
@@ -359,6 +360,12 @@ ng_bridge_newhook(node_p node, hook_p ho
linkNum = strtoul(cp, &eptr, 10);
if (*eptr != '\0' || linkNum >= NG_BRIDGE_MAX_LINKS)
return (EINVAL);
+ } else if (strcmp(name, "anchor") == 0) {
+ linkNum = 0;
+ priv->persistent = 1;
+ }
+
+ if (linkNum >= 0 ) {
if (priv->links[linkNum] != NULL)
return (EISCONN);
priv->links[linkNum] = malloc(sizeof(*priv->links[linkNum]),
@@ -366,7 +373,7 @@ ng_bridge_newhook(node_p node, hook_p ho
if (priv->links[linkNum] == NULL)
return (ENOMEM);
priv->links[linkNum]->hook = hook;
- NG_HOOK_SET_PRIVATE(hook, (void *)linkNum);
+ NG_HOOK_SET_PRIVATE(hook, (void *)(intptr_t)linkNum);
priv->numLinks++;
return (0);
}
@@ -799,7 +806,8 @@ ng_bridge_disconnect(hook_p hook)
/* If no more hooks, go away */
if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
- && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
+ && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))
+ && !priv->persistent) {
ng_rmnode_self(NG_HOOK_NODE(hook));
}
return (0);
diff -drup src-org/sys/netgraph/ng_hub.c src/sys/netgraph/ng_hub.c
--- src-org/sys/netgraph/ng_hub.c 2009-10-25 01:10:29.000000000 +0000
+++ src/sys/netgraph/ng_hub.c 2009-11-11 12:46:02.000000000 +0000
@@ -37,6 +37,7 @@
#include <netgraph/netgraph.h>
static ng_constructor_t ng_hub_constructor;
+static ng_newhook_t ng_hub_newhook;
static ng_rcvdata_t ng_hub_rcvdata;
static ng_disconnect_t ng_hub_disconnect;
@@ -44,6 +45,7 @@ static struct ng_type ng_hub_typestruct
.version = NG_ABI_VERSION,
.name = NG_HUB_NODE_TYPE,
.constructor = ng_hub_constructor,
+ .newhook = ng_hub_newhook,
.rcvdata = ng_hub_rcvdata,
.disconnect = ng_hub_disconnect,
};
@@ -57,6 +59,14 @@ ng_hub_constructor(node_p node)
return (0);
}
+static int
+ng_hub_newhook(node_p node, hook_p hook, const char *name)
+{
+ if (strcmp(name, "anchor") == 0)
+ node->nd_private = (void *) 1;
+ return (0);
+}
+
static int
ng_hub_rcvdata(hook_p hook, item_p item)
{
@@ -94,7 +104,7 @@ ng_hub_disconnect(hook_p hook)
{
if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 &&
- NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))
+ NG_NODE_IS_VALID(NG_HOOK_NODE(hook)) && !hook->hk_node->nd_private)
ng_rmnode_self(NG_HOOK_NODE(hook));
return (0);
}