Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/librumphijack A simple dup2-enforced affine transformati...
details: https://anonhg.NetBSD.org/src/rev/0ac88833bf11
branches: trunk
changeset: 762785:0ac88833bf11
user: pooka <pooka%NetBSD.org@localhost>
date: Mon Feb 28 19:57:36 2011 +0000
description:
A simple dup2-enforced affine transformation isn't enough when
dealing with dup2() from a rump kernel fd to a host kernel fd.
Consider:
s1 = socket();
s2 = socket();
dup2(s2, 0);
Instead, maintain a real mapping table (and get on my knees and
pray i don't have to touch this hair-splitting code ever again).
Apparently bourne shell scripts from a rump kernel fs work now
(sh script.sh; ./script.sh doesn't work for obvious "IT'S THE WRONG
FS NAMESPACE" reasons). No test regressions either, so I'm a
happy camper.
diffstat:
lib/librumphijack/hijack.c | 265 +++++++++++++++++++++++++++++++-------------
1 files changed, 188 insertions(+), 77 deletions(-)
diffs (truncated from 453 to 300 lines):
diff -r f2486c08d203 -r 0ac88833bf11 lib/librumphijack/hijack.c
--- a/lib/librumphijack/hijack.c Mon Feb 28 18:28:20 2011 +0000
+++ b/lib/librumphijack/hijack.c Mon Feb 28 19:57:36 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hijack.c,v 1.70 2011/02/27 11:32:12 pooka Exp $ */
+/* $NetBSD: hijack.c,v 1.71 2011/02/28 19:57:36 pooka Exp $ */
/*-
* Copyright (c) 2011 Antti Kantee. All Rights Reserved.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: hijack.c,v 1.70 2011/02/27 11:32:12 pooka Exp $");
+__RCSID("$NetBSD: hijack.c,v 1.71 2011/02/28 19:57:36 pooka Exp $");
#define __ssp_weak_name(fun) _hijack_ ## fun
@@ -232,23 +232,89 @@
} syscalls[DUALCALL__NUM];
#define GETSYSCALL(which, name) syscalls[DUALCALL_##name].bs_##which
-pid_t (*host_fork)(void);
-int (*host_daemon)(int, int);
-int (*host_execve)(const char *, char *const[], char *const[]);
-void * (*host_mmap)(void *, size_t, int, int, int, off_t);
+static pid_t (*host_fork)(void);
+static int (*host_daemon)(int, int);
+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 *);
+
+/*
+ * Maintain a mapping table for the usual dup2 suspects.
+ */
+/* note: you cannot change this without editing the env-passing code */
+#define DUP2HIGH 2
+static uint32_t dup2vec[DUP2HIGH+1];
+#define DUP2BIT (1<<31)
+#define DUP2ALIAS (1<<30)
+#define DUP2FDMASK ((1<<30)-1)
+
+static bool
+isdup2d(int fd)
+{
+
+ return fd <= DUP2HIGH && fd >= 0 && dup2vec[fd] & DUP2BIT;
+}
+
+static int
+mapdup2(int hostfd)
+{
+
+ _DIAGASSERT(isdup2d(hostfd));
+ return dup2vec[hostfd] & DUP2FDMASK;
+}
+
+static int
+unmapdup2(int rumpfd)
+{
+ int i;
-/* ok, we need *two* bits per dup2'd fd to track fd+HIJACKOFF aliases */
-static uint32_t dup2mask;
-#define ISDUP2D(fd) (((fd) < 16) && (1<<(fd) & dup2mask))
-#define SETDUP2(fd) \
- do { if ((fd) < 16) dup2mask |= (1<<(fd)); } while (/*CONSTCOND*/0)
-#define CLRDUP2(fd) \
- do { if ((fd) < 16) dup2mask &= ~(1<<(fd)); } while (/*CONSTCOND*/0)
-#define ISDUP2ALIAS(fd) (((fd) < 16) && (1<<((fd)+16) & dup2mask))
-#define SETDUP2ALIAS(fd) \
- do { if ((fd) < 16) dup2mask |= (1<<((fd)+16)); } while (/*CONSTCOND*/0)
-#define CLRDUP2ALIAS(fd) \
- do { if ((fd) < 16) dup2mask &= ~(1<<((fd)+16)); } while (/*CONSTCOND*/0)
+ for (i = 0; i <= DUP2HIGH; i++) {
+ if (dup2vec[i] & DUP2BIT && (dup2vec[i] & DUP2FDMASK) == rumpfd)
+ return i;
+ }
+ return -1;
+}
+
+static void
+setdup2(int hostfd, int rumpfd)
+{
+
+ if (hostfd > DUP2HIGH) {
+ _DIAGASSERT(0);
+ return;
+ }
+
+ dup2vec[hostfd] = DUP2BIT | DUP2ALIAS | rumpfd;
+}
+
+static void
+clrdup2(int hostfd)
+{
+
+ if (hostfd > DUP2HIGH) {
+ _DIAGASSERT(0);
+ return;
+ }
+
+ dup2vec[hostfd] = 0;
+}
+
+static bool
+killdup2alias(int rumpfd)
+{
+ int hostfd;
+
+ if ((hostfd = unmapdup2(rumpfd)) == -1)
+ return false;
+
+ if (dup2vec[hostfd] & DUP2ALIAS) {
+ dup2vec[hostfd] &= ~DUP2ALIAS;
+ return true;
+ }
+ return false;
+}
//#define DEBUGJACK
#ifdef DEBUGJACK
@@ -258,7 +324,7 @@
{
va_list ap;
- if (ISDUP2D(STDERR_FILENO))
+ if (isdup2d(STDERR_FILENO))
return;
va_start(ap, fmt);
@@ -266,6 +332,28 @@
va_end(ap);
}
+static const char *
+whichfd(int fd)
+{
+
+ if (fd == -1)
+ return "-1";
+ else if (fd_isrump(fd))
+ return "rump";
+ else
+ return "host";
+}
+
+static const char *
+whichpath(const char *path)
+{
+
+ if (path_isrump(path))
+ return "rump";
+ else
+ return "host";
+}
+
#else
#define DPRINTF(x)
#endif
@@ -275,7 +363,7 @@
{ \
type (*fun) proto; \
\
- DPRINTF(("%s -> %d\n", __STRING(name), fd)); \
+ DPRINTF(("%s -> %d (%s)\n", __STRING(name), fd, whichfd(fd))); \
if (fd_isrump(fd)) { \
fun = syscalls[rcname].bs_rump; \
fd = fd_host2rump(fd); \
@@ -291,7 +379,8 @@
{ \
type (*fun) proto; \
\
- DPRINTF(("%s -> %s\n", __STRING(name), path)); \
+ DPRINTF(("%s -> %s (%s)\n", __STRING(name), path, \
+ whichpath(path))); \
if (path_isrump(path)) { \
fun = syscalls[rcname].bs_rump; \
path = path_host2rump(path); \
@@ -500,9 +589,13 @@
}
}
- if (getenv_r("RUMPHIJACK__DUP2MASK", buf, sizeof(buf)) == 0) {
- dup2mask = strtoul(buf, NULL, 10);
- unsetenv("RUMPHIJACK__DUP2MASK");
+ if (getenv_r("RUMPHIJACK__DUP2INFO", buf, sizeof(buf)) == 0) {
+ if (sscanf(buf, "%u,%u,%u",
+ &dup2vec[0], &dup2vec[1], &dup2vec[2]) != 3) {
+ warnx("invalid dup2mask: %s", buf);
+ memset(dup2vec, 0, sizeof(dup2vec));
+ }
+ unsetenv("RUMPHIJACK__DUP2INFO");
}
if (getenv_r("RUMPHIJACK__PWDINRUMP", buf, sizeof(buf)) == 0) {
pwdinrump = true;
@@ -510,35 +603,47 @@
}
}
-/* XXX: need runtime selection. low for now due to FD_SETSIZE */
+/* Need runtime selection. low for now due to FD_SETSIZE */
#define HIJACK_FDOFF 128
+
static int
fd_rump2host(int fd)
{
if (fd == -1)
return fd;
+ return fd + HIJACK_FDOFF;
+}
- if (!ISDUP2D(fd))
- fd += HIJACK_FDOFF;
+static int
+fd_rump2host_withdup(int fd)
+{
+ int hfd;
- return fd;
+ _DIAGASSERT(fd != -1);
+ hfd = unmapdup2(fd);
+ if (hfd != -1) {
+ _DIAGASSERT(hfd <= DUP2HIGH);
+ return hfd;
+ }
+ return fd_rump2host(fd);
}
static int
fd_host2rump(int fd)
{
- if (!ISDUP2D(fd))
- fd -= HIJACK_FDOFF;
- return fd;
+ if (!isdup2d(fd))
+ return fd - HIJACK_FDOFF;
+ else
+ return mapdup2(fd);
}
static bool
fd_isrump(int fd)
{
- return ISDUP2D(fd) || fd >= HIJACK_FDOFF;
+ return isdup2d(fd) || fd >= HIJACK_FDOFF;
}
#define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_FDOFF)
@@ -614,7 +719,7 @@
int (*op_close)(int) = GETSYSCALL(host, CLOSE);
int ofd, i;
- for (i = 1; ISDUP2D(fd); i++) {
+ for (i = 1; isdup2d(fd); i++) {
ofd = fd;
fd = op_fcntl(ofd, F_DUPFD, i);
op_close(ofd);
@@ -631,6 +736,8 @@
va_list ap;
int fd;
+ DPRINTF(("open -> %s (%s)\n", path, whichpath(path)));
+
if (path_isrump(path)) {
path = path_host2rump(path);
op_open = GETSYSCALL(rump, OPEN);
@@ -648,6 +755,8 @@
fd = fd_rump2host(fd);
else
fd = fd_dupgood(fd);
+
+ DPRINTF(("open <- %d (%s)\n", fd, whichfd(fd)));
return fd;
}
@@ -854,13 +963,12 @@
return rv;
}
-#include <syslog.h>
int
fcntl(int fd, int cmd, ...)
{
int (*op_fcntl)(int, int, ...);
va_list ap;
- int rv, minfd, i;
+ int rv, minfd, i, maxdup2;
DPRINTF(("fcntl -> %d (cmd %d)\n", fd, cmd));
@@ -890,23 +998,21 @@
/*
* Additionally, we want to do a rump closem, but only
Home |
Main Index |
Thread Index |
Old Index