372 lines
11 KiB
Diff
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);
|
|
}
|