Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/librumphijack Hijack pathname-based system calls. Now a...



details:   https://anonhg.NetBSD.org/src/rev/835c5bcbf2a3
branches:  trunk
changeset: 762196:835c5bcbf2a3
user:      pooka <pooka%NetBSD.org@localhost>
date:      Thu Feb 17 12:23:58 2011 +0000

description:
Hijack pathname-based system calls.  Now all paths starting with
/rump are hijacked to go to the rump server.  So you can e.g. start
a hijacked shell and cd to /rump:

$ cd /rump
$ pwd
/rump
$ ls -l dev/null
crwxr-xr-x  1 root  wheel  2, 2 Feb 17 12:35 dev/null
$ ls -l /dev/null
crw-rw-rw-  1 root  wheel  2, 2 Dec 22  2009 /dev/null
$ chmod 0 /dev/null
chmod: /dev/null: Operation not permitted
$ chmod 0 dev/null
$ ls -l /rump/dev/null
c---------  1 root  wheel  2, 2 Feb 17 12:35 /rump/dev/null

(of course the rump server must have vfs loaded for that to work)

diffstat:

 lib/librumphijack/hijack.c |  383 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 373 insertions(+), 10 deletions(-)

diffs (truncated from 496 to 300 lines):

diff -r 704178915b7d -r 835c5bcbf2a3 lib/librumphijack/hijack.c
--- a/lib/librumphijack/hijack.c        Thu Feb 17 12:08:46 2011 +0000
+++ b/lib/librumphijack/hijack.c        Thu Feb 17 12:23:58 2011 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: hijack.c,v 1.44 2011/02/16 19:26:58 pooka Exp $       */
+/*      $NetBSD: hijack.c,v 1.45 2011/02/17 12:23:58 pooka Exp $       */
 
 /*-
  * Copyright (c) 2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: hijack.c,v 1.44 2011/02/16 19:26:58 pooka Exp $");
+__RCSID("$NetBSD: hijack.c,v 1.45 2011/02/17 12:23:58 pooka Exp $");
 
 #define __ssp_weak_name(fun) _hijack_ ## fun
 
@@ -36,6 +36,7 @@
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/poll.h>
+#include <sys/statvfs.h>
 
 #include <rump/rumpclient.h>
 #include <rump/rump_syscalls.h>
@@ -70,6 +71,20 @@
        DUALCALL_CLOSE,
        DUALCALL_POLLTS,
        DUALCALL_KEVENT,
+       DUALCALL_STAT, DUALCALL_LSTAT, DUALCALL_FSTAT,
+       DUALCALL_CHMOD, DUALCALL_LCHMOD, DUALCALL_FCHMOD,
+       DUALCALL_CHOWN, DUALCALL_LCHOWN, DUALCALL_FCHOWN,
+       DUALCALL_OPEN,
+       DUALCALL_STATVFS1, DUALCALL_FSTATVFS1,
+       DUALCALL_CHDIR, DUALCALL_FCHDIR,
+       DUALCALL_LSEEK,
+       DUALCALL_GETDENTS,
+       DUALCALL_UNLINK, DUALCALL_SYMLINK, DUALCALL_READLINK,
+       DUALCALL_RENAME,
+       DUALCALL_MKDIR, DUALCALL_RMDIR,
+       DUALCALL_UTIMES, DUALCALL_LUTIMES, DUALCALL_FUTIMES,
+       DUALCALL_TRUNCATE, DUALCALL_FTRUNCATE,
+       DUALCALL_FSYNC, DUALCALL_FSYNC_RANGE,
        DUALCALL__NUM
 };
 
@@ -84,12 +99,25 @@
 #define REALSELECT select
 #define REALPOLLTS pollts
 #define REALKEVENT kevent
+#define REALSTAT __stat30
+#define REALLSTAT __lstat30
+#define REALFSTAT __fstat30
+#define REALUTIMES utimes
+#define REALLUTIMES lutimes
+#define REALFUTIMES futimes
 #else
 #define REALSELECT _sys___select50
 #define REALPOLLTS _sys___pollts50
 #define REALKEVENT _sys___kevent50
+#define REALSTAT __stat50
+#define REALLSTAT __lstat50
+#define REALFSTAT __fstat50
+#define REALUTIMES __utimes50
+#define REALLUTIMES __lutimes50
+#define REALFUTIMES __futimes50
 #endif
 #define REALREAD _sys_read
+#define REALGETDENTS __getdents30
 
 int REALSELECT(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 int REALPOLLTS(struct pollfd *, nfds_t,
@@ -97,6 +125,13 @@
 int REALKEVENT(int, const struct kevent *, size_t, struct kevent *, size_t,
               const struct timespec *);
 ssize_t REALREAD(int, void *, size_t);
+int REALSTAT(const char *, struct stat *);
+int REALLSTAT(const char *, struct stat *);
+int REALFSTAT(int, struct stat *);
+int REALGETDENTS(int, char *, size_t);
+int REALUTIMES(const char *, const struct timeval [2]);
+int REALLUTIMES(const char *, const struct timeval [2]);
+int REALFUTIMES(int, const struct timeval [2]);
 
 #define S(a) __STRING(a)
 struct sysnames {
@@ -128,6 +163,35 @@
        { DUALCALL_CLOSE,       "close",        RSYS_NAME(CLOSE)        },
        { DUALCALL_POLLTS,      S(REALPOLLTS),  RSYS_NAME(POLLTS)       },
        { DUALCALL_KEVENT,      S(REALKEVENT),  RSYS_NAME(KEVENT)       },
+       { DUALCALL_STAT,        S(REALSTAT),    RSYS_NAME(STAT)         },
+       { DUALCALL_LSTAT,       S(REALLSTAT),   RSYS_NAME(LSTAT)        },
+       { DUALCALL_FSTAT,       S(REALFSTAT),   RSYS_NAME(FSTAT)        },
+       { DUALCALL_CHOWN,       "chown",        RSYS_NAME(CHOWN)        },
+       { DUALCALL_LCHOWN,      "lchown",       RSYS_NAME(LCHOWN)       },
+       { DUALCALL_FCHOWN,      "fchown",       RSYS_NAME(FCHOWN)       },
+       { DUALCALL_CHMOD,       "chmod",        RSYS_NAME(CHMOD)        },
+       { DUALCALL_LCHMOD,      "lchmod",       RSYS_NAME(LCHMOD)       },
+       { DUALCALL_FCHMOD,      "fchmod",       RSYS_NAME(FCHMOD)       },
+       { DUALCALL_UTIMES,      S(REALUTIMES),  RSYS_NAME(UTIMES)       },
+       { DUALCALL_LUTIMES,     S(REALLUTIMES), RSYS_NAME(LUTIMES)      },
+       { DUALCALL_FUTIMES,     S(REALFUTIMES), RSYS_NAME(FUTIMES)      },
+       { DUALCALL_OPEN,        "open",         RSYS_NAME(OPEN)         },
+       { DUALCALL_STATVFS1,    "statvfs1",     RSYS_NAME(STATVFS1)     },
+       { DUALCALL_FSTATVFS1,   "fstatvfs1",    RSYS_NAME(FSTATVFS1)    },
+       { DUALCALL_CHDIR,       "chdir",        RSYS_NAME(CHDIR)        },
+       { DUALCALL_FCHDIR,      "fchdir",       RSYS_NAME(FCHDIR)       },
+       { DUALCALL_LSEEK,       "lseek",        RSYS_NAME(LSEEK)        },
+       { DUALCALL_GETDENTS,    "__getdents30", RSYS_NAME(GETDENTS)     },
+       { DUALCALL_UNLINK,      "unlink",       RSYS_NAME(UNLINK)       },
+       { DUALCALL_SYMLINK,     "symlink",      RSYS_NAME(SYMLINK)      },
+       { DUALCALL_READLINK,    "readlink",     RSYS_NAME(READLINK)     },
+       { DUALCALL_RENAME,      "rename",       RSYS_NAME(RENAME)       },
+       { DUALCALL_MKDIR,       "mkdir",        RSYS_NAME(MKDIR)        },
+       { DUALCALL_RMDIR,       "rmdir",        RSYS_NAME(RMDIR)        },
+       { DUALCALL_TRUNCATE,    "truncate",     RSYS_NAME(TRUNCATE)     },
+       { DUALCALL_FTRUNCATE,   "ftruncate",    RSYS_NAME(FTRUNCATE)    },
+       { DUALCALL_FSYNC,       "fsync",        RSYS_NAME(FSYNC)        },
+       { DUALCALL_FSYNC_RANGE, "fsync_range",  RSYS_NAME(FSYNC_RANGE)  },
 };
 #undef S
 
@@ -184,6 +248,22 @@
        return fun vars;                                                \
 }
 
+#define PATHCALL(type, name, rcname, args, proto, vars)                        \
+type name args                                                         \
+{                                                                      \
+       type (*fun) proto;                                              \
+                                                                       \
+       DPRINTF(("%s -> %s\n", __STRING(name), path));                  \
+       if (path_isrump(path)) {                                        \
+               fun = syscalls[rcname].bs_rump;                         \
+               path = path_host2rump(path);                            \
+       } else {                                                        \
+               fun = syscalls[rcname].bs_host;                         \
+       }                                                               \
+                                                                       \
+       return fun vars;                                                \
+}
+
 /*
  * This is called from librumpclient in case of LD_PRELOAD.
  * It ensures correct RTLD_NEXT.
@@ -208,6 +288,8 @@
        return (void *)rv;
 }
 
+static int pwdinrump = 0;
+
 /* low calorie sockets? */
 static bool hostlocalsockets = true;
 
