Source-Changes-HG archive

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

[src/trunk]: src/lib/librumphijack Add a bunch of process-wide hijack calls. ...



details:   https://anonhg.NetBSD.org/src/rev/e9619e7a8de6
branches:  trunk
changeset: 763058:e9619e7a8de6
user:      pooka <pooka%NetBSD.org@localhost>
date:      Wed Mar 09 15:03:18 2011 +0000

description:
Add a bunch of process-wide hijack calls.  Among other things, it's
now possible to use unmodified userspace binaries (rpcbind, mountd,
nfsd) to start a rump nfs service and mount file systems from it.

pain-rustique:42:~> mount
rumpfs on / type rumpfs (local)
10.1.1.1:/export on /mnt type nfs

diffstat:

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

diffs (truncated from 338 to 300 lines):

diff -r 92bb227cdeaf -r e9619e7a8de6 lib/librumphijack/hijack.c
--- a/lib/librumphijack/hijack.c        Wed Mar 09 13:21:36 2011 +0000
+++ b/lib/librumphijack/hijack.c        Wed Mar 09 15:03:18 2011 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: hijack.c,v 1.77 2011/03/09 09:17:12 pooka Exp $       */
+/*      $NetBSD: hijack.c,v 1.78 2011/03/09 15:03:18 pooka Exp $       */
 
 /*-
  * Copyright (c) 2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: hijack.c,v 1.77 2011/03/09 09:17:12 pooka Exp $");
+__RCSID("$NetBSD: hijack.c,v 1.78 2011/03/09 15:03:18 pooka Exp $");
 
 #define __ssp_weak_name(fun) _hijack_ ## fun
 
@@ -94,6 +94,9 @@
        DUALCALL_CHFLAGS, DUALCALL_LCHFLAGS, DUALCALL_FCHFLAGS,
        DUALCALL_ACCESS,
        DUALCALL_MKNOD,
+       DUALCALL___SYSCTL,
+       DUALCALL_GETVFSSTAT, DUALCALL_NFSSVC,
+       DUALCALL_GETFH, DUALCALL_FHOPEN, DUALCALL_FHSTAT, DUALCALL_FHSTATVFS1,
        DUALCALL__NUM
 };
 
@@ -115,6 +118,7 @@
 #define REALLUTIMES lutimes
 #define REALFUTIMES futimes
 #define REALMKNOD mknod
+#define REALFHSTAT __fhstat40
 #else
 #define REALSELECT _sys___select50
 #define REALPOLLTS _sys___pollts50
@@ -126,12 +130,16 @@
 #define REALLUTIMES __lutimes50
 #define REALFUTIMES __futimes50
 #define REALMKNOD __mknod50
+#define REALFHSTAT __fhstat50
 #endif
 #define REALREAD _sys_read
 #define REALPREAD _sys_pread
 #define REALPWRITE _sys_pwrite
 #define REALGETDENTS __getdents30
 #define REALMOUNT __mount50
+#define REALGETFH __getfh30
+#define REALFHOPEN __fhopen40
+#define REALFHSTATVFS1 __fhstatvfs140
 
 int REALSELECT(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 int REALPOLLTS(struct pollfd *, nfds_t,
@@ -151,6 +159,10 @@
 int REALMOUNT(const char *, const char *, int, void *, size_t);
 int __getcwd(char *, size_t);
 int REALMKNOD(const char *, mode_t, dev_t);
+int REALGETFH(const char *, void *, size_t *);
+int REALFHOPEN(const void *, size_t, int);
+int REALFHSTAT(const void *, size_t, struct stat *);
+int REALFHSTATVFS1(const void *, size_t, struct statvfs *, int);
 
 #define S(a) __STRING(a)
 struct sysnames {
@@ -223,6 +235,13 @@
        { DUALCALL_FCHFLAGS,    "fchflags",     RSYS_NAME(FCHFLAGS)     },
        { DUALCALL_ACCESS,      "access",       RSYS_NAME(ACCESS)       },
        { DUALCALL_MKNOD,       S(REALMKNOD),   RSYS_NAME(MKNOD)        },
+       { DUALCALL___SYSCTL,    "__sysctl",     RSYS_NAME(__SYSCTL)     },
+       { DUALCALL_GETVFSSTAT,  "getvfsstat",   RSYS_NAME(GETVFSSTAT)   },
+       { DUALCALL_NFSSVC,      "nfssvc",       RSYS_NAME(NFSSVC)       },
+       { DUALCALL_GETFH,       "S(REALGETFH)", RSYS_NAME(GETFH)        },
+       { DUALCALL_FHOPEN,      "S(REALFHOPEN)",RSYS_NAME(FHOPEN)       },
+       { DUALCALL_FHSTAT,      "S(REALFHSTAT)",RSYS_NAME(FHSTAT)       },
+       { DUALCALL_FHSTATVFS1,  "S(REALSTATVFS1)",RSYS_NAME(FHSTATVFS1) },
 };
 #undef S
 
@@ -403,6 +422,21 @@
        return fun vars;                                                \
 }
 
+#define VFSCALL(bit, type, name, rcname, args, proto, vars)            \
+type name args                                                         \
+{                                                                      \
+       type (*fun) proto;                                              \
+                                                                       \
+       DPRINTF(("%s (0x%x, 0x%x)\n", __STRING(name), bit, vfsbits));   \
+       if (vfsbits & bit) {                                            \
+               fun = syscalls[rcname].bs_rump;                         \
+       } else {                                                        \
+               fun = syscalls[rcname].bs_host;                         \
+       }                                                               \
+                                                                       \
+       return fun vars;                                                \
+}
+
 /*
  * These variables are set from the RUMPHIJACK string and control
  * which operations can product rump kernel file descriptors.
@@ -462,7 +496,7 @@
                        }
                }
                if (socketmap[i].name == NULL) {
-                       warnx("invalid socket specifier %s", p);
+                       errx(1, "invalid socket specifier %s", p);
                }
        }
 }
@@ -519,14 +553,103 @@
        }
 }
 
+#define VFSBIT_NFSSVC          0x01
+#define VFSBIT_GETVFSSTAT      0x02
+#define VFSBIT_FHCALLS         0x04
+static unsigned vfsbits;
+
+static struct {
+       int bit;
+       const char *name;
+} vfscalls[] = {
+       { VFSBIT_NFSSVC, "nfssvc" },
+       { VFSBIT_GETVFSSTAT, "getvfsstat" },
+       { VFSBIT_FHCALLS, "fhcalls" },
+       { -1, NULL }
+};
+
+static void
+vfsparser(char *buf)
+{
+       char *p, *l;
+       bool turnon;
+       unsigned int fullmask;
+       int i;
+
+       /* build the full mask and sanity-check while we're at it */
+       fullmask = 0;
+       for (i = 0; vfscalls[i].name != NULL; i++) {
+               if (fullmask & vfscalls[i].bit)
+                       errx(1, "problem exists between vi and chair");
+               fullmask |= vfscalls[i].bit;
+       }
+
+
+       /* if "all" is present, it must be specified first */
+       if (strncmp(buf, "all", strlen("all")) == 0) {
+               vfsbits = fullmask;
+               buf += strlen("all");
+               if (*buf == ':')
+                       buf++;
+       }
+
+       for (p = strtok_r(buf, ":", &l); p; p = strtok_r(NULL, ":", &l)) {
+               turnon = true;
+               if (strncmp(p, "no", strlen("no")) == 0) {
+                       turnon = false;
+                       p += strlen("no");
+               }
+
+               for (i = 0; vfscalls[i].name; i++) {
+                       if (strcmp(p, vfscalls[i].name) == 0) {
+                               if (turnon)
+                                       vfsbits |= vfscalls[i].bit;
+                               else
+                                       vfsbits &= ~vfscalls[i].bit;
+                               break;
+                       }
+               }
+               if (vfscalls[i].name == NULL) {
+                       errx(1, "invalid vfscall specifier %s", p);
+               }
+       }
+}
+
+static bool rumpsysctl = false;
+
+static void
+sysctlparser(char *buf)
+{
+
+       if (buf == NULL) {
+               rumpsysctl = true;
+               return;
+       }
+
+       if (strcasecmp(buf, "y") == 0 || strcasecmp(buf, "yes") == 0 ||
+           strcasecmp(buf, "yep") == 0 || strcasecmp(buf, "tottakai") == 0) {
+               rumpsysctl = true;
+               return;
+       }
+       if (strcasecmp(buf, "n") == 0 || strcasecmp(buf, "no") == 0) {
+               rumpsysctl = false;
+               return;
+       }
+
+       errx(1, "sysctl value should be y(es)/n(o), gave: %s", buf);
+}
+
 static struct {
        void (*parsefn)(char *);
        const char *name;
+       bool needvalues;
 } hijackparse[] = {
-       { sockparser, "socket" },
-       { pathparser, "path" },
-       { blanketparser, "blanket" },
-       { NULL, NULL },
+       { sockparser, "socket", true },
+       { pathparser, "path", true },
+       { blanketparser, "blanket", true },
+       { vfsparser, "vfs", true },
+       { sysctlparser, "sysctl", false },
+       { NULL, NULL, false },
 };
 
 static void
