Source-Changes-HG archive

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

[src/trunk]: src Start rework of system call proxying over socket ("sysproxy").



details:   https://anonhg.NetBSD.org/src/rev/5ba1f007ef88
branches:  trunk
changeset: 758231:5ba1f007ef88
user:      pooka <pooka%NetBSD.org@localhost>
date:      Wed Oct 27 20:44:49 2010 +0000

description:
Start rework of system call proxying over socket ("sysproxy").
This incarnation is written in the user namespace as opposed to
the previous one which was done in kernel namespace.  Also, rump
does all the handshaking now instead of excepting an application
to come up with the user namespace socket.

There's still a lot to do, including making code "a bit" more
robust, actually running different clients in a different process
inside the kernel and splitting the client side library from librump.
I'm committing this now so that I don't lose it, plus it generally
works as long as you don't use it in unexcepted ways: i've tested
ifconfig(8), route(8), envstat(8) and sysctl(8).

diffstat:

 lib/librumpuser/Makefile                 |    4 +-
 lib/librumpuser/rumpuser_sp.c            |  950 +++++++++++++++++++++++++++++++
 sys/rump/include/rump/rump.h             |    3 +-
 sys/rump/include/rump/rumpuser.h         |   12 +-
 sys/rump/librump/rumpkern/rump.c         |   79 +-
 sys/rump/librump/rumpkern/rump_private.h |   11 +-
 sys/rump/librump/rumpkern/rumpcopy.c     |   31 +-
 sys/rump/librump/rumpkern/vm.c           |   11 +-
 8 files changed, 1041 insertions(+), 60 deletions(-)

diffs (truncated from 1317 to 300 lines):

diff -r e2eb4d2cec61 -r 5ba1f007ef88 lib/librumpuser/Makefile
--- a/lib/librumpuser/Makefile  Wed Oct 27 20:37:11 2010 +0000
+++ b/lib/librumpuser/Makefile  Wed Oct 27 20:44:49 2010 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile,v 1.2 2010/02/26 18:54:20 pooka Exp $
+#      $NetBSD: Makefile,v 1.3 2010/10/27 20:44:50 pooka Exp $
 #
 
 WARNS=         4
@@ -11,7 +11,7 @@
 
 SRCS=          rumpuser.c rumpuser_net.c
 SRCS+=         rumpuser_pth.c
-SRCS+=         rumpuser_dl.c
+SRCS+=         rumpuser_dl.c rumpuser_sp.c
 
 INCSDIR=       /usr/include/rump
 INCS=          rumpuser.h
diff -r e2eb4d2cec61 -r 5ba1f007ef88 lib/librumpuser/rumpuser_sp.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/librumpuser/rumpuser_sp.c     Wed Oct 27 20:44:49 2010 +0000
@@ -0,0 +1,950 @@
+/*      $NetBSD: rumpuser_sp.c,v 1.1 2010/10/27 20:44:50 pooka Exp $   */
+
+/*
+ * Copyright (c) 2010 Antti Kantee.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Sysproxy routines.  This provides system RPC support over host sockets.
+ * The most notable limitation is that the client and server must share
+ * the same ABI.  This does not mean that they have to be the same
+ * machine or that they need to run the same version of the host OS,
+ * just that they must agree on the data structures.  This even *might*
+ * work correctly from one hardware architecture to another.
+ *
+ * Not finished yet, i.e. don't use in production.  Lacks locking plus
+ * handling of multiple clients and unexpected connection closes.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: rumpuser_sp.c,v 1.1 2010/10/27 20:44:50 pooka Exp $");
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rump/rump.h>
+#include <rump/rumpuser.h>
+
+//#define DEBUG
+#ifdef DEBUG
+#define DPRINTF(x) mydprintf x
+static void
+mydprintf(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+}
+#else
+#define DPRINTF(x)
+#endif
+
+/*
+ * Bah, I hate writing on-off-wire conversions in C
+ */
+
+enum {
+       RUMPSP_SYSCALL_REQ,     RUMPSP_SYSCALL_RESP,
+       RUMPSP_COPYIN_REQ,      RUMPSP_COPYIN_RESP,
+       RUMPSP_COPYOUT_REQ,     /* no copyout resp */
+       RUMPSP_ANONMMAP_REQ,    RUMPSP_ANONMMAP_RESP
+};
+
+struct rsp_hdr {
+       uint64_t rsp_len;
+       uint64_t rsp_reqno;
+       uint32_t rsp_type;
+       /*
+        * We want this structure 64bit-aligned for typecast fun,
+        * so might as well use the following for something.
+        */
+       uint32_t rsp_sysnum;
+};
+#define HDRSZ sizeof(struct rsp_hdr)
+
+/*
+ * Data follows the header.  We have two types of structured data.
+ */
+
+/* copyin/copyout */
+struct rsp_copydata {
+       size_t rcp_len;
+       void *rcp_addr;
+       uint8_t rcp_data[0];
+};
+
+/* syscall response */
+struct rsp_sysresp {
+       int rsys_error;
+       register_t rsys_retval[2];
+};
+
+
+struct spclient {
+       int spc_fd;
+
+       /* incoming */
+       struct rsp_hdr spc_hdr;
+       uint8_t *spc_buf;
+       size_t spc_off;
+
+#if 0
+       /* outgoing */
+       int spc_obusy;
+       pthread_mutex_t spc_omtx;
+       pthread_cond_t spc_cv;
+#endif
+};
+
+typedef int (*addrparse_fn)(const char *, int, struct sockaddr **);
+typedef int (*connecthook_fn)(int);
+
+#define MAXCLI 4
+
+static struct pollfd pfdlist[MAXCLI];
+static struct spclient spclist[MAXCLI];
+static unsigned int nfds, maxidx;
+static uint64_t nextreq;
+static pthread_key_t spclient_tls;
+
+static struct spclient clispc;
+
+
+static int
+dosend(struct spclient *spc, const void *data, size_t dlen)
+{
+       struct pollfd pfd;
+       const uint8_t *sdata = data;
+       ssize_t n;
+       size_t sent;
+       int fd = spc->spc_fd;
+
+       pfd.fd = fd;
+       pfd.events = POLLOUT;
+
+       for (sent = 0, n = 0; sent < dlen; ) {
+               if (n) {
+                       if (poll(&pfd, 1, INFTIM) == -1) {
+                               if (errno == EINTR)
+                                       continue;
+                               return errno;
+                       }
+               }
+
+               n = write(fd, sdata + sent, dlen - sent);
+               if (n == 0) {
+                       return EFAULT;
+               }
+               if (n == -1 && errno != EAGAIN) {
+                       return EFAULT;
+               }
+               sent += n;
+       }
+
+       return 0;
+}
+
+static int
+send_syscall_req(struct spclient *spc, int sysnum,
+       const void *data, size_t dlen)
+{
+       struct rsp_hdr rhdr;
+
+       rhdr.rsp_len = sizeof(rhdr) + dlen;
+       rhdr.rsp_reqno = nextreq++;
+       rhdr.rsp_type = RUMPSP_SYSCALL_REQ;
+       rhdr.rsp_sysnum = sysnum;
+
+       dosend(spc, &rhdr, sizeof(rhdr));
+       dosend(spc, data, dlen);
+
+       return 0;
+}
+
+static int
+send_syscall_resp(struct spclient *spc, uint64_t reqno, int error,
+       register_t retval[2])
+{
+       struct rsp_hdr rhdr;
+       struct rsp_sysresp sysresp;
+
+       rhdr.rsp_len = sizeof(rhdr) + sizeof(sysresp);
+       rhdr.rsp_reqno = reqno;
+       rhdr.rsp_type = RUMPSP_SYSCALL_RESP;
+       rhdr.rsp_sysnum = 0;
+
+       sysresp.rsys_error = error;
+       memcpy(sysresp.rsys_retval, retval, sizeof(retval));
+
+       dosend(spc, &rhdr, sizeof(rhdr));
+       dosend(spc, &sysresp, sizeof(sysresp));
+
+       return 0;
+}
+
+static int
+send_copyin_req(struct spclient *spc, const void *remaddr, size_t dlen)
+{
+       struct rsp_hdr rhdr;
+       struct rsp_copydata copydata;
+
+       rhdr.rsp_len = sizeof(rhdr) + sizeof(copydata);
+       rhdr.rsp_reqno = nextreq++;
+       rhdr.rsp_type = RUMPSP_COPYIN_REQ;
+       rhdr.rsp_sysnum = 0;
+
+       copydata.rcp_addr = __UNCONST(remaddr);
+       copydata.rcp_len = dlen;
+
+       dosend(spc, &rhdr, sizeof(rhdr));
+       dosend(spc, &copydata, sizeof(copydata));
+
+       return 0;
+}
+
+static int
+send_copyin_resp(struct spclient *spc, uint64_t reqno, void *data, size_t dlen)
+{
+       struct rsp_hdr rhdr;
+
+       rhdr.rsp_len = sizeof(rhdr) + dlen;
+       rhdr.rsp_reqno = reqno;
+       rhdr.rsp_type = RUMPSP_COPYIN_RESP;
+       rhdr.rsp_sysnum = 0;
+
+       dosend(spc, &rhdr, sizeof(rhdr));
+       dosend(spc, data, dlen);
+
+       return 0;
+}
+
+static int
+send_copyout_req(struct spclient *spc, const void *remaddr,
+       const void *data, size_t dlen)
+{
+       struct rsp_hdr rhdr;
+       struct rsp_copydata copydata;
+
+       rhdr.rsp_len = sizeof(rhdr) + sizeof(copydata) + dlen;
+       rhdr.rsp_reqno = nextreq++;
+       rhdr.rsp_type = RUMPSP_COPYOUT_REQ;
+       rhdr.rsp_sysnum = 0;
+
+       copydata.rcp_addr = __UNCONST(remaddr);
+       copydata.rcp_len = dlen;
+
+       dosend(spc, &rhdr, sizeof(rhdr));
+       dosend(spc, &copydata, sizeof(copydata));
+       dosend(spc, data, dlen);
+



Home | Main Index | Thread Index | Old Index