@@ -278,6 +360,11 @@
 
        if (getenv_r("RUMPHIJACK__DUP2MASK", buf, sizeof(buf)) == 0) {
                dup2mask = strtoul(buf, NULL, 10);
+               unsetenv("RUMPHIJACK__DUP2MASK");
+       }
+       if (getenv_r("RUMPHIJACK__PWDINRUMP", buf, sizeof(buf)) == 0) {
+               pwdinrump = strtoul(buf, NULL, 10);
+               unsetenv("RUMPHIJACK__PWDINRUMP");
        }
 }
 
@@ -314,6 +401,37 @@
 
 #define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_FDOFF)
 
+#define RUMPPREFIX "/rump"
+static int
+path_isrump(const char *path)
+{
+
+       if (*path == '/') {
+               if (strncmp(path, RUMPPREFIX, sizeof(RUMPPREFIX)-1) == 0)
+                       return 1;
+               return 0;
+       } else {
+               return pwdinrump;
+       }
+}
+
+static const char *rootpath = "/";
+static const char *
+path_host2rump(const char *path)
+{
+       const char *rv;
+
+       if (*path == '/') {
+               rv = path + (sizeof(RUMPPREFIX)-1);
+               if (*rv == '\0')
+                       rv = rootpath;
+       } else {
+               rv = path;
+       }
+
+       return rv;
+}
+
 static int
 dodup(int oldd, int minfd)
 {
@@ -340,6 +458,86 @@
        return newd;
 }
 
