Module Name:    src
Committed By:   pooka
Date:           Tue Mar  8 20:59:02 UTC 2011

Modified Files:
        src/lib/librumphijack: hijack.c rumphijack.3

Log Message:
Add ``blanket''.  It acts like path, except that the prefix does
_not_ get removed if the call goes to the rump namespace.

So, now it's possible to use e.g. tcpdump (and most other utilities
which hardcore a /dev pathname) on a rump kernel:

golem> setenv RUMPHIJACK blanket=/dev/bpf
golem> tcpdump -n -i virt0
tcpdump: WARNING: SIOCGIFADDR: virt0: Device not configured
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on virt0, link-type EN10MB (Ethernet), capture size 96 bytes
21:55:38.925596 IP 192.168.2.101 > 204.152.190.12: ICMP echo request, id 47811, 
seq 0, length 64
21:55:39.095596 IP 204.152.190.12 > 192.168.2.101: ICMP echo reply, id 47811, 
seq 0, length 64

(if you additionally set socket=all in RUMPHIJACK, tcpdump doesn't
whine about the "not configured" interface)


To generate a diff of this commit:
cvs rdiff -u -r1.74 -r1.75 src/lib/librumphijack/hijack.c
cvs rdiff -u -r1.5 -r1.6 src/lib/librumphijack/rumphijack.3

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/librumphijack/hijack.c
diff -u src/lib/librumphijack/hijack.c:1.74 src/lib/librumphijack/hijack.c:1.75
--- src/lib/librumphijack/hijack.c:1.74	Tue Mar  1 10:54:06 2011
+++ src/lib/librumphijack/hijack.c	Tue Mar  8 20:59:01 2011
@@ -1,4 +1,4 @@
-/*      $NetBSD: hijack.c,v 1.74 2011/03/01 10:54:06 pooka Exp $	*/
+/*      $NetBSD: hijack.c,v 1.75 2011/03/08 20:59:01 pooka Exp $	*/
 
 /*-
  * Copyright (c) 2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: hijack.c,v 1.74 2011/03/01 10:54:06 pooka Exp $");
+__RCSID("$NetBSD: hijack.c,v 1.75 2011/03/08 20:59:01 pooka Exp $");
 
 #define __ssp_weak_name(fun) _hijack_ ## fun
 
@@ -237,8 +237,16 @@
 static int	(*host_execve)(const char *, char *const[], char *const[]);
 static void *	(*host_mmap)(void *, size_t, int, int, int, off_t);
 
-static bool	fd_isrump(int);
-static bool	path_isrump(const char *);
+/*
+ * This tracks if our process is in a subdirectory of /rump.
+ * It's preserved over exec.
+ */
+static bool pwdinrump;
+
+enum pathtype { PATH_HOST, PATH_RUMP, PATH_RUMPBLANKET };
+
+static bool		fd_isrump(int);
+static enum pathtype	path_isrump(const char *);
 
 /*
  * Maintain a mapping table for the usual dup2 suspects.
@@ -381,12 +389,14 @@
 type name args								\
 {									\
 	type (*fun) proto;						\
+	enum pathtype pt;						\
 									\
 	DPRINTF(("%s -> %s (%s)\n", __STRING(name), path,		\
 	    whichpath(path)));						\
-	if (path_isrump(path)) {					\
+	if ((pt = path_isrump(path)) != PATH_HOST) {			\
 		fun = syscalls[rcname].bs_rump;				\
-		path = path_host2rump(path);				\
+		if (pt == PATH_RUMP)					\
+			path = path_host2rump(path);			\
 	} else {							\
 		fun = syscalls[rcname].bs_host;				\
 	}								\
@@ -395,12 +405,6 @@
 }
 
 /*
- * This tracks if our process is in a subdirectory of /rump.
- * It's preserved over exec.
- */
-static bool pwdinrump = false;
-
-/*
  * These variables are set from the RUMPHIJACK string and control
  * which operations can product rump kernel file descriptors.
  * This should be easily extendable for future needs.
@@ -483,12 +487,46 @@
 	rumpprefixlen = strlen(rumpprefix);
 }
 
+static struct blanket {
+	const char *pfx;
+	size_t len;
+} *blanket;
+static int nblanket;
+
+static void
+blanketparser(char *buf)
+{
+	char *p, *l;
+	int i;
+
+	for (nblanket = 0, p = buf; p; p = strchr(p+1, ':'), nblanket++)
+		continue;
+
+	blanket = malloc(nblanket * sizeof(*blanket));
+	if (blanket == NULL)
+		err(1, "alloc blanket %d", nblanket);
+
+	for (p = strtok_r(buf, ":", &l), i = 0; p;
+	    p = strtok_r(NULL, ":", &l), i++) {
+		blanket[i].pfx = strdup(p);
+		if (blanket[i].pfx == NULL)
+			err(1, "strdup blanket");
+		blanket[i].len = strlen(p);
+
+		if (blanket[i].len == 0 || *blanket[i].pfx != '/')
+			errx(1, "invalid blanket specifier %s", p);
+		if (*(blanket[i].pfx + blanket[i].len-1) == '/')
+			errx(1, "invalid blanket specifier %s", p);
+	}
+}
+
 static struct {
 	void (*parsefn)(char *);
 	const char *name;
 } hijackparse[] = {
 	{ sockparser, "socket" },
 	{ pathparser, "path" },
+	{ blanketparser, "blanket" },
 	{ NULL, NULL },
 };
 
@@ -651,19 +689,28 @@
 
 #define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_FDOFF)
 
-static bool
+static enum pathtype
 path_isrump(const char *path)
 {
+	int i;
 
-	if (rumpprefix == NULL)
-		return false;
+	if (rumpprefix == NULL && nblanket == 0)
+		return PATH_HOST;
 
 	if (*path == '/') {
-		if (strncmp(path, rumpprefix, rumpprefixlen) == 0)
-			return true;
-		return false;
+		if (rumpprefix) {
+			if (strncmp(path, rumpprefix, rumpprefixlen) == 0) {
+				return PATH_RUMP;
+			}
+		}
+		for (i = 0; i < nblanket; i++) {
+			if (strncmp(path, blanket[i].pfx, blanket[i].len) == 0)
+				return PATH_RUMPBLANKET;
+		}
+
+		return PATH_HOST;
 	} else {
-		return pwdinrump;
+		return pwdinrump ? PATH_RUMP : PATH_HOST;
 	}
 }
 
@@ -737,12 +784,14 @@
 	int (*op_open)(const char *, int, ...);
 	bool isrump;
 	va_list ap;
+	enum pathtype pt;
 	int fd;
 
 	DPRINTF(("open -> %s (%s)\n", path, whichpath(path)));
 
-	if (path_isrump(path)) {
-		path = path_host2rump(path);
+	if ((pt = path_isrump(path)) != PATH_HOST) {
+		if (pt == PATH_RUMP)
+			path = path_host2rump(path);
 		op_open = GETSYSCALL(rump, OPEN);
 		isrump = true;
 	} else {
@@ -767,25 +816,20 @@
 chdir(const char *path)
 {
 	int (*op_chdir)(const char *);
-	bool isrump;
+	enum pathtype pt;
 	int rv;
 
-	if (path_isrump(path)) {
+	if ((pt = path_isrump(path)) != PATH_HOST) {
 		op_chdir = GETSYSCALL(rump, CHDIR);
-		isrump = true;
-		path = path_host2rump(path);
+		if (pt == PATH_RUMP)
+			path = path_host2rump(path);
 	} else {
 		op_chdir = GETSYSCALL(host, CHDIR);
-		isrump = false;
 	}
 
 	rv = op_chdir(path);
-	if (rv == 0) {
-		if (isrump)
-			pwdinrump = true;
-		else
-			pwdinrump = false;
-	}
+	if (rv == 0)
+		pwdinrump = pt != PATH_HOST;
 
 	return rv;
 }
@@ -808,10 +852,7 @@
 
 	rv = op_fchdir(fd);
 	if (rv == 0) {
-		if (isrump)
-			pwdinrump = true;
-		else
-			pwdinrump = false;
+		pwdinrump = isrump;
 	}
 
 	return rv;
@@ -821,12 +862,11 @@
 __getcwd(char *bufp, size_t len)
 {
 	int (*op___getcwd)(char *, size_t);
+	size_t prefixgap;
+	bool iamslash;
 	int rv;
 
-	if (pwdinrump) {
-		size_t prefixgap;
-		bool iamslash;
-
+	if (pwdinrump && rumpprefix) {
 		if (rumpprefix[rumpprefixlen-1] == '/')
 			iamslash = true;
 		else
@@ -856,30 +896,37 @@
 		/* don't append extra slash in the purely-slash case */
 		if (rv == 2 && !iamslash)
 			bufp[rumpprefixlen] = '\0';