@@ -534,6 +657,7 @@
 {
        char *p, *p2, *l;
        const char *hijackcopy;
+       bool nop2;
        int i;
 
        if ((hijackcopy = strdup(hijack)) == NULL)
@@ -544,14 +668,20 @@
                rumpsockets[i] = false;
 
        for (p = strtok_r(hijack, ",", &l); p; p = strtok_r(NULL, ",", &l)) {
+               nop2 = false;
                p2 = strchr(p, '=');
-               if (!p2)
-                       errx(1, "invalid hijack specifier: %s", hijackcopy);
+               if (!p2) {
+                       nop2 = true;
+                       p2 = p + strlen(p);
+               }
 
                for (i = 0; hijackparse[i].parsefn; i++) {
                        if (strncmp(hijackparse[i].name, p,
                            (size_t)(p2-p)) == 0) {
-                               hijackparse[i].parsefn(p2+1);
+                               if (nop2 && hijackparse[i].needvalues)
+                                       errx(1, "invalid hijack specifier: %s",
+                                           hijackcopy);
+                               hijackparse[i].parsefn(nop2 ? NULL : p2+1);
                                break;
                        }
                }
@@ -1713,6 +1843,30 @@
 }
 
 /*
+ * these go to one or the other on a per-process configuration
+ */
+int __sysctl(const int *, unsigned int, void *, size_t *, const void *, size_t);
+int
+__sysctl(const int *name, unsigned int namelen, void *old, size_t *oldlenp,
+       const void *new, size_t newlen)
+{
+       int (*op___sysctl)(const int *, unsigned int, void *, size_t *,
+           const void *, size_t);
+
+       if (rumpsysctl) {
+               op___sysctl = GETSYSCALL(rump, __SYSCTL);
+       } else {
+               op___sysctl = GETSYSCALL(host, __SYSCTL);
+               /* we haven't inited yet */
+               if (__predict_false(op___sysctl == NULL)) {
+                       op___sysctl = dlsym(RTLD_NEXT, "__sysctl");
+               }
+       }
+
+       return op___sysctl(name, namelen, old, oldlenp, new, newlen);
+}
+
+/*
  * Rest are std type calls.
  */
 
@@ -2006,3 +2160,57 @@
        (const char *path, int flags),                                  \
        (const char *, int),                                            \
        (path, flags))
+
+/*
+ * These act different on a per-process vfs configuration
+ */
+
+VFSCALL(VFSBIT_GETVFSSTAT, int, getvfsstat, DUALCALL_GETVFSSTAT,       \
+       (struct statvfs *buf, size_t buflen, int flags),                \
+       (struct statvfs *, size_t, int),                                \
+       (buf, buflen, flags))
+
+VFSCALL(VFSBIT_FHCALLS, int, REALGETFH, DUALCALL_GETFH,                        \
+       (const char *path, void *fhp, size_t *fh_size),                 \
+       (const char *, void *, size_t *),                               \
+       (path, fhp, fh_size))
+
+VFSCALL(VFSBIT_FHCALLS, int, REALFHOPEN, DUALCALL_FHOPEN,              \



Home | Main Index | Thread Index | Old Index