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

[libvirt] [PATCH 1/2] add 'umask' option to -chardev



To use virtio-serial device, unix socket created for chardev with
default umask(022) has insufficient permissions.

e.g. start kvm guest with:
-device virtio-serial \
-chardev socket,path=/tmp/foo,server,nowait,id=foo \
-device virtserialport,chardev=foo,name=org.fedoraproject.port.0

Check permissions for the socket file that has been created in the host
to enable communication through virtual serial ports in the guest:
#ls -l /tmp/somefile.sock
srwxr-xr-x 1 qemu qemu 0 21. Jul 14:19 /tmp/somefile.sock

Other users in the qemu group (like real user, test engines, etc) cannot
write to this socket.

Problem reported here:
https://sourceware.org/bugzilla/show_bug.cgi?id=13078#c11
https://bugzilla.novell.com/show_bug.cgi?id=888166

This patch tries to add a 'umask' option to 'chardev', so that user
can have chance to indicate a umask overwritting the default one (default
is 022), then create unix sockets with expected permissions.

Signed-off-by: Chunyan Liu <cyliu suse com>
---
This is patch for qemu.

 qemu-char.c         |  3 +++
 qemu-options.hx     |  9 +++++++--
 util/qemu-sockets.c | 12 +++++++++++-
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index d4f327a..a39a5e4 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3856,6 +3856,9 @@ QemuOptsList qemu_chardev_opts = {
         },{
             .name = "chardev",
             .type = QEMU_OPT_STRING,
+        },{
+            .name = "umask",
+            .type = QEMU_OPT_NUMBER,
         },
         { /* end of list */ }
     },
diff --git a/qemu-options.hx b/qemu-options.hx
index ecd0e34..078e9db 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1929,7 +1929,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
     "-chardev null,id=id[,mux=on|off]\n"
     "-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4][,ipv6][,nodelay]\n"
     "         [,server][,nowait][,telnet][,mux=on|off] (tcp)\n"
-    "-chardev socket,id=id,path=path[,server][,nowait][,telnet],[mux=on|off] (unix)\n"
+    "-chardev socket,id=id,path=path[,umask][,server][,nowait][,telnet],[mux=on|off] (unix)\n"
     "-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n"
     "         [,localport=localport][,ipv4][,ipv6][,mux=on|off]\n"
     "-chardev msmouse,id=id[,mux=on|off]\n"
@@ -2001,12 +2001,17 @@ Options to each backend are described below.
 A void device. This device will not emit any data, and will drop any data it
 receives. The null backend does not take any options.
 
- item -chardev socket ,id= var{id} [ var{TCP options} or @var{unix options}] [,server] [,nowait] [,telnet]
+ item -chardev socket ,id= var{id} [ var{TCP options} or @var{unix options}] [,umask][,server] [,nowait] [,telnet]
 
 Create a two-way stream socket, which can be either a TCP or a unix socket. A
 unix socket will be created if @option{path} is specified. Behaviour is
 undefined if TCP options are specified for a unix socket.
 
+ option{umask} specifies the umask used for creating a unix socket. Without
+this option, default umask(022) will be used, permission is not sufficient
+for virtio-serial device. One can indicate umask=0x002 for virtio-serial
+device for correct usage.
+
 @option{server} specifies that the socket shall be a listening socket.
 
 @option{nowait} specifies that QEMU should not block waiting for a client to
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 5d38395..facf2c6 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -680,7 +680,8 @@ int unix_listen_opts(QemuOpts *opts, Error **errp)
 {
     struct sockaddr_un un;
     const char *path = qemu_opt_get(opts, "path");
-    int sock, fd;
+    int newmask = qemu_opt_get_number(opts, "umask", 0);
+    int sock, fd, oldmask;
 
     sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0);
     if (sock < 0) {
@@ -708,10 +709,19 @@ int unix_listen_opts(QemuOpts *opts, Error **errp)
     }
 
     unlink(un.sun_path);
+    if (newmask) {
+        oldmask = umask(newmask);
+    }
     if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
+        if (newmask) {
+            umask(oldmask);
+        }
         error_set_errno(errp, errno, QERR_SOCKET_BIND_FAILED);
         goto err;
     }
+    if (newmask) {
+        umask(oldmask);
+    }
     if (listen(sock, 1) < 0) {
         error_set_errno(errp, errno, QERR_SOCKET_LISTEN_FAILED);
         goto err;
-- 
1.8.5.2


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