Source-Changes-HG archive

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

[src/trunk]: src/lib/librumphijack implement descriptor passing.



details:   https://anonhg.NetBSD.org/src/rev/f7b445d1387b
branches:  trunk
changeset: 779938:f7b445d1387b
user:      yamt <yamt%NetBSD.org@localhost>
date:      Fri Jun 29 13:20:25 2012 +0000

description:
implement descriptor passing.

diffstat:

 lib/librumphijack/hijack.c |  130 ++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 118 insertions(+), 12 deletions(-)

diffs (158 lines):

diff -r 53cb4b9f1527 -r f7b445d1387b lib/librumphijack/hijack.c
--- a/lib/librumphijack/hijack.c        Fri Jun 29 12:51:38 2012 +0000
+++ b/lib/librumphijack/hijack.c        Fri Jun 29 13:20:25 2012 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: hijack.c,v 1.93 2012/06/25 22:32:47 abs Exp $ */
+/*      $NetBSD: hijack.c,v 1.94 2012/06/29 13:20:25 yamt Exp $        */
 
 /*-
  * Copyright (c) 2011 Antti Kantee.  All Rights Reserved.
@@ -29,7 +29,7 @@
 #undef _FORTIFY_SOURCE
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: hijack.c,v 1.93 2012/06/25 22:32:47 abs Exp $");
+__RCSID("$NetBSD: hijack.c,v 1.94 2012/06/29 13:20:25 yamt Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -1335,6 +1335,122 @@
 }
 
 /*
+ * file descriptor passing
+ *
+ * we intercept sendmsg and recvmsg to convert file descriptors in
+ * control messages.  an attempt to send a descriptor from a different kernel
+ * is rejected.  (ENOTSUP)
+ */
+
+static int
+msg_convert(struct msghdr *msg, int (*func)(int))
+{
+       struct cmsghdr *cmsg;
+
+       for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
+           cmsg = CMSG_NXTHDR(msg, cmsg)) {
+               if (cmsg->cmsg_level == SOL_SOCKET &&
+                   cmsg->cmsg_type == SCM_RIGHTS) {
+                       int *fdp = (void *)CMSG_DATA(cmsg);
+                       const size_t size =
+                           cmsg->cmsg_len - __CMSG_ALIGN(sizeof(*cmsg));
+                       const int nfds = size / sizeof(int);
+                       const int * const efdp = fdp + nfds;
+
+                       while (fdp < efdp) {
+                               const int newval = func(*fdp);
+
+                               if (newval < 0) {
+                                       return ENOTSUP;
+                               }
+                               *fdp = newval;
+                               fdp++;
+                       }
+               }
+       }
+       return 0;
+}
+
+ssize_t
+recvmsg(int fd, struct msghdr *msg, int flags)
+{
+       ssize_t (*op_recvmsg)(int, struct msghdr *, int);
+       ssize_t ret;
+       const bool isrump = fd_isrump(fd);
+
+       if (isrump) {
+               fd = fd_host2rump(fd);
+               op_recvmsg = GETSYSCALL(rump, RECVMSG);
+       } else {
+               op_recvmsg = GETSYSCALL(host, RECVMSG);
+       }
+       ret = op_recvmsg(fd, msg, flags);
+       if (ret == -1) {
+               return ret;
+       }
+       /*
+        * convert descriptors in the message.
+        */
+       if (isrump) {
+               msg_convert(msg, fd_rump2host);
+       } else {
+               msg_convert(msg, fd_host2host);
+       }
+       return ret;
+}
+
+static int
+fd_check_rump(int fd)
+{
+
+       return fd_isrump(fd) ? 0 : -1;
+}
+
+static int
+fd_check_host(int fd)
+{
+
+       return !fd_isrump(fd) ? 0 : -1;
+}
+
+ssize_t
+sendmsg(int fd, const struct msghdr *msg, int flags)
+{
+       ssize_t (*op_sendmsg)(int, const struct msghdr *, int);
+       const bool isrump = fd_isrump(fd);
+       int error;
+
+       /*
+        * reject descriptors from a different kernel.
+        */
+       error = msg_convert(__UNCONST(msg),
+           isrump ? fd_check_rump: fd_check_host);
+       if (error != 0) {
+               errno = error;
+               return -1;
+       }
+       /*
+        * convert descriptors in the message to raw values.
+        */
+       if (isrump) {
+               fd = fd_host2rump(fd);
+               /*
+                * XXX we directly modify the given message assuming:
+                * - cmsg is writable (typically on caller's stack)
+                * - caller don't care cmsg's contents after calling sendmsg.
+                *   (thus no need to restore values)
+                *
+                * it's safer to copy and modify instead.
+                */
+               msg_convert(__UNCONST(msg), fd_host2rump);
+               op_sendmsg = GETSYSCALL(rump, SENDMSG);
+       } else {
+               op_sendmsg = GETSYSCALL(host, SENDMSG);
+       }
+       return op_sendmsg(fd, msg, flags);
+}
+
+/*
  * dup2 is special.  we allow dup2 of a rump kernel fd to 0-2 since
  * many programs do that.  dup2 of a rump kernel fd to another value
  * not >= fdoff is an error.
@@ -1949,16 +2065,6 @@
            const struct sockaddr *, socklen_t),                        \
        (fd, buf, len, flags, to, tolen))
 
-FDCALL(ssize_t, recvmsg, DUALCALL_RECVMSG,                             \
-       (int fd, struct msghdr *msg, int flags),                        \
-       (int, struct msghdr *, int),                                    \
-       (fd, msg, flags))
-
-FDCALL(ssize_t, sendmsg, DUALCALL_SENDMSG,                             \
-       (int fd, const struct msghdr *msg, int flags),                  \
-       (int, const struct msghdr *, int),                              \
-       (fd, msg, flags))
-
 FDCALL(int, getsockopt, DUALCALL_GETSOCKOPT,                           \
        (int fd, int level, int optn, void *optval, socklen_t *optlen), \
        (int, int, int, void *, socklen_t *),                           \



Home | Main Index | Thread Index | Old Index