qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 05/13] hw/9pfs: Add support to use named socket for


From: M. Mohan Kumar
Subject: [Qemu-devel] [PATCH 05/13] hw/9pfs: Add support to use named socket for proxy FS
Date: Tue, 1 Nov 2011 02:23:24 +0530

From: "M. Mohan Kumar" <address@hidden>

Add option to use named socket for communicating between proxy helper
and qemu proxy FS. Access to socket can be given by using command line
options -u and -g.

Signed-off-by: M. Mohan Kumar <address@hidden>
---
 hw/9pfs/virtfs-proxy-helper.c |   89 ++++++++++++++++++++++++++++++++++++++--
 hw/9pfs/virtio-9p-proxy.c     |   56 ++++++++++++++++++++++---
 qemu-config.c                 |    6 +++
 vl.c                          |    6 ++-
 4 files changed, 144 insertions(+), 13 deletions(-)

diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 8e82ca7..9d925e0 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -26,6 +26,9 @@ static struct option helper_opts[] = {
     {"fd", required_argument, NULL, 'f'},
     {"path", required_argument, NULL, 'p'},
     {"nodaemon", no_argument, NULL, 'n'},
+    {"socket", required_argument, NULL, 's'},
+    {"uid", required_argument, NULL, 'u'},
+    {"gid", required_argument, NULL, 'g'},
 };
 
 int is_daemon;
@@ -153,11 +156,61 @@ static int read_request(int sockfd, struct iovec *iovec)
     } while (1);
 }
 
+/* create unix domain socket and return the descriptor */
+static int proxy_socket(const char *path, uid_t uid, gid_t gid)
+{
+    int sock, client;
+    struct sockaddr_un proxy, qemu;
+    socklen_t size;
+
+    /* requested socket already exists, refuse to start */
+    if (!access(path, F_OK)) {
+        do_log(LOG_CRIT, "socket already exists\n");
+        return -1;
+    }
+
+    sock = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock < 0) {
+        do_perror("socket");
+        return -1;
+    }
+
+    /* mask other part of mode bits */
+    umask(7);
+
+    proxy.sun_family = AF_UNIX;
+    strcpy(proxy.sun_path, path);
+    if (bind(sock, (struct sockaddr *)&proxy,
+            sizeof(struct sockaddr_un)) < 0) {
+        do_perror("bind");
+        return -1;
+    }
+    if (chown(proxy.sun_path, uid, gid) < 0) {
+        do_perror("chown");
+        return -1;
+    }
+    if (listen(sock, 1) < 0) {
+        do_perror("listen");
+        return -1;
+    }
+
+    client = accept(sock, (struct sockaddr *)&qemu, &size);
+    if (client < 0) {
+        do_perror("accept");
+        return -1;
+    }
+    return client;
+}
+
 static void usage(char *prog)
 {
     fprintf(stderr, "usage: %s\n"
         " -p|--path <path> 9p path to export\n"
         " {-f|--fd <socket-descriptor>} socket file descriptor to be used\n"
+        " {-s|--socket <socketname> socket file used for communication\n"
+        " \t-u|--uid <uid> -g|--gid <gid>} - uid:gid combination to give "
+        " access to this socket\n"
+        " \tNote: -s & -f can not be used together\n"
         " [-n|--nodaemon] Run as a normal program\n",
         basename(prog));
 }