-
-		return rv;
+	} else if (pwdinrump) {
+		/* assume blanket.  we can't provide a prefix here */
+		op___getcwd = GETSYSCALL(rump, __GETCWD);
+		rv = op___getcwd(bufp, len);
 	} else {
 		op___getcwd = GETSYSCALL(host, __GETCWD);
-		return op___getcwd(bufp, len);
+		rv = op___getcwd(bufp, len);
 	}
+
+	return rv;
 }
 
 int
 rename(const char *from, const char *to)
 {
 	int (*op_rename)(const char *, const char *);
+	enum pathtype ptf, ptt;
 
-	if (path_isrump(from)) {
-		if (!path_isrump(to)) {
+	if ((ptf = path_isrump(from)) != PATH_HOST) {
+		if ((ptt = path_isrump(to)) == PATH_HOST) {
 			errno = EXDEV;
 			return -1;
 		}
 
-		from = path_host2rump(from);
-		to = path_host2rump(to);
+		if (ptf == PATH_RUMP)
+			from = path_host2rump(from);
+		if (ptt == PATH_RUMP)
+			to = path_host2rump(to);
 		op_rename = GETSYSCALL(rump, RENAME);
 	} else {
-		if (path_isrump(to)) {
+		if (path_isrump(to) != PATH_HOST) {
 			errno = EXDEV;
 			return -1;
 		}

Index: src/lib/librumphijack/rumphijack.3
diff -u src/lib/librumphijack/rumphijack.3:1.5 src/lib/librumphijack/rumphijack.3:1.6
--- src/lib/librumphijack/rumphijack.3:1.5	Sun Feb 20 14:21:04 2011
+++ src/lib/librumphijack/rumphijack.3	Tue Mar  8 20:59:01 2011
@@ -1,4 +1,4 @@
-.\"     $NetBSD: rumphijack.3,v 1.5 2011/02/20 14:21:04 pooka Exp $
+.\"     $NetBSD: rumphijack.3,v 1.6 2011/03/08 20:59:01 pooka Exp $
 .\"
 .\" Copyright (c) 2011 Antti Kantee.  All rights reserved.
 .\"
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd February 18, 2011
+.Dd March 8, 2011
 .Dt RUMPHIJACK 3
 .Os
 .Sh NAME
@@ -53,7 +53,7 @@
 .Dq name=value
 tuples.
 The possible lefthandside names are:
-.Bl -tag -width xxsocketxx
+.Bl -tag -width xxblanketxx
 .It Dq path
 Pathname-based system calls are hijacked if the path the system
 call is directed to resides under
@@ -64,6 +64,45 @@
 This also implies that neither
 .Dq ..
 nor symbolic links will cause the namespace to be switched.
+.It Dq blanket
+A colon-separated list of rump path prefixes.
+This acts almost like
+.Dq path
+with the difference that the prefix does not get removed when
+passing the path to the rump kernel.
+For example, if
+.Dq path
+is
+.Pa /rump ,
+accessing
+.Pa /rump/dev/bpf
+will cause
+.Pa /dev/bpf
+to be accessed in the rump kernel.
+In contrast, if
+.Dq blanket
+contains
+.Pa /dev/bpf ,
+accessing
+.Pa /dev/bpf
+will cause an access to
+.Pa /dev/bpf
+in the rump kernel.
+.Pp
+In case the current working directory is changed to a blanketed
+directory, the current working directory will still be reported
+with the rump prefix, if available.
+Note, though, that some shells cache the directory and maybe report
+something else.
+In case no rump path prefix has been configured, the raw rump
+directory is reported.
+.Pp
+It is recommended to supply blanketed pathnames as specific as
+possible, i.e. use
+.Pa /dev/bpf
+instead of
+.Pa /dev
+unless necessary to do otherwise.
 .It Dq socket
 The specifier
 .Ar value

Reply via email to