From 1cb1c5d10bb9e180bd3f7be2c10b212ed86a97b4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Thu, 5 Jul 2012 19:35:57 +0200 Subject: [PATCH 1/4] slirp: Enforce host-side user of smb share Windows 7 (and possibly other versions) cannot connect to the samba share if the exported host directory is not world-readable. This can be resolved by forcing the username used for access checks to the one under which QEMU and smbd are running. Signed-off-by: Jan Kiszka --- net/slirp.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index 37b6ccfde9..a43b5764e1 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -26,6 +26,7 @@ #include "config-host.h" #ifndef _WIN32 +#include #include #endif #include "net.h" @@ -487,8 +488,15 @@ static int slirp_smb(SlirpState* s, const char *exported_dir, static int instance; char smb_conf[128]; char smb_cmdline[128]; + struct passwd *passwd; FILE *f; + passwd = getpwuid(geteuid()); + if (!passwd) { + error_report("failed to retrieve user name"); + return -1; + } + snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d", (long)getpid(), instance++); if (mkdir(s->smb_dir, 0700) < 0) { @@ -517,14 +525,16 @@ static int slirp_smb(SlirpState* s, const char *exported_dir, "[qemu]\n" "path=%s\n" "read only=no\n" - "guest ok=yes\n", + "guest ok=yes\n" + "force user=%s\n", s->smb_dir, s->smb_dir, s->smb_dir, s->smb_dir, s->smb_dir, s->smb_dir, - exported_dir + exported_dir, + passwd->pw_name ); fclose(f); From b412eb61bfd400ad70afe11ac3a5fb2931124804 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sun, 3 Jun 2012 09:45:01 +0200 Subject: [PATCH 2/4] slirp: add 'cmd:' target for guestfwd When using guestfwd=, Qemu only connects the virtual server's TCP port to a single chardev. This is useless in most cases, as we usually want to have more than a single connection from the guest to the outside world. This patch adds a new cmd: target to guestfwd= that allows for execution of a command on every TCP connection. This leverages the same code as the -smb parameter, just that here the command is user defined. Reported-by: Sascha Wilde Signed-off-by: Alexander Graf Signed-off-by: Jan Kiszka --- net/slirp.c | 44 +++++++++++++++++++++++++++----------------- qemu-options.hx | 22 +++++++++++++++++++++- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index a43b5764e1..180147e831 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -626,25 +626,35 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, fwd = g_malloc(sizeof(struct GuestFwd)); snprintf(buf, sizeof(buf), "guestfwd.tcp.%d", port); - fwd->hd = qemu_chr_new(buf, p, NULL); - if (!fwd->hd) { - error_report("could not open guest forwarding device '%s'", buf); - g_free(fwd); - return -1; - } - if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) { - error_report("conflicting/invalid host:port in guest forwarding " - "rule '%s'", config_str); - g_free(fwd); - return -1; - } - fwd->server = server; - fwd->port = port; - fwd->slirp = s->slirp; + if ((strlen(p) > 4) && !strncmp(p, "cmd:", 4)) { + if (slirp_add_exec(s->slirp, 0, &p[4], &server, port) < 0) { + error_report("conflicting/invalid host:port in guest forwarding " + "rule '%s'", config_str); + g_free(fwd); + return -1; + } + } else { + fwd->hd = qemu_chr_new(buf, p, NULL); + if (!fwd->hd) { + error_report("could not open guest forwarding device '%s'", buf); + g_free(fwd); + return -1; + } - qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, - NULL, fwd); + if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) { + error_report("conflicting/invalid host:port in guest forwarding " + "rule '%s'", config_str); + g_free(fwd); + return -1; + } + fwd->server = server; + fwd->port = port; + fwd->slirp = s->slirp; + + qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, + NULL, fwd); + } return 0; fail_syntax: diff --git a/qemu-options.hx b/qemu-options.hx index 8b662648ae..ecf7ca12d7 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1421,8 +1421,28 @@ Then when you use on the host @code{telnet localhost 5555}, you connect to the guest telnet server. @item guestfwd=[tcp]:@var{server}:@var{port}-@var{dev} +@item guestfwd=[tcp]:@var{server}:@var{port}-@var{cmd:command} Forward guest TCP connections to the IP address @var{server} on port @var{port} -to the character device @var{dev}. This option can be given multiple times. +to the character device @var{dev} or to a program executed by @var{cmd:command} +which gets spawned for each connection. This option can be given multiple times. + +You can either use a chardev directly and have that one used throughout Qemu's +lifetime, like in the following example: + +@example +# open 10.10.1.1:4321 on bootup, connect 10.0.2.100:1234 to it whenever +# the guest accesses it +qemu -net user,guestfwd=tcp:10.0.2.100:1234-tcp:10.10.1.1:4321 [...] +@end example + +Or you can execute a command on every TCP connection established by the guest, +so that Qemu behaves similar to an inetd process for that virtual server: + +@example +# call "netcat 10.10.1.1 4321" on every TCP connection to 10.0.2.100:1234 +# and connect the TCP stream to its stdin/stdout +qemu -net 'user,guestfwd=tcp:10.0.2.100:1234-cmd:netcat 10.10.1.1 4321' +@end example @end table From 927d811b282ffdf5386bd63f435c1507634ba49a Mon Sep 17 00:00:00 2001 From: Dunrong Huang Date: Fri, 6 Jul 2012 14:04:43 +0800 Subject: [PATCH 3/4] slirp: Ensure smbd and shared directory exist when enable smb Users may pass the following parameters to qemu: $ qemu-kvm -net nic -net user,smb= ... $ qemu-kvm -net nic -net user,smb ... $ qemu-kvm -net nic -net user,smb=bad_directory ... In these cases, qemu started successfully while samba server failed to start. Users will confuse since samba server failed silently without any indication of what it did wrong. To avoid it, we check whether the shared directory exist and if users have permission to access this directory when QEMU's "built-in" SMB server is enabled. Signed-off-by: Dunrong Huang Signed-off-by: Jan Kiszka --- net/slirp.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/slirp.c b/net/slirp.c index 180147e831..eb80889572 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -497,6 +497,18 @@ static int slirp_smb(SlirpState* s, const char *exported_dir, return -1; } + if (access(CONFIG_SMBD_COMMAND, F_OK)) { + error_report("could not find '%s', please install it", + CONFIG_SMBD_COMMAND); + return -1; + } + + if (access(exported_dir, R_OK | X_OK)) { + error_report("no such directory '%s', or you do not have permission " + "to access it, please check it", exported_dir); + return -1; + } + snprintf(s->smb_dir, sizeof(s->smb_dir), "/tmp/qemu-smb.%ld-%d", (long)getpid(), instance++); if (mkdir(s->smb_dir, 0700) < 0) { From 22a61f365df83d5d7884cceb1c462295977cb2db Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 6 Jul 2012 08:40:48 +0200 Subject: [PATCH 4/4] slirp: Improve error reporting of inaccessible smb directories Instead of guessing, print the error code returned by access. Signed-off-by: Jan Kiszka --- net/slirp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index eb80889572..b82eab0a07 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -504,8 +504,8 @@ static int slirp_smb(SlirpState* s, const char *exported_dir, } if (access(exported_dir, R_OK | X_OK)) { - error_report("no such directory '%s', or you do not have permission " - "to access it, please check it", exported_dir); + error_report("error accessing shared directory '%s': %s", + exported_dir, strerror(errno)); return -1; }