@@ -184,16 +237,20 @@ error:
 int main(int argc, char **argv)
 {
     int sock;
+    char sock_name[PATH_MAX];
     char rpath[PATH_MAX];
     struct stat stbuf;
     int c, option_index;
+    uid_t own_u;
+    gid_t own_g;
 
     is_daemon = 1;
-    rpath[0] = '\0';
+    sock_name[0] = rpath[0] = '\0';
     sock = -1;
+    own_u = own_g = -1;
     while (1) {
         option_index = 0;
-        c = getopt_long(argc, argv, "p:nh?f:", helper_opts,
+        c = getopt_long(argc, argv, "p:nh?f:s:u:g:", helper_opts,
                         &option_index);
         if (c == -1) {
             break;
@@ -205,9 +262,18 @@ int main(int argc, char **argv)
         case 'n':
             is_daemon = 0;
             break;
-       case 'f':
+        case 'f':
             sock = atoi(optarg);
             break;
+        case 's':
+            strcpy(sock_name, optarg);
+            break;
+        case 'u':
+            own_u = atoi(optarg);
+            break;
+        case 'g':
+            own_g = atoi(optarg);
+            break;
         case '?':
         case 'h':
         default:
@@ -218,8 +284,15 @@ int main(int argc, char **argv)
     }
 
     /* Parameter validation */
-    if (sock == -1 || rpath[0] == '\0') {
-        fprintf(stderr, "socket descriptor or path not specified\n");
+    if ((sock_name[0] == '\0' && sock == -1) || rpath[0] == '\0') {
+        fprintf(stderr, "socket, socket descriptor or path not specified\n");
+        usage(argv[0]);
+        return -1;
+    }
+
+    if (*sock_name && (own_u == -1 || own_g == -1)) {
+        fprintf(stderr, "owner uid:gid not specified, ");
+        fprintf(stderr, "owner specifies who can access the socket file\n");
         usage(argv[0]);
         return -1;
     }
@@ -243,6 +316,12 @@ int main(int argc, char **argv)
     }
 
     do_log(LOG_INFO, "Started");
+    if (*sock_name) {
+        sock = proxy_socket(sock_name, own_u, own_g);
+        if (sock < 0) {
+            goto error;
+        }
+    }
 
     if (chroot(rpath) < 0) {
         do_perror("chroot");
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index c682e36..0ec686c 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -16,6 +16,10 @@
 #include "fsdev/qemu-fsdev.h"
 #include "proxy.h"
 
+/* FS specific flags */
+#define V9FS_PROXY_SOCK_FD          (1 << 9)
+#define V9FS_PROXY_SOCK_NAME        (1 << 10)
+
 typedef struct V9fsProxy {
     int sockfd;
     QemuMutex mutex;
@@ -301,15 +305,49 @@ static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
     return ret;
 }
 
+static int connect_namedsocket(const char *path)
+{
+    int sockfd, size;
+    struct sockaddr_un helper;
+
+    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sockfd < 0) {
+        fprintf(stderr, "socket %s\n", strerror(errno));
+        return -1;
+    }
+    strcpy(helper.sun_path, path);
+    helper.sun_family = AF_UNIX;
+    size = strlen(helper.sun_path) + sizeof(helper.sun_family);
+    if (connect(sockfd, (struct sockaddr *)&helper, size) < 0) {
+        fprintf(stderr, "socket error\n");
+        return -1;
+    }
+
+    /* remove the socket for security reasons */
+    unlink(path);
+    return sockfd;
+}
+
 static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
 {
+    const char *socket = qemu_opt_get(opts, "socket");
     const char *sock_fd = qemu_opt_get(opts, "sock_fd");
 
-    if (sock_fd) {
-        fprintf(stderr, "sock_fd option not specified\n");
+    if (!socket && !sock_fd) {
+        fprintf(stderr, "socket and sock_fd none of the option specified\n");
+        return -1;
+    }
+    if (socket && sock_fd) {
+        fprintf(stderr, "Both socket and sock_fd options specified\n");
         return -1;
     }
-    fs->path = g_strdup(sock_fd);
+    if (socket) {
+        fs->path = g_strdup(socket);
+        fs->export_flags = V9FS_PROXY_SOCK_NAME;
+    } else {
+        fs->path = g_strdup(sock_fd);
+        fs->export_flags = V9FS_PROXY_SOCK_FD;
+    }
     return 0;
 }
 
@@ -318,10 +356,14 @@ static int proxy_init(FsContext *ctx)
     V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
     int sock_id;
 
-    sock_id = atoi(ctx->fs_root);
-    if (sock_id < 0) {
-        fprintf(stderr, "socket descriptor not initialized\n");
-        return -1;
+    if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) {
+        sock_id = connect_namedsocket(ctx->fs_root);
+    } else {
+        sock_id = atoi(ctx->fs_root);
+        if (sock_id < 0) {
+            fprintf(stderr, "socket descriptor not initialized\n");
+            return -1;
+        }
     }
     g_free(ctx->fs_root);
 
diff --git a/qemu-config.c b/qemu-config.c
index 5e63c14..6203e7b 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -187,6 +187,9 @@ QemuOptsList qemu_fsdev_opts = {
         }, {
             .name = "sock_fd",
             .type = QEMU_OPT_NUMBER,
+        }, {
+            .name = "socket",
+            .type = QEMU_OPT_STRING,
         },
 
         { /*End of list */ }
@@ -219,6 +222,9 @@ QemuOptsList qemu_virtfs_opts = {
         }, {
             .name = "sock_fd",
             .type = QEMU_OPT_NUMBER,
+        }, {
+            .name = "socket",
+            .type = QEMU_OPT_STRING,
         },
 
         { /*End of list */ }
diff --git a/vl.c b/vl.c
index 5a5ab7f..8fbf481 100644
--- a/vl.c
+++ b/vl.c
@@ -2663,7 +2663,7 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_virtfs: {
                 QemuOpts *fsdev;
                 QemuOpts *device;
-                const char *writeout, *sock_fd;
+                const char *writeout, *sock_fd, *socket;
 
                 olist = qemu_find_opts("virtfs");
                 if (!olist) {
@@ -2703,6 +2703,10 @@ int main(int argc, char **argv, char **envp)
                 qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
                 qemu_opt_set(fsdev, "security_model",
                              qemu_opt_get(opts, "security_model"));
+                socket = qemu_opt_get(opts, "socket");
+                if (socket) {
+                    qemu_opt_set(fsdev, "socket", socket);
+                }
                 sock_fd = qemu_opt_get(opts, "sock_fd");
                 if (sock_fd) {
                     qemu_opt_set(fsdev, "sock_fd", sock_fd);
-- 
1.7.6




reply via email to

[Prev in Thread] Current Thread [Next in Thread]