+int
+open(const char *path, int flags, ...)
+{
+       int (*op_open)(const char *, int, ...);
+       bool isrump;
+       va_list ap;
+       int fd;
+
+       if (path_isrump(path)) {
+               path = path_host2rump(path);
+               op_open = GETSYSCALL(rump, OPEN);
+               isrump = true;
+       } else {
+               op_open = GETSYSCALL(host, OPEN);
+               isrump = false;
+       }
+
+       va_start(ap, flags);
+       fd = op_open(path, flags, va_arg(ap, mode_t));
+       va_end(ap);
+
+       if (isrump)
+               fd = fd_rump2host(fd);
+       return fd;
+}
+
+int
+chdir(const char *path)
+{
+       int (*op_chdir)(const char *);
+       bool isrump;
+       int rv;
+
+       if (path_isrump(path)) {
+               op_chdir = GETSYSCALL(rump, CHDIR);
+               isrump = true;
+               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;
+       }
+
+       return rv;
+}
+
+int
+fchdir(int fd)
+{
+       int (*op_fchdir)(int);
+       bool isrump;
+       int rv;
+
+       if (fd_isrump(fd)) {
+               op_fchdir = GETSYSCALL(rump, FCHDIR);
+               isrump = true;
+               fd = fd_host2rump(fd);
+       } else {
+               op_fchdir = GETSYSCALL(host, FCHDIR);
+               isrump = false;
+       }
+
+       rv = op_fchdir(fd);
+       if (rv == 0) {
+               if (isrump)
+                       pwdinrump = true;
+               else
+                       pwdinrump = false;
+       }
+
+       return rv;
+}
+
 int __socket30(int, int, int);
 int
 __socket30(int domain, int type, int protocol)
@@ -628,26 +826,56 @@
 {
        char buf[128];
        char *dup2str;
+       char *pwdinrumpstr;
        char **newenv;
        size_t nelem;
        int rv, sverrno;



Home | Main Index | Thread Index | Old Index