* [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors @ 2009-07-06 17:30 Mark McLoughlin 2009-07-06 17:30 ` [Qemu-devel] [PATCH 1/3] Make tcp_chr_read() use recvmsg() Mark McLoughlin 2009-07-07 5:28 ` [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors Avi Kivity 0 siblings, 2 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-06 17:30 UTC (permalink / raw) To: qemu-devel Hi, You can pass file descriptors to qemu via the command line using '-net tap,fd=' or '-net socket,tap='. However, you cannot currently do this via the monitor. libvirt always configures tap interfaces before passing them to qemu. One reason for this is to allow libvirtd to have privileges to /dev/net/tun without allowing qemu those privileges. Because of this, libvirt currently does not support NIC hotplug for qemu. The following three patches add support for passing a file descriptor to the monitor command by allowing file descriptors to be received over monitor commands on a unix socket. For reference: https://fedoraproject.org/wiki/Features/KVM_NIC_Hotplug https://fedoraproject.org/wiki/Features/VirtPrivileges Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 1/3] Make tcp_chr_read() use recvmsg() 2009-07-06 17:30 [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors Mark McLoughlin @ 2009-07-06 17:30 ` Mark McLoughlin 2009-07-06 17:31 ` [Qemu-devel] [PATCH 2/3] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin 2009-07-07 5:28 ` [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors Avi Kivity 1 sibling, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-06 17:30 UTC (permalink / raw) To: qemu-devel This makes no functional changes, just paves the way for the next patch. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- qemu-char.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 287e0cd..e0d7220 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -1911,15 +1911,25 @@ static void tcp_chr_read(void *opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr->opaque; + struct msghdr msg = { 0, }; + struct iovec iov[1]; uint8_t buf[1024]; int len, size; if (!s->connected || s->max_size <= 0) return; + len = sizeof(buf); if (len > s->max_size) len = s->max_size; - size = recv(s->fd, (void *)buf, len, 0); + + iov[0].iov_base = buf; + iov[0].iov_len = len; + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + size = recvmsg(s->fd, &msg, 0); if (size == 0) { /* connection closed */ s->connected = 0; -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 2/3] Add SCM_RIGHTS support to unix socket character devices 2009-07-06 17:30 ` [Qemu-devel] [PATCH 1/3] Make tcp_chr_read() use recvmsg() Mark McLoughlin @ 2009-07-06 17:31 ` Mark McLoughlin 2009-07-06 17:32 ` [Qemu-devel] [PATCH 3/3] Add support for fd=msgfd for tap and socket networking Mark McLoughlin 0 siblings, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-06 17:31 UTC (permalink / raw) To: qemu-devel If a file descriptor is passed via a message with SCM_RIGHTS ancillary data on a unix socket, store the file descriptor for use in the chr_read() handler. Close the file descriptor if it was not used. The qemu_chr_get_msgfd() and monitor_get_msgfd() APIs provide access to any passed descriptor. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- monitor.c | 5 +++++ monitor.h | 1 + qemu-char.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-char.h | 2 ++ 4 files changed, 58 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index bad79fe..f61f43d 100644 --- a/monitor.c +++ b/monitor.c @@ -2981,6 +2981,11 @@ static void monitor_read(void *opaque, const uint8_t *buf, int size) cur_mon = old_mon; } +int monitor_get_msgfd(Monitor *mon) +{ + return qemu_chr_get_msgfd(mon->chr); +} + static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque) { monitor_suspend(mon); diff --git a/monitor.h b/monitor.h index 13e8cc7..af97a86 100644 --- a/monitor.h +++ b/monitor.h @@ -19,6 +19,7 @@ void monitor_resume(Monitor *mon); void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, BlockDriverCompletionFunc *completion_cb, void *opaque); +int monitor_get_msgfd(Monitor *mon); void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap); void monitor_printf(Monitor *mon, const char *fmt, ...) diff --git a/qemu-char.c b/qemu-char.c index e0d7220..f06a614 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) s->chr_read(s->handler_opaque, buf, len); } +int qemu_chr_get_msgfd(CharDriverState *s) +{ + return s->get_msgfd ? s->get_msgfd(s) : -1; +} + void qemu_chr_accept_input(CharDriverState *s) { if (s->chr_accept_input) @@ -1832,6 +1837,7 @@ typedef struct { int do_telnetopt; int do_nodelay; int is_unix; + int msgfd; } TCPCharDriver; static void tcp_chr_accept(void *opaque); @@ -1907,12 +1913,46 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr, *size = j; } +static int tcp_get_msgfd(CharDriverState *chr) +{ + TCPCharDriver *s = chr->opaque; + + return s->msgfd; +} + +static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg) +{ + TCPCharDriver *s = chr->opaque; + struct cmsghdr *cmsg; + + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { + int fd; + + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || + cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) + continue; + + fd = *((int *)CMSG_DATA(cmsg)); + if (fd < 0) + continue; + + if (s->msgfd != -1) + close(s->msgfd); + s->msgfd = fd; + } +} + static void tcp_chr_read(void *opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr->opaque; struct msghdr msg = { 0, }; struct iovec iov[1]; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(int))]; + } msg_control; uint8_t buf[1024]; int len, size; @@ -1928,6 +1968,8 @@ static void tcp_chr_read(void *opaque) msg.msg_iov = iov; msg.msg_iovlen = 1; + msg.msg_control = &msg_control; + msg.msg_controllen = sizeof(msg_control); size = recvmsg(s->fd, &msg, 0); if (size == 0) { @@ -1940,10 +1982,16 @@ static void tcp_chr_read(void *opaque) closesocket(s->fd); s->fd = -1; } else if (size > 0) { + if (s->is_unix) + unix_process_msgfd(chr, &msg); if (s->do_telnetopt) tcp_chr_process_IAC_bytes(chr, s, buf, &size); if (size > 0) qemu_chr_read(chr, buf, size); + if (s->msgfd != -1) { + close(s->msgfd); + s->msgfd = -1; + } } } @@ -2105,12 +2153,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, s->connected = 0; s->fd = -1; s->listen_fd = -1; + s->msgfd = -1; s->is_unix = is_unix; s->do_nodelay = do_nodelay && !is_unix; chr->opaque = s; chr->chr_write = tcp_chr_write; chr->chr_close = tcp_chr_close; + chr->get_msgfd = tcp_get_msgfd; if (is_listen) { s->listen_fd = fd; diff --git a/qemu-char.h b/qemu-char.h index e1aa8db..77d4eda 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -51,6 +51,7 @@ struct CharDriverState { int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); void (*chr_update_read_handler)(struct CharDriverState *s); int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); + int (*get_msgfd)(struct CharDriverState *s); IOEventHandler *chr_event; IOCanRWHandler *chr_can_read; IOReadHandler *chr_read; @@ -81,6 +82,7 @@ void qemu_chr_reset(CharDriverState *s); void qemu_chr_initial_reset(void); int qemu_chr_can_read(CharDriverState *s); void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); +int qemu_chr_get_msgfd(CharDriverState *s); void qemu_chr_accept_input(CharDriverState *s); void qemu_chr_info(Monitor *mon); -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 3/3] Add support for fd=msgfd for tap and socket networking 2009-07-06 17:31 ` [Qemu-devel] [PATCH 2/3] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin @ 2009-07-06 17:32 ` Mark McLoughlin 0 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-06 17:32 UTC (permalink / raw) To: qemu-devel This allows a program to initialize a host networking device using a file descriptor passed over a unix monitor socket. If the programs does e.g. "host_net_add tap fd=msgfd" it must pass a file descriptor as part of that same message via SCM_RIGHTS ancillary data. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- net.c | 39 ++++++++++++++++++++++++++++++++++----- 1 files changed, 34 insertions(+), 5 deletions(-) diff --git a/net.c b/net.c index 001ebcb..0bb8b52 100644 --- a/net.c +++ b/net.c @@ -2388,6 +2388,30 @@ void qemu_check_nic_model_list(NICInfo *nd, const char * const *models, exit(exit_status); } +static int net_handle_fd_param(Monitor *mon, const char *param) +{ + if (!strcmp(param, "msgfd")) { + int fd; + + fd = monitor_get_msgfd(mon); + if (fd == -1) { + config_error(mon, "No file descriptor found in ancillary data\n"); + return -1; + } + + fd = dup(fd); + if (fd == -1) { + config_error(mon, "Failed to dup() file descriptor: %s\n", + strerror(errno)); + return -1; + } + + return fd; + } else { + return strtol(param, NULL, 0); + } +} + int net_client_init(Monitor *mon, const char *device, const char *p) { char buf[1024]; @@ -2625,12 +2649,15 @@ int net_client_init(Monitor *mon, const char *device, const char *p) static const char * const fd_params[] = { "vlan", "name", "fd", "sndbuf", NULL }; + ret = -1; if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) { config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); - ret = -1; goto out; } - fd = strtol(buf, NULL, 0); + fd = net_handle_fd_param(mon, buf); + if (fd == -1) { + goto out; + } fcntl(fd, F_SETFL, O_NONBLOCK); s = net_tap_fd_init(vlan, device, name, fd); } else { @@ -2670,13 +2697,15 @@ int net_client_init(Monitor *mon, const char *device, const char *p) "vlan", "name", "fd", NULL }; int fd; + ret = -1; if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) { config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); - ret = -1; goto out; } - fd = strtol(buf, NULL, 0); - ret = -1; + fd = net_handle_fd_param(mon, buf); + if (fd == -1) { + goto out; + } if (net_socket_fd_init(vlan, device, name, fd, 1)) ret = 0; } else if (get_param_value(buf, sizeof(buf), "listen", p) > 0) { -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors 2009-07-06 17:30 [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors Mark McLoughlin 2009-07-06 17:30 ` [Qemu-devel] [PATCH 1/3] Make tcp_chr_read() use recvmsg() Mark McLoughlin @ 2009-07-07 5:28 ` Avi Kivity 2009-07-07 7:43 ` Mark McLoughlin 1 sibling, 1 reply; 53+ messages in thread From: Avi Kivity @ 2009-07-07 5:28 UTC (permalink / raw) To: Mark McLoughlin; +Cc: qemu-devel On 07/06/2009 08:30 PM, Mark McLoughlin wrote: > Hi, > You can pass file descriptors to qemu via the command line using '-net > tap,fd=' or '-net socket,tap='. However, you cannot currently do this > via the monitor. > > libvirt always configures tap interfaces before passing them to qemu. > One reason for this is to allow libvirtd to have privileges > to /dev/net/tun without allowing qemu those privileges. Because of this, > libvirt currently does not support NIC hotplug for qemu. > > The following three patches add support for passing a file descriptor > to the monitor command by allowing file descriptors to be received over > monitor commands on a unix socket. > > I'm a great fan of SCM_RIGHTS. To make it easier to use in more commands, I think it makes sense to have a separate command to pass the fd: (qemu) getfd foo (qemu) getfd bar (qemu) getfd baz (qemu) pci_add ...,fd=foo (qemu) pci_add ...,fd=bar ...,fd=baz A closefd command would be needed to deal with errors. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors 2009-07-07 5:28 ` [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors Avi Kivity @ 2009-07-07 7:43 ` Mark McLoughlin 2009-07-07 7:52 ` Avi Kivity 0 siblings, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-07 7:43 UTC (permalink / raw) To: Avi Kivity; +Cc: qemu-devel On Tue, 2009-07-07 at 08:28 +0300, Avi Kivity wrote: > On 07/06/2009 08:30 PM, Mark McLoughlin wrote: > > Hi, > > You can pass file descriptors to qemu via the command line using '-net > > tap,fd=' or '-net socket,tap='. However, you cannot currently do this > > via the monitor. > > > > libvirt always configures tap interfaces before passing them to qemu. > > One reason for this is to allow libvirtd to have privileges > > to /dev/net/tun without allowing qemu those privileges. Because of this, > > libvirt currently does not support NIC hotplug for qemu. > > > > The following three patches add support for passing a file descriptor > > to the monitor command by allowing file descriptors to be received over > > monitor commands on a unix socket. > > > > > > I'm a great fan of SCM_RIGHTS. To make it easier to use in more > commands, I think it makes sense to have a separate command to pass the fd: > > (qemu) getfd foo > (qemu) getfd bar > (qemu) getfd baz > (qemu) pci_add ...,fd=foo > (qemu) pci_add ...,fd=bar ...,fd=baz > > A closefd command would be needed to deal with errors. Nice idea, certainly. However, since it's only currently useful for tap/socket networking, I'm happier with not adding two new monitor commands and only supporting a single fd for now. Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors 2009-07-07 7:43 ` Mark McLoughlin @ 2009-07-07 7:52 ` Avi Kivity 2009-07-07 8:13 ` Mark McLoughlin 0 siblings, 1 reply; 53+ messages in thread From: Avi Kivity @ 2009-07-07 7:52 UTC (permalink / raw) To: Mark McLoughlin; +Cc: qemu-devel On 07/07/2009 10:43 AM, Mark McLoughlin wrote: > >> (qemu) getfd foo >> (qemu) getfd bar >> (qemu) getfd baz >> (qemu) pci_add ...,fd=foo >> (qemu) pci_add ...,fd=bar ...,fd=baz >> >> A closefd command would be needed to deal with errors. >> > > Nice idea, certainly. > > However, since it's only currently useful for tap/socket networking, I'm > happier with not adding two new monitor commands and only supporting a > single fd for now. > What happens when we do get more commands? Do we then add the new commands and special-case fd=msgfd ? -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors 2009-07-07 7:52 ` Avi Kivity @ 2009-07-07 8:13 ` Mark McLoughlin 2009-07-07 9:03 ` Avi Kivity 0 siblings, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-07 8:13 UTC (permalink / raw) To: Avi Kivity; +Cc: qemu-devel On Tue, 2009-07-07 at 10:52 +0300, Avi Kivity wrote: > On 07/07/2009 10:43 AM, Mark McLoughlin wrote: > > > >> (qemu) getfd foo > >> (qemu) getfd bar > >> (qemu) getfd baz > >> (qemu) pci_add ...,fd=foo > >> (qemu) pci_add ...,fd=bar ...,fd=baz > >> > >> A closefd command would be needed to deal with errors. > >> > > > > Nice idea, certainly. > > > > However, since it's only currently useful for tap/socket networking, I'm > > happier with not adding two new monitor commands and only supporting a > > single fd for now. > > > > What happens when we do get more commands? Any specific ideas around what else might use it? > Do we then add the new commands and special-case fd=msgfd ? Sounds like a fine plan to me. We could name an fd passed via the current commands as "msgfd" and only the "getfd" command would have the ability to assign another name. Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors 2009-07-07 8:13 ` Mark McLoughlin @ 2009-07-07 9:03 ` Avi Kivity 2009-07-07 10:06 ` Daniel P. Berrange 0 siblings, 1 reply; 53+ messages in thread From: Avi Kivity @ 2009-07-07 9:03 UTC (permalink / raw) To: Mark McLoughlin; +Cc: qemu-devel On 07/07/2009 11:13 AM, Mark McLoughlin wrote: >>> >>> Nice idea, certainly. >>> >>> However, since it's only currently useful for tap/socket networking, I'm >>> happier with not adding two new monitor commands and only supporting a >>> single fd for now. >>> >>> >> What happens when we do get more commands? >> > > Any specific ideas around what else might use it? > Migration, usb, passing around eventfds for interguest communication. >> Do we then add the new commands and special-case fd=msgfd ? >> > > Sounds like a fine plan to me. We could name an fd passed via the > current commands as "msgfd" and only the "getfd" command would have the > ability to assign another name. > If we can't see ahead, it's fine to accumulate cruft. When we can however we should avoid it. The external interfaces are complicated enough. -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors 2009-07-07 9:03 ` Avi Kivity @ 2009-07-07 10:06 ` Daniel P. Berrange 2009-07-08 14:56 ` Mark McLoughlin 0 siblings, 1 reply; 53+ messages in thread From: Daniel P. Berrange @ 2009-07-07 10:06 UTC (permalink / raw) To: Avi Kivity; +Cc: Mark McLoughlin, qemu-devel On Tue, Jul 07, 2009 at 12:03:18PM +0300, Avi Kivity wrote: > On 07/07/2009 11:13 AM, Mark McLoughlin wrote: > >>> > >>>Nice idea, certainly. > >>> > >>>However, since it's only currently useful for tap/socket networking, I'm > >>>happier with not adding two new monitor commands and only supporting a > >>>single fd for now. > >>> > >>> > >>What happens when we do get more commands? > >> > > > >Any specific ideas around what else might use it? > > > > Migration, usb, passing around eventfds for interguest communication. I must say the idea of being able to pass a FD for migration would be very nice. We currently have to open a localhost TCP port and tell QEMU to connect to is, which is less than desirable for security since we cannot guarentee the process we want is the one actually connecting. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors 2009-07-07 10:06 ` Daniel P. Berrange @ 2009-07-08 14:56 ` Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 1/5] Make tcp_chr_read() use recvmsg() Mark McLoughlin 0 siblings, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-08 14:56 UTC (permalink / raw) To: Daniel P. Berrange; +Cc: Avi Kivity, qemu-devel On Tue, 2009-07-07 at 11:06 +0100, Daniel P. Berrange wrote: > On Tue, Jul 07, 2009 at 12:03:18PM +0300, Avi Kivity wrote: > > On 07/07/2009 11:13 AM, Mark McLoughlin wrote: > > >>> > > >>>Nice idea, certainly. > > >>> > > >>>However, since it's only currently useful for tap/socket networking, I'm > > >>>happier with not adding two new monitor commands and only supporting a > > >>>single fd for now. > > >>> > > >>> > > >>What happens when we do get more commands? > > >> > > > > > >Any specific ideas around what else might use it? > > > > > > > Migration, usb, passing around eventfds for interguest communication. > > I must say the idea of being able to pass a FD for migration would be > very nice. We currently have to open a localhost TCP port and tell QEMU > to connect to is, which is less than desirable for security since we > cannot guarentee the process we want is the one actually connecting. Okay, I'm sold - following up with a version with getfd/closefd. Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 1/5] Make tcp_chr_read() use recvmsg() 2009-07-08 14:56 ` Mark McLoughlin @ 2009-07-08 14:57 ` Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin 0 siblings, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-08 14:57 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- qemu-char.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 287e0cd..e0d7220 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -1911,15 +1911,25 @@ static void tcp_chr_read(void *opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr->opaque; + struct msghdr msg = { 0, }; + struct iovec iov[1]; uint8_t buf[1024]; int len, size; if (!s->connected || s->max_size <= 0) return; + len = sizeof(buf); if (len > s->max_size) len = s->max_size; - size = recv(s->fd, (void *)buf, len, 0); + + iov[0].iov_base = buf; + iov[0].iov_len = len; + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + size = recvmsg(s->fd, &msg, 0); if (size == 0) { /* connection closed */ s->connected = 0; -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices 2009-07-08 14:57 ` [Qemu-devel] [PATCH 1/5] Make tcp_chr_read() use recvmsg() Mark McLoughlin @ 2009-07-08 14:57 ` Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Mark McLoughlin 2009-07-08 15:25 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Avi Kivity 0 siblings, 2 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-08 14:57 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin If a file descriptor is passed via a message with SCM_RIGHTS ancillary data on a unix socket, store the file descriptor for use in the chr_read() handler. Close the file descriptor if it was not used. The qemu_chr_get_msgfd() API provides access to the passed descriptor. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- qemu-char.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-char.h | 2 ++ 2 files changed, 52 insertions(+), 0 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index e0d7220..f06a614 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) s->chr_read(s->handler_opaque, buf, len); } +int qemu_chr_get_msgfd(CharDriverState *s) +{ + return s->get_msgfd ? s->get_msgfd(s) : -1; +} + void qemu_chr_accept_input(CharDriverState *s) { if (s->chr_accept_input) @@ -1832,6 +1837,7 @@ typedef struct { int do_telnetopt; int do_nodelay; int is_unix; + int msgfd; } TCPCharDriver; static void tcp_chr_accept(void *opaque); @@ -1907,12 +1913,46 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr, *size = j; } +static int tcp_get_msgfd(CharDriverState *chr) +{ + TCPCharDriver *s = chr->opaque; + + return s->msgfd; +} + +static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg) +{ + TCPCharDriver *s = chr->opaque; + struct cmsghdr *cmsg; + + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { + int fd; + + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || + cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) + continue; + + fd = *((int *)CMSG_DATA(cmsg)); + if (fd < 0) + continue; + + if (s->msgfd != -1) + close(s->msgfd); + s->msgfd = fd; + } +} + static void tcp_chr_read(void *opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr->opaque; struct msghdr msg = { 0, }; struct iovec iov[1]; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(int))]; + } msg_control; uint8_t buf[1024]; int len, size; @@ -1928,6 +1968,8 @@ static void tcp_chr_read(void *opaque) msg.msg_iov = iov; msg.msg_iovlen = 1; + msg.msg_control = &msg_control; + msg.msg_controllen = sizeof(msg_control); size = recvmsg(s->fd, &msg, 0); if (size == 0) { @@ -1940,10 +1982,16 @@ static void tcp_chr_read(void *opaque) closesocket(s->fd); s->fd = -1; } else if (size > 0) { + if (s->is_unix) + unix_process_msgfd(chr, &msg); if (s->do_telnetopt) tcp_chr_process_IAC_bytes(chr, s, buf, &size); if (size > 0) qemu_chr_read(chr, buf, size); + if (s->msgfd != -1) { + close(s->msgfd); + s->msgfd = -1; + } } } @@ -2105,12 +2153,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, s->connected = 0; s->fd = -1; s->listen_fd = -1; + s->msgfd = -1; s->is_unix = is_unix; s->do_nodelay = do_nodelay && !is_unix; chr->opaque = s; chr->chr_write = tcp_chr_write; chr->chr_close = tcp_chr_close; + chr->get_msgfd = tcp_get_msgfd; if (is_listen) { s->listen_fd = fd; diff --git a/qemu-char.h b/qemu-char.h index e1aa8db..77d4eda 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -51,6 +51,7 @@ struct CharDriverState { int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); void (*chr_update_read_handler)(struct CharDriverState *s); int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); + int (*get_msgfd)(struct CharDriverState *s); IOEventHandler *chr_event; IOCanRWHandler *chr_can_read; IOReadHandler *chr_read; @@ -81,6 +82,7 @@ void qemu_chr_reset(CharDriverState *s); void qemu_chr_initial_reset(void); int qemu_chr_can_read(CharDriverState *s); void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); +int qemu_chr_get_msgfd(CharDriverState *s); void qemu_chr_accept_input(CharDriverState *s); void qemu_chr_info(Monitor *mon); -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 14:57 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin @ 2009-07-08 14:57 ` Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 4/5] Add monitor_get_fd() command for fetching named fds Mark McLoughlin 2009-07-08 15:26 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Avi Kivity 2009-07-08 15:25 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Avi Kivity 1 sibling, 2 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-08 14:57 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin Add monitor commands to support passing file descriptors via SCM_RIGHTS. getfd assigns the passed file descriptor a name for use with other monitor commands. closefd allows passed file descriptors to be closed. If a monitor command actually uses a named file descriptor, closefd will not be required. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- monitor.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-monitor.hx | 18 ++++++++++++++ 2 files changed, 87 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index bad79fe..85fa137 100644 --- a/monitor.c +++ b/monitor.c @@ -70,6 +70,14 @@ typedef struct mon_cmd_t { const char *help; } mon_cmd_t; +/* file descriptors passed via SCM_RIGHTS */ +typedef struct mon_fd_t mon_fd_t; +struct mon_fd_t { + char *name; + int fd; + LIST_ENTRY(mon_fd_t) next; +}; + struct Monitor { CharDriverState *chr; int flags; @@ -80,6 +88,7 @@ struct Monitor { CPUState *mon_cpu; BlockDriverCompletionFunc *password_completion_cb; void *password_opaque; + LIST_HEAD(,mon_fd_t) fds; LIST_ENTRY(Monitor) entry; }; @@ -1677,6 +1686,66 @@ static void do_acl_remove(Monitor *mon, const char *aclname, const char *match) } } +static void do_getfd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + int fd; + + fd = qemu_chr_get_msgfd(mon->chr); + if (fd == -1) { + monitor_printf(mon, "getfd: no file descriptor supplied via SCM_RIGHTS\n"); + return; + } + + if (qemu_isdigit(fdname[0])) { + monitor_printf(mon, "getfd: monitor names may not begin with a number\n"); + return; + } + + fd = dup(fd); + if (fd == -1) { + monitor_printf(mon, "Failed to dup() file descriptor: %s\n", + strerror(errno)); + return; + } + + LIST_FOREACH(monfd, &mon->fds, next) { + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + close(monfd->fd); + monfd->fd = fd; + return; + } + + monfd = qemu_mallocz(sizeof(mon_fd_t)); + monfd->name = qemu_strdup(fdname); + monfd->fd = fd; + + LIST_INSERT_HEAD(&mon->fds, monfd, next); +} + +static void do_closefd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + + LIST_FOREACH(monfd, &mon->fds, next) { + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + LIST_REMOVE(monfd, next); + close(monfd->fd); + qemu_free(monfd->name); + qemu_free(monfd); + return; + } + + monitor_printf(mon, "Failed to find file descriptor named %s\n", + fdname); +} + static const mon_cmd_t mon_cmds[] = { #include "qemu-monitor.h" { NULL, NULL, }, diff --git a/qemu-monitor.hx b/qemu-monitor.hx index dc10b75..2279012 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -615,6 +615,24 @@ Remove all matches from the access control list, and set the default policy back to @code{deny}. ETEXI + { "getfd", "s", do_getfd, "getfd name", + "receive a file descriptor via SCM rights and assign it a name" }, +STEXI +@item getfd @var{fdname} +If a file descriptor is passed alongside this command using the SCM_RIGHTS +mechanism on unix sockets, it is stored using the name @var{fdname} for +later use by other monitor commands. +ETEXI + + { "closefd", "s", do_closefd, "closefd name", + "close a file descriptor previously passed via SCM rights" }, +STEXI +@item closefd @var{fdname} +Close the file descriptor previously assigned to @var{fdname} using the +@code{getfd} command. This is only needed if the file descriptor was never +used by another monitor command. +ETEXI + STEXI @end table ETEXI -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 4/5] Add monitor_get_fd() command for fetching named fds 2009-07-08 14:57 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Mark McLoughlin @ 2009-07-08 14:57 ` Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 5/5] Add support for fd=name to tap and socket networking Mark McLoughlin 2009-07-08 15:26 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Avi Kivity 1 sibling, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-08 14:57 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- monitor.c | 24 ++++++++++++++++++++++++ monitor.h | 2 ++ 2 files changed, 26 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index 85fa137..38e0da5 100644 --- a/monitor.c +++ b/monitor.c @@ -1746,6 +1746,30 @@ static void do_closefd(Monitor *mon, const char *fdname) fdname); } +int monitor_get_fd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + + LIST_FOREACH(monfd, &mon->fds, next) { + int fd; + + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + fd = monfd->fd; + + /* caller takes ownership of fd */ + LIST_REMOVE(monfd, next); + qemu_free(monfd->name); + qemu_free(monfd); + + return fd; + } + + return -1; +} + static const mon_cmd_t mon_cmds[] = { #include "qemu-monitor.h" { NULL, NULL, }, diff --git a/monitor.h b/monitor.h index 13e8cc7..f6a43c0 100644 --- a/monitor.h +++ b/monitor.h @@ -20,6 +20,8 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, BlockDriverCompletionFunc *completion_cb, void *opaque); +int monitor_get_fd(Monitor *mon, const char *fdname); + void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap); void monitor_printf(Monitor *mon, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 5/5] Add support for fd=name to tap and socket networking 2009-07-08 14:57 ` [Qemu-devel] [PATCH 4/5] Add monitor_get_fd() command for fetching named fds Mark McLoughlin @ 2009-07-08 14:57 ` Mark McLoughlin 0 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-08 14:57 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin This allows a program to initialize a host networking device using a file descriptor passed over a unix monitor socket. The program must first pass the file descriptor using SCM_RIGHTS ancillary data with the getfd monitor command. It then may do "host_net_add tap fd=name" to use the named file descriptor. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- net.c | 42 +++++++++++++++++++++++++++++++++++------- 1 files changed, 35 insertions(+), 7 deletions(-) diff --git a/net.c b/net.c index 001ebcb..a97abb4 100644 --- a/net.c +++ b/net.c @@ -2388,6 +2388,23 @@ void qemu_check_nic_model_list(NICInfo *nd, const char * const *models, exit(exit_status); } +static int net_handle_fd_param(Monitor *mon, const char *param) +{ + if (!qemu_isdigit(param[0])) { + int fd; + + fd = monitor_get_fd(mon, param); + if (fd == -1) { + config_error(mon, "No file descriptor named %s found", param); + return -1; + } + + return fd; + } else { + return strtol(param, NULL, 0); + } +} + int net_client_init(Monitor *mon, const char *device, const char *p) { char buf[1024]; @@ -2625,14 +2642,20 @@ int net_client_init(Monitor *mon, const char *device, const char *p) static const char * const fd_params[] = { "vlan", "name", "fd", "sndbuf", NULL }; + ret = -1; if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) { config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); - ret = -1; goto out; } - fd = strtol(buf, NULL, 0); + fd = net_handle_fd_param(mon, buf); + if (fd == -1) { + goto out; + } fcntl(fd, F_SETFL, O_NONBLOCK); s = net_tap_fd_init(vlan, device, name, fd); + if (!s) { + close(fd); + } } else { static const char * const tap_params[] = { "vlan", "name", "ifname", "script", "downscript", "sndbuf", NULL @@ -2670,15 +2693,20 @@ int net_client_init(Monitor *mon, const char *device, const char *p) "vlan", "name", "fd", NULL }; int fd; + ret = -1; if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) { config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); - ret = -1; goto out; } - fd = strtol(buf, NULL, 0); - ret = -1; - if (net_socket_fd_init(vlan, device, name, fd, 1)) - ret = 0; + fd = net_handle_fd_param(mon, buf); + if (fd == -1) { + goto out; + } + if (!net_socket_fd_init(vlan, device, name, fd, 1)) { + close(fd); + goto out; + } + ret = 0; } else if (get_param_value(buf, sizeof(buf), "listen", p) > 0) { static const char * const listen_params[] = { "vlan", "name", "listen", NULL -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 14:57 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 4/5] Add monitor_get_fd() command for fetching named fds Mark McLoughlin @ 2009-07-08 15:26 ` Avi Kivity 2009-07-08 16:03 ` Mark McLoughlin 1 sibling, 1 reply; 53+ messages in thread From: Avi Kivity @ 2009-07-08 15:26 UTC (permalink / raw) To: Mark McLoughlin; +Cc: qemu-devel On 07/08/2009 05:57 PM, Mark McLoughlin wrote: > Add monitor commands to support passing file descriptors via > SCM_RIGHTS. > > getfd assigns the passed file descriptor a name for use with other > monitor commands. > > closefd allows passed file descriptors to be closed. If a monitor > command actually uses a named file descriptor, closefd will not be > required. > > > > @@ -70,6 +70,14 @@ typedef struct mon_cmd_t { > const char *help; > } mon_cmd_t; > > +/* file descriptors passed via SCM_RIGHTS */ > +typedef struct mon_fd_t mon_fd_t; > +struct mon_fd_t { > + char *name; > + int fd; > + LIST_ENTRY(mon_fd_t) next; > +}; > + > The _t namespace is reserved by posix and not used for structures in qemu anyway. I see there's precedent a few lines above but let's not introduce new violations. > + > + fd = dup(fd); > Why? -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 15:26 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Avi Kivity @ 2009-07-08 16:03 ` Mark McLoughlin 2009-07-08 16:15 ` Avi Kivity 0 siblings, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-08 16:03 UTC (permalink / raw) To: Avi Kivity; +Cc: qemu-devel On Wed, 2009-07-08 at 18:26 +0300, Avi Kivity wrote: > On 07/08/2009 05:57 PM, Mark McLoughlin wrote: > > Add monitor commands to support passing file descriptors via > > SCM_RIGHTS. > > > > getfd assigns the passed file descriptor a name for use with other > > monitor commands. > > > > closefd allows passed file descriptors to be closed. If a monitor > > command actually uses a named file descriptor, closefd will not be > > required. > > > > > > > > > @@ -70,6 +70,14 @@ typedef struct mon_cmd_t { > > const char *help; > > } mon_cmd_t; > > > > +/* file descriptors passed via SCM_RIGHTS */ > > +typedef struct mon_fd_t mon_fd_t; > > +struct mon_fd_t { > > + char *name; > > + int fd; > > + LIST_ENTRY(mon_fd_t) next; > > +}; > > + > > > > The _t namespace is reserved by posix and not used for structures in > qemu anyway. I see there's precedent a few lines above but let's not > introduce new violations. Bah, where there's a number of different styles used in a code base, and where there's no guidelines in CODING_STYLE, I tend to stick with the style of the code I'm editing. And, in this case, the closest structure definition used this style. > > + > > + fd = dup(fd); > > > > Why? Because it gets closed again after the chr_read() handler finishes. I guess we could make qemu_chr_get_msgfd() pass ownership of the fd to the caller. Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 16:03 ` Mark McLoughlin @ 2009-07-08 16:15 ` Avi Kivity 2009-07-08 18:08 ` Anthony Liguori 0 siblings, 1 reply; 53+ messages in thread From: Avi Kivity @ 2009-07-08 16:15 UTC (permalink / raw) To: Mark McLoughlin; +Cc: qemu-devel On 07/08/2009 07:03 PM, Mark McLoughlin wrote: >> The _t namespace is reserved by posix and not used for structures in >> qemu anyway. I see there's precedent a few lines above but let's not >> introduce new violations. >> > > Bah, where there's a number of different styles used in a code base, and > where there's no guidelines in CODING_STYLE, I tend to stick with the > style of the code I'm editing. And, in this case, the closest structure > definition used this style. > > Naming is one of the few things CODING_STYLE does talk about. >>> + >>> + fd = dup(fd); >>> >>> >> Why? >> > > Because it gets closed again after the chr_read() handler finishes. I > guess we could make qemu_chr_get_msgfd() pass ownership of the fd to the > caller. > I'd prefer the communication layer to queue fds and getfd to dequeue them. -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 16:15 ` Avi Kivity @ 2009-07-08 18:08 ` Anthony Liguori 2009-07-08 18:11 ` Avi Kivity 0 siblings, 1 reply; 53+ messages in thread From: Anthony Liguori @ 2009-07-08 18:08 UTC (permalink / raw) To: Avi Kivity; +Cc: Mark McLoughlin, qemu-devel Avi Kivity wrote: > I'd prefer the communication layer to queue fds and getfd to dequeue > them. How many do you queue? The correct answer is one, btw ;-) Regards, Anthony Liguori ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 18:08 ` Anthony Liguori @ 2009-07-08 18:11 ` Avi Kivity 2009-07-08 18:21 ` Anthony Liguori 0 siblings, 1 reply; 53+ messages in thread From: Avi Kivity @ 2009-07-08 18:11 UTC (permalink / raw) To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel On 07/08/2009 09:08 PM, Anthony Liguori wrote: > Avi Kivity wrote: >> I'd prefer the communication layer to queue fds and getfd to dequeue >> them. > > How many do you queue? The correct answer is one, btw ;-) You queue as many as you receive, and you dequeue as many getfd commands as you get. Nothing prevents the client from sending two getfd commands in a single packet. We can either support it or start writing detailed documentation and handle the bug reports when people don't read it. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 18:11 ` Avi Kivity @ 2009-07-08 18:21 ` Anthony Liguori 2009-07-08 18:32 ` Avi Kivity 0 siblings, 1 reply; 53+ messages in thread From: Anthony Liguori @ 2009-07-08 18:21 UTC (permalink / raw) To: Avi Kivity; +Cc: Mark McLoughlin, qemu-devel Avi Kivity wrote: > On 07/08/2009 09:08 PM, Anthony Liguori wrote: >> Avi Kivity wrote: >>> I'd prefer the communication layer to queue fds and getfd to dequeue >>> them. >> >> How many do you queue? The correct answer is one, btw ;-) > > You queue as many as you receive, and you dequeue as many getfd > commands as you get. Then someone can connect to the monitor and consume an arbitrary number of fds? I'd be very concerned about the potential to leak fds within QEMU from a poorly written client. Seems like a very easy mistake to make. > Nothing prevents the client from sending two getfd commands in a > single packet. We can either support it or start writing detailed > documentation and handle the bug reports when people don't read it. What would a client do that would result in this happening? It's really a contrived example when you think about it pragmatically (at least given today's monitor). Regards, Anthony Liguori ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 18:21 ` Anthony Liguori @ 2009-07-08 18:32 ` Avi Kivity 2009-07-08 18:50 ` Anthony Liguori 0 siblings, 1 reply; 53+ messages in thread From: Avi Kivity @ 2009-07-08 18:32 UTC (permalink / raw) To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel On 07/08/2009 09:21 PM, Anthony Liguori wrote: > Avi Kivity wrote: >> On 07/08/2009 09:08 PM, Anthony Liguori wrote: >>> Avi Kivity wrote: >>>> I'd prefer the communication layer to queue fds and getfd to >>>> dequeue them. >>> >>> How many do you queue? The correct answer is one, btw ;-) >> >> You queue as many as you receive, and you dequeue as many getfd >> commands as you get. > > Then someone can connect to the monitor and consume an arbitrary > number of fds? I'd be very concerned about the potential to leak fds > within QEMU from a poorly written client. Seems like a very easy > mistake to make. Well, that's intrinsic to the getfd command. We could limit it by saying we support a set number of fds, or even give them fixed names. > >> Nothing prevents the client from sending two getfd commands in a >> single packet. We can either support it or start writing detailed >> documentation and handle the bug reports when people don't read it. > > What would a client do that would result in this happening? It's > really a contrived example when you think about it pragmatically (at > least given today's monitor). I am in fact thinking of tomorrow's monitor. If indeed we follow an rpc model, it should be quite easy to have multiple threads (each doing an unrelated task) each issuing a series of commands and processing the replies. There would be a lock protecting the socket, but there would be no reason to limit the number of outstanding commands. I think that's a perfectly reasonable way to write a client. If the client is written in a high level language it's also reasonable that some buffering would take place and you'd see a single packet containing multiple commands, or a command split into multiple packets. Therefore I'd like to avoid any assumptions in this area. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 18:32 ` Avi Kivity @ 2009-07-08 18:50 ` Anthony Liguori 2009-07-08 19:52 ` Avi Kivity 0 siblings, 1 reply; 53+ messages in thread From: Anthony Liguori @ 2009-07-08 18:50 UTC (permalink / raw) To: Avi Kivity; +Cc: Mark McLoughlin, qemu-devel Avi Kivity wrote: > On 07/08/2009 09:21 PM, Anthony Liguori wrote: >> Then someone can connect to the monitor and consume an arbitrary >> number of fds? I'd be very concerned about the potential to leak fds >> within QEMU from a poorly written client. Seems like a very easy >> mistake to make. > > Well, that's intrinsic to the getfd command. We could limit it by > saying we support a set number of fds, or even give them fixed names. So what's the set number and why isn't 1 a reasonable fixed number? >>> Nothing prevents the client from sending two getfd commands in a >>> single packet. We can either support it or start writing detailed >>> documentation and handle the bug reports when people don't read it. >> >> What would a client do that would result in this happening? It's >> really a contrived example when you think about it pragmatically (at >> least given today's monitor). > > I am in fact thinking of tomorrow's monitor. Indeed, I figured as much :-) > If indeed we follow an rpc model, it should be quite easy to have > multiple threads (each doing an unrelated task) each issuing a series > of commands and processing the replies. There would be a lock > protecting the socket, but there would be no reason to limit the > number of outstanding commands. I think that's a perfectly reasonable > way to write a client. You can't just use a lock on the socket for transmit because you have to deal with partial transmissions and the subsequent queuing. You need a single queue mechanism shared by all writers and you need writers to submit the full rpcs so that they can be queued in the proper order. When we get to the point of the RPC model though, we'll have one monitor state for each asynchronous message we're processing. I contend that we only ever want to pass a single fd per command so if we stick with queueing 1 fd per monitor today, it'll map quite nicely to how we would handle things in the RPC model. > If the client is written in a high level language it's also reasonable > that some buffering would take place and you'd see a single packet > containing multiple commands, or a command split into multiple > packets. Therefore I'd like to avoid any assumptions in this area. That misses the point though. We process one command at a time in the monitor so we only need to buffer one fd at a time. When we start to process multiple commands at once in the monitor, we'll do so with multiple monitor states and we'll want to have one fd per monitor state. Message boundaries really don't matter. Regards, Anthony Liguori ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 18:50 ` Anthony Liguori @ 2009-07-08 19:52 ` Avi Kivity 2009-07-11 1:12 ` Jamie Lokier 2009-07-21 16:40 ` Mark McLoughlin 0 siblings, 2 replies; 53+ messages in thread From: Avi Kivity @ 2009-07-08 19:52 UTC (permalink / raw) To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel On 07/08/2009 09:50 PM, Anthony Liguori wrote: > Avi Kivity wrote: >> On 07/08/2009 09:21 PM, Anthony Liguori wrote: >>> Then someone can connect to the monitor and consume an arbitrary >>> number of fds? I'd be very concerned about the potential to leak >>> fds within QEMU from a poorly written client. Seems like a very >>> easy mistake to make. >> >> Well, that's intrinsic to the getfd command. We could limit it by >> saying we support a set number of fds, or even give them fixed names. > > So what's the set number Good question. > and why isn't 1 a reasonable fixed number? > Parallel execution of commands (which I don't propose anytime soon) and commands that accept multiple fds (maybe a command that accepts an irqfd/ioeventfd pair from another guest and exposes the pair to the guest as part of a pci device). > >> If indeed we follow an rpc model, it should be quite easy to have >> multiple threads (each doing an unrelated task) each issuing a series >> of commands and processing the replies. There would be a lock >> protecting the socket, but there would be no reason to limit the >> number of outstanding commands. I think that's a perfectly >> reasonable way to write a client. > > You can't just use a lock on the socket for transmit because you have > to deal with partial transmissions and the subsequent queuing. You > need a single queue mechanism shared by all writers and you need > writers to submit the full rpcs so that they can be queued in the > proper order. > > When we get to the point of the RPC model though, we'll have one > monitor state for each asynchronous message we're processing. I > contend that we only ever want to pass a single fd per command so if > we stick with queueing 1 fd per monitor today, it'll map quite nicely > to how we would handle things in the RPC model. I'm thinking about the client, not qemu, but you're right that the fd and the message that refer to it must be in a single transaction. So at the qemu_chr level, we'll never queue more than one fd. > >> If the client is written in a high level language it's also >> reasonable that some buffering would take place and you'd see a >> single packet containing multiple commands, or a command split into >> multiple packets. Therefore I'd like to avoid any assumptions in >> this area. > > That misses the point though. We process one command at a time in the > monitor so we only need to buffer one fd at a time. When we start to > process multiple commands at once in the monitor, we'll do so with > multiple monitor states and we'll want to have one fd per monitor state. Again I'm thinking of the client. If two client threads issue commands in parallel there'd be >1 fds on the wire. But qemu can consume them sequentially so I agree queue may hold just a single fd. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 19:52 ` Avi Kivity @ 2009-07-11 1:12 ` Jamie Lokier 2009-07-21 16:40 ` Mark McLoughlin 1 sibling, 0 replies; 53+ messages in thread From: Jamie Lokier @ 2009-07-11 1:12 UTC (permalink / raw) To: Avi Kivity; +Cc: Mark McLoughlin, qemu-devel Avi Kivity wrote: > >That misses the point though. We process one command at a time in the > >monitor so we only need to buffer one fd at a time. When we start to > >process multiple commands at once in the monitor, we'll do so with > >multiple monitor states and we'll want to have one fd per monitor state. > > Again I'm thinking of the client. If two client threads issue commands > in parallel there'd be >1 fds on the wire. But qemu can consume them > sequentially so I agree queue may hold just a single fd. No, even though QEMU processes commands sequentially. If the client sends "command_1_with_fd" + FD1 "command_2_with_fd" + FD2 and then waits for the results of commands 1 and 2, QEMU calls recvmsg() and will read "command_1_with_fd\r\ncommand_2_with_fd\r\n" + FD1 + FD2 unless QEMU is consuming only one byte at a time from the socket, and dispatching commands as soon as it sees the line terminator. If QEMU reads more than one byte at a time, and the client sends more than one command without waiting for the previous one's result, QEMU needs to buffer more FDs otherwise some will get lost. -- Jamie ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-08 19:52 ` Avi Kivity 2009-07-11 1:12 ` Jamie Lokier @ 2009-07-21 16:40 ` Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Make tcp_chr_read() use recvmsg() Mark McLoughlin ` (5 more replies) 1 sibling, 6 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-21 16:40 UTC (permalink / raw) To: Avi Kivity; +Cc: qemu-devel On Wed, 2009-07-08 at 22:52 +0300, Avi Kivity wrote: > On 07/08/2009 09:50 PM, Anthony Liguori wrote: > > Avi Kivity wrote: > >> If the client is written in a high level language it's also > >> reasonable that some buffering would take place and you'd see a > >> single packet containing multiple commands, or a command split into > >> multiple packets. Therefore I'd like to avoid any assumptions in > >> this area. > > > > That misses the point though. We process one command at a time in the > > monitor so we only need to buffer one fd at a time. When we start to > > process multiple commands at once in the monitor, we'll do so with > > multiple monitor states and we'll want to have one fd per monitor state. > > Again I'm thinking of the client. If two client threads issue commands > in parallel there'd be >1 fds on the wire. But qemu can consume them > sequentially so I agree queue may hold just a single fd. Okay, it sounds like these patches didn't get applied for 0.11 because of confusion over the conclusion here. My take on it is that we're all agreed that it's never valid with the current monitor protocol for a client to queue up multiple fds. It's a synchronous protocol, you can't send multiple commands at once. I'll re-post the patches in reply to this. Thanks, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH] Make tcp_chr_read() use recvmsg() 2009-07-21 16:40 ` Mark McLoughlin @ 2009-07-21 16:53 ` Mark McLoughlin 2009-07-21 17:13 ` Blue Swirl 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin ` (4 subsequent siblings) 5 siblings, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-21 16:53 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- qemu-char.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 287e0cd..e0d7220 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -1911,15 +1911,25 @@ static void tcp_chr_read(void *opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr->opaque; + struct msghdr msg = { 0, }; + struct iovec iov[1]; uint8_t buf[1024]; int len, size; if (!s->connected || s->max_size <= 0) return; + len = sizeof(buf); if (len > s->max_size) len = s->max_size; - size = recv(s->fd, (void *)buf, len, 0); + + iov[0].iov_base = buf; + iov[0].iov_len = len; + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + size = recvmsg(s->fd, &msg, 0); if (size == 0) { /* connection closed */ s->connected = 0; -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH] Make tcp_chr_read() use recvmsg() 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Make tcp_chr_read() use recvmsg() Mark McLoughlin @ 2009-07-21 17:13 ` Blue Swirl 2009-07-22 0:00 ` Jamie Lokier 2009-07-22 8:10 ` Mark McLoughlin 0 siblings, 2 replies; 53+ messages in thread From: Blue Swirl @ 2009-07-21 17:13 UTC (permalink / raw) To: Mark McLoughlin; +Cc: qemu-devel On Tue, Jul 21, 2009 at 7:53 PM, Mark McLoughlin<markmc@redhat.com> wrote: > Signed-off-by: Mark McLoughlin <markmc@redhat.com> A quick grep with mingw32 headers didn't find recvmsg. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH] Make tcp_chr_read() use recvmsg() 2009-07-21 17:13 ` Blue Swirl @ 2009-07-22 0:00 ` Jamie Lokier 2009-07-22 8:10 ` Mark McLoughlin 1 sibling, 0 replies; 53+ messages in thread From: Jamie Lokier @ 2009-07-22 0:00 UTC (permalink / raw) To: Blue Swirl; +Cc: Mark McLoughlin, qemu-devel Blue Swirl wrote: > On Tue, Jul 21, 2009 at 7:53 PM, Mark McLoughlin<markmc@redhat.com> wrote: > > Signed-off-by: Mark McLoughlin <markmc@redhat.com> > > A quick grep with mingw32 headers didn't find recvmsg. It's not surprising. Win32 sockets (Winsock) don't have recvmsg, and don't support SCM_RIGHTS. Or even unix domain sockets :-) File descriptors are passed in a different way on Win32. -- Jamie ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH] Make tcp_chr_read() use recvmsg() 2009-07-21 17:13 ` Blue Swirl 2009-07-22 0:00 ` Jamie Lokier @ 2009-07-22 8:10 ` Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 1/5] " Mark McLoughlin ` (4 more replies) 1 sibling, 5 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-22 8:10 UTC (permalink / raw) To: Blue Swirl; +Cc: qemu-devel On Tue, 2009-07-21 at 20:13 +0300, Blue Swirl wrote: > On Tue, Jul 21, 2009 at 7:53 PM, Mark McLoughlin<markmc@redhat.com> wrote: > > Signed-off-by: Mark McLoughlin <markmc@redhat.com> > > A quick grep with mingw32 headers didn't find recvmsg. Thanks, my bad - fixed version coming up. Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 1/5] Make tcp_chr_read() use recvmsg() 2009-07-22 8:10 ` Mark McLoughlin @ 2009-07-22 8:11 ` Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin ` (3 subsequent siblings) 4 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-22 8:11 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin Split out tcp_chr_recv() out of tcp_chr_read() and implement it on non-win32 using recvmsg(). This is needed for a subsequent patch which implements SCM_RIGHTS support. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- qemu-char.c | 25 ++++++++++++++++++++++++- 1 files changed, 24 insertions(+), 1 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 287e0cd..9886228 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -1907,6 +1907,29 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr, *size = j; } +#ifndef WIN32 +static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) +{ + TCPCharDriver *s = chr->opaque; + struct msghdr msg = { 0, }; + struct iovec iov[1]; + + iov[0].iov_base = buf; + iov[0].iov_len = len; + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + return recvmsg(s->fd, &msg, 0); +} +#else +static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) +{ + TCPCharDriver *s = chr->opaque; + return recv(s->fd, buf, len, 0); +} +#endif + static void tcp_chr_read(void *opaque) { CharDriverState *chr = opaque; @@ -1919,7 +1942,7 @@ static void tcp_chr_read(void *opaque) len = sizeof(buf); if (len > s->max_size) len = s->max_size; - size = recv(s->fd, (void *)buf, len, 0); + size = tcp_chr_recv(chr, (void *)buf, len); if (size == 0) { /* connection closed */ s->connected = 0; -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices 2009-07-22 8:10 ` Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 1/5] " Mark McLoughlin @ 2009-07-22 8:11 ` Mark McLoughlin 2009-08-13 16:20 ` Cam Macdonell 2009-07-22 8:11 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Mark McLoughlin ` (2 subsequent siblings) 4 siblings, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-22 8:11 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin If a file descriptor is passed via a message with SCM_RIGHTS ancillary data on a unix socket, store the file descriptor for use in the chr_read() handler. Close the file descriptor if it was not used. The qemu_chr_get_msgfd() API provides access to the passed descriptor. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- qemu-char.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-char.h | 2 ++ 2 files changed, 56 insertions(+), 1 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 9886228..6e2cd31 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) s->chr_read(s->handler_opaque, buf, len); } +int qemu_chr_get_msgfd(CharDriverState *s) +{ + return s->get_msgfd ? s->get_msgfd(s) : -1; +} + void qemu_chr_accept_input(CharDriverState *s) { if (s->chr_accept_input) @@ -1832,6 +1837,7 @@ typedef struct { int do_telnetopt; int do_nodelay; int is_unix; + int msgfd; } TCPCharDriver; static void tcp_chr_accept(void *opaque); @@ -1907,20 +1913,61 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr, *size = j; } +static int tcp_get_msgfd(CharDriverState *chr) +{ + TCPCharDriver *s = chr->opaque; + + return s->msgfd; +} + #ifndef WIN32 +static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg) +{ + TCPCharDriver *s = chr->opaque; + struct cmsghdr *cmsg; + + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { + int fd; + + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || + cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) + continue; + + fd = *((int *)CMSG_DATA(cmsg)); + if (fd < 0) + continue; + + if (s->msgfd != -1) + close(s->msgfd); + s->msgfd = fd; + } +} + static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) { TCPCharDriver *s = chr->opaque; struct msghdr msg = { 0, }; struct iovec iov[1]; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(int))]; + } msg_control; + ssize_t ret; iov[0].iov_base = buf; iov[0].iov_len = len; msg.msg_iov = iov; msg.msg_iovlen = 1; + msg.msg_control = &msg_control; + msg.msg_controllen = sizeof(msg_control); + + ret = recvmsg(s->fd, &msg, 0); + if (ret > 0 && s->is_unix) + unix_process_msgfd(chr, &msg); - return recvmsg(s->fd, &msg, 0); + return ret; } #else static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) @@ -1957,6 +2004,10 @@ static void tcp_chr_read(void *opaque) tcp_chr_process_IAC_bytes(chr, s, buf, &size); if (size > 0) qemu_chr_read(chr, buf, size); + if (s->msgfd != -1) { + close(s->msgfd); + s->msgfd = -1; + } } } @@ -2118,12 +2169,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, s->connected = 0; s->fd = -1; s->listen_fd = -1; + s->msgfd = -1; s->is_unix = is_unix; s->do_nodelay = do_nodelay && !is_unix; chr->opaque = s; chr->chr_write = tcp_chr_write; chr->chr_close = tcp_chr_close; + chr->get_msgfd = tcp_get_msgfd; if (is_listen) { s->listen_fd = fd; diff --git a/qemu-char.h b/qemu-char.h index e1aa8db..77d4eda 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -51,6 +51,7 @@ struct CharDriverState { int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); void (*chr_update_read_handler)(struct CharDriverState *s); int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); + int (*get_msgfd)(struct CharDriverState *s); IOEventHandler *chr_event; IOCanRWHandler *chr_can_read; IOReadHandler *chr_read; @@ -81,6 +82,7 @@ void qemu_chr_reset(CharDriverState *s); void qemu_chr_initial_reset(void); int qemu_chr_can_read(CharDriverState *s); void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); +int qemu_chr_get_msgfd(CharDriverState *s); void qemu_chr_accept_input(CharDriverState *s); void qemu_chr_info(Monitor *mon); -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices 2009-07-22 8:11 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin @ 2009-08-13 16:20 ` Cam Macdonell 2009-08-14 6:38 ` Mark McLoughlin 0 siblings, 1 reply; 53+ messages in thread From: Cam Macdonell @ 2009-08-13 16:20 UTC (permalink / raw) To: Mark McLoughlin; +Cc: qemu-devel Mark McLoughlin wrote: > If a file descriptor is passed via a message with SCM_RIGHTS ancillary > data on a unix socket, store the file descriptor for use in the > chr_read() handler. Close the file descriptor if it was not used. > > The qemu_chr_get_msgfd() API provides access to the passed descriptor. > > Signed-off-by: Mark McLoughlin <markmc@redhat.com> > --- > qemu-char.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- > qemu-char.h | 2 ++ > 2 files changed, 56 insertions(+), 1 deletions(-) > > diff --git a/qemu-char.c b/qemu-char.c > index 9886228..6e2cd31 100644 > --- a/qemu-char.c > +++ b/qemu-char.c > @@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) > s->chr_read(s->handler_opaque, buf, len); > } > > +int qemu_chr_get_msgfd(CharDriverState *s) > +{ > + return s->get_msgfd ? s->get_msgfd(s) : -1; > +} > + > void qemu_chr_accept_input(CharDriverState *s) > { > if (s->chr_accept_input) > @@ -1832,6 +1837,7 @@ typedef struct { > int do_telnetopt; > int do_nodelay; > int is_unix; > + int msgfd; > } TCPCharDriver; > > static void tcp_chr_accept(void *opaque); > @@ -1907,20 +1913,61 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr, > *size = j; > } > > +static int tcp_get_msgfd(CharDriverState *chr) > +{ > + TCPCharDriver *s = chr->opaque; > + > + return s->msgfd; > +} > + > #ifndef WIN32 > +static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg) > +{ > + TCPCharDriver *s = chr->opaque; > + struct cmsghdr *cmsg; > + > + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { > + int fd; > + > + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || > + cmsg->cmsg_level != SOL_SOCKET || > + cmsg->cmsg_type != SCM_RIGHTS) > + continue; > + > + fd = *((int *)CMSG_DATA(cmsg)); > + if (fd < 0) > + continue; > + > + if (s->msgfd != -1) > + close(s->msgfd); > + s->msgfd = fd; > + } > +} > + > static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) > { > TCPCharDriver *s = chr->opaque; > struct msghdr msg = { 0, }; > struct iovec iov[1]; > + union { > + struct cmsghdr cmsg; > + char control[CMSG_SPACE(sizeof(int))]; > + } msg_control; > + ssize_t ret; > > iov[0].iov_base = buf; > iov[0].iov_len = len; > > msg.msg_iov = iov; > msg.msg_iovlen = 1; > + msg.msg_control = &msg_control; > + msg.msg_controllen = sizeof(msg_control); > + > + ret = recvmsg(s->fd, &msg, 0); > + if (ret > 0 && s->is_unix) > + unix_process_msgfd(chr, &msg); > > - return recvmsg(s->fd, &msg, 0); > + return ret; > } > #else > static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len) > @@ -1957,6 +2004,10 @@ static void tcp_chr_read(void *opaque) > tcp_chr_process_IAC_bytes(chr, s, buf, &size); > if (size > 0) > qemu_chr_read(chr, buf, size); > + if (s->msgfd != -1) { > + close(s->msgfd); > + s->msgfd = -1; > + } Hi Mark, I'm trying to understand the intended behaviour here so I can use your patch. In your comments for the patch it reads "store the file descriptor for use in the chr_read() handler. Close the file descriptor if it was not used." It seems that upon returning from the chr_read() handler the descriptor is closed if s->msgfd is not set to -1. Does this mean the handler should set the fd to -1 after retrieving it if the process wants to keep that fd open, otherwise it will be closed when chr_read() returns? Should tcp_get_msgfd() perhaps set s->msgfd to -1 after it is retrieved? Sort of a "read and clear" behaviour? Thanks, Cam > } > } > > @@ -2118,12 +2169,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, > s->connected = 0; > s->fd = -1; > s->listen_fd = -1; > + s->msgfd = -1; > s->is_unix = is_unix; > s->do_nodelay = do_nodelay && !is_unix; > > chr->opaque = s; > chr->chr_write = tcp_chr_write; > chr->chr_close = tcp_chr_close; > + chr->get_msgfd = tcp_get_msgfd; > > if (is_listen) { > s->listen_fd = fd; > diff --git a/qemu-char.h b/qemu-char.h > index e1aa8db..77d4eda 100644 > --- a/qemu-char.h > +++ b/qemu-char.h > @@ -51,6 +51,7 @@ struct CharDriverState { > int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); > void (*chr_update_read_handler)(struct CharDriverState *s); > int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); > + int (*get_msgfd)(struct CharDriverState *s); > IOEventHandler *chr_event; > IOCanRWHandler *chr_can_read; > IOReadHandler *chr_read; > @@ -81,6 +82,7 @@ void qemu_chr_reset(CharDriverState *s); > void qemu_chr_initial_reset(void); > int qemu_chr_can_read(CharDriverState *s); > void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); > +int qemu_chr_get_msgfd(CharDriverState *s); > void qemu_chr_accept_input(CharDriverState *s); > void qemu_chr_info(Monitor *mon); > ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices 2009-08-13 16:20 ` Cam Macdonell @ 2009-08-14 6:38 ` Mark McLoughlin 0 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-08-14 6:38 UTC (permalink / raw) To: Cam Macdonell; +Cc: qemu-devel On Thu, 2009-08-13 at 10:20 -0600, Cam Macdonell wrote: > > @@ -1957,6 +2004,10 @@ static void tcp_chr_read(void *opaque) > > tcp_chr_process_IAC_bytes(chr, s, buf, &size); > > if (size > 0) > > qemu_chr_read(chr, buf, size); > > + if (s->msgfd != -1) { > > + close(s->msgfd); > > + s->msgfd = -1; > > + } > > Hi Mark, > > I'm trying to understand the intended behaviour here so I can use your > patch. In your comments for the patch it reads "store the file > descriptor for use in the chr_read() handler. Close the file descriptor > if it was not used." It seems that upon returning from the chr_read() > handler the descriptor is closed if s->msgfd is not set to -1. Does > this mean the handler should set the fd to -1 after retrieving it if the > process wants to keep that fd open, otherwise it will be closed when > chr_read() returns? Should tcp_get_msgfd() perhaps set s->msgfd to -1 > after it is retrieved? Sort of a "read and clear" behaviour? Yes, that would work and TBH I can't recall why I chose not to do that. It'd be like popping the fd from a one item queue. The current caller of get_msgfd() dup()s the fd which achieves the same thing. Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-22 8:10 ` Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 1/5] " Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin @ 2009-07-22 8:11 ` Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 4/5] Add monitor_get_fd() command for fetching named fds Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 5/5] Add support for fd=name to tap and socket networking Mark McLoughlin 4 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-22 8:11 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin Add monitor commands to support passing file descriptors via SCM_RIGHTS. getfd assigns the passed file descriptor a name for use with other monitor commands. closefd allows passed file descriptors to be closed. If a monitor command actually uses a named file descriptor, closefd will not be required. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- monitor.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-monitor.hx | 18 ++++++++++++++ 2 files changed, 87 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index e38c86e..817e4b7 100644 --- a/monitor.c +++ b/monitor.c @@ -70,6 +70,14 @@ typedef struct mon_cmd_t { const char *help; } mon_cmd_t; +/* file descriptors passed via SCM_RIGHTS */ +typedef struct mon_fd_t mon_fd_t; +struct mon_fd_t { + char *name; + int fd; + LIST_ENTRY(mon_fd_t) next; +}; + struct Monitor { CharDriverState *chr; int flags; @@ -80,6 +88,7 @@ struct Monitor { CPUState *mon_cpu; BlockDriverCompletionFunc *password_completion_cb; void *password_opaque; + LIST_HEAD(,mon_fd_t) fds; LIST_ENTRY(Monitor) entry; }; @@ -1705,6 +1714,66 @@ static void do_inject_mce(Monitor *mon, } #endif +static void do_getfd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + int fd; + + fd = qemu_chr_get_msgfd(mon->chr); + if (fd == -1) { + monitor_printf(mon, "getfd: no file descriptor supplied via SCM_RIGHTS\n"); + return; + } + + if (qemu_isdigit(fdname[0])) { + monitor_printf(mon, "getfd: monitor names may not begin with a number\n"); + return; + } + + fd = dup(fd); + if (fd == -1) { + monitor_printf(mon, "Failed to dup() file descriptor: %s\n", + strerror(errno)); + return; + } + + LIST_FOREACH(monfd, &mon->fds, next) { + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + close(monfd->fd); + monfd->fd = fd; + return; + } + + monfd = qemu_mallocz(sizeof(mon_fd_t)); + monfd->name = qemu_strdup(fdname); + monfd->fd = fd; + + LIST_INSERT_HEAD(&mon->fds, monfd, next); +} + +static void do_closefd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + + LIST_FOREACH(monfd, &mon->fds, next) { + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + LIST_REMOVE(monfd, next); + close(monfd->fd); + qemu_free(monfd->name); + qemu_free(monfd); + return; + } + + monitor_printf(mon, "Failed to find file descriptor named %s\n", + fdname); +} + static const mon_cmd_t mon_cmds[] = { #include "qemu-monitor.h" { NULL, NULL, }, diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 70e2475..11bdb2c 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -628,6 +628,24 @@ STEXI Inject an MCE on the given CPU (x86 only). ETEXI + { "getfd", "s", do_getfd, "getfd name", + "receive a file descriptor via SCM rights and assign it a name" }, +STEXI +@item getfd @var{fdname} +If a file descriptor is passed alongside this command using the SCM_RIGHTS +mechanism on unix sockets, it is stored using the name @var{fdname} for +later use by other monitor commands. +ETEXI + + { "closefd", "s", do_closefd, "closefd name", + "close a file descriptor previously passed via SCM rights" }, +STEXI +@item closefd @var{fdname} +Close the file descriptor previously assigned to @var{fdname} using the +@code{getfd} command. This is only needed if the file descriptor was never +used by another monitor command. +ETEXI + STEXI @end table ETEXI -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 4/5] Add monitor_get_fd() command for fetching named fds 2009-07-22 8:10 ` Mark McLoughlin ` (2 preceding siblings ...) 2009-07-22 8:11 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Mark McLoughlin @ 2009-07-22 8:11 ` Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 5/5] Add support for fd=name to tap and socket networking Mark McLoughlin 4 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-22 8:11 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- monitor.c | 24 ++++++++++++++++++++++++ monitor.h | 2 ++ 2 files changed, 26 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index 817e4b7..6ad2e14 100644 --- a/monitor.c +++ b/monitor.c @@ -1774,6 +1774,30 @@ static void do_closefd(Monitor *mon, const char *fdname) fdname); } +int monitor_get_fd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + + LIST_FOREACH(monfd, &mon->fds, next) { + int fd; + + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + fd = monfd->fd; + + /* caller takes ownership of fd */ + LIST_REMOVE(monfd, next); + qemu_free(monfd->name); + qemu_free(monfd); + + return fd; + } + + return -1; +} + static const mon_cmd_t mon_cmds[] = { #include "qemu-monitor.h" { NULL, NULL, }, diff --git a/monitor.h b/monitor.h index 13e8cc7..f6a43c0 100644 --- a/monitor.h +++ b/monitor.h @@ -20,6 +20,8 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, BlockDriverCompletionFunc *completion_cb, void *opaque); +int monitor_get_fd(Monitor *mon, const char *fdname); + void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap); void monitor_printf(Monitor *mon, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH 5/5] Add support for fd=name to tap and socket networking 2009-07-22 8:10 ` Mark McLoughlin ` (3 preceding siblings ...) 2009-07-22 8:11 ` [Qemu-devel] [PATCH 4/5] Add monitor_get_fd() command for fetching named fds Mark McLoughlin @ 2009-07-22 8:11 ` Mark McLoughlin 2009-07-23 13:37 ` Mark McLoughlin 4 siblings, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-22 8:11 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin This allows a program to initialize a host networking device using a file descriptor passed over a unix monitor socket. The program must first pass the file descriptor using SCM_RIGHTS ancillary data with the getfd monitor command. It then may do "host_net_add tap fd=name" to use the named file descriptor. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- net.c | 42 +++++++++++++++++++++++++++++++++++------- 1 files changed, 35 insertions(+), 7 deletions(-) diff --git a/net.c b/net.c index 90cf912..1838692 100644 --- a/net.c +++ b/net.c @@ -2410,6 +2410,23 @@ void qemu_check_nic_model_list(NICInfo *nd, const char * const *models, exit(exit_status); } +static int net_handle_fd_param(Monitor *mon, const char *param) +{ + if (!qemu_isdigit(param[0])) { + int fd; + + fd = monitor_get_fd(mon, param); + if (fd == -1) { + config_error(mon, "No file descriptor named %s found", param); + return -1; + } + + return fd; + } else { + return strtol(param, NULL, 0); + } +} + int net_client_init(Monitor *mon, const char *device, const char *p) { char buf[1024]; @@ -2650,14 +2667,20 @@ int net_client_init(Monitor *mon, const char *device, const char *p) static const char * const fd_params[] = { "vlan", "name", "fd", "sndbuf", NULL }; + ret = -1; if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) { config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); - ret = -1; goto out; } - fd = strtol(buf, NULL, 0); + fd = net_handle_fd_param(mon, buf); + if (fd == -1) { + goto out; + } fcntl(fd, F_SETFL, O_NONBLOCK); s = net_tap_fd_init(vlan, device, name, fd); + if (!s) { + close(fd); + } } else { static const char * const tap_params[] = { "vlan", "name", "ifname", "script", "downscript", "sndbuf", NULL @@ -2697,15 +2720,20 @@ int net_client_init(Monitor *mon, const char *device, const char *p) "vlan", "name", "fd", NULL }; int fd; + ret = -1; if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) { config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); - ret = -1; goto out; } - fd = strtol(buf, NULL, 0); - ret = -1; - if (net_socket_fd_init(vlan, device, name, fd, 1)) - ret = 0; + fd = net_handle_fd_param(mon, buf); + if (fd == -1) { + goto out; + } + if (!net_socket_fd_init(vlan, device, name, fd, 1)) { + close(fd); + goto out; + } + ret = 0; } else if (get_param_value(buf, sizeof(buf), "listen", p) > 0) { static const char * const listen_params[] = { "vlan", "name", "listen", NULL -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 5/5] Add support for fd=name to tap and socket networking 2009-07-22 8:11 ` [Qemu-devel] [PATCH 5/5] Add support for fd=name to tap and socket networking Mark McLoughlin @ 2009-07-23 13:37 ` Mark McLoughlin 0 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-23 13:37 UTC (permalink / raw) To: qemu-devel On Wed, 2009-07-22 at 09:11 +0100, Mark McLoughlin wrote: > This allows a program to initialize a host networking device using a > file descriptor passed over a unix monitor socket. > > The program must first pass the file descriptor using SCM_RIGHTS > ancillary data with the getfd monitor command. It then may do > "host_net_add tap fd=name" to use the named file descriptor. Again begging for this to be pulled into stable-0.11 :-) These exact patches were posted in time for the branch but got dropped mainly because of confusion over whether all the concerns had been addressed It's a nice feature for a relatively small set of changes, and without them libvirt can't do NIC hotplug Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH] Add SCM_RIGHTS support to unix socket character devices 2009-07-21 16:40 ` Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Make tcp_chr_read() use recvmsg() Mark McLoughlin @ 2009-07-21 16:53 ` Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add getfd and closefd monitor commands Mark McLoughlin ` (3 subsequent siblings) 5 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-21 16:53 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin If a file descriptor is passed via a message with SCM_RIGHTS ancillary data on a unix socket, store the file descriptor for use in the chr_read() handler. Close the file descriptor if it was not used. The qemu_chr_get_msgfd() API provides access to the passed descriptor. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- qemu-char.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-char.h | 2 ++ 2 files changed, 52 insertions(+), 0 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index e0d7220..f06a614 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) s->chr_read(s->handler_opaque, buf, len); } +int qemu_chr_get_msgfd(CharDriverState *s) +{ + return s->get_msgfd ? s->get_msgfd(s) : -1; +} + void qemu_chr_accept_input(CharDriverState *s) { if (s->chr_accept_input) @@ -1832,6 +1837,7 @@ typedef struct { int do_telnetopt; int do_nodelay; int is_unix; + int msgfd; } TCPCharDriver; static void tcp_chr_accept(void *opaque); @@ -1907,12 +1913,46 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr, *size = j; } +static int tcp_get_msgfd(CharDriverState *chr) +{ + TCPCharDriver *s = chr->opaque; + + return s->msgfd; +} + +static void unix_process_msgfd(CharDriverState *chr, struct msghdr *msg) +{ + TCPCharDriver *s = chr->opaque; + struct cmsghdr *cmsg; + + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { + int fd; + + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || + cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) + continue; + + fd = *((int *)CMSG_DATA(cmsg)); + if (fd < 0) + continue; + + if (s->msgfd != -1) + close(s->msgfd); + s->msgfd = fd; + } +} + static void tcp_chr_read(void *opaque) { CharDriverState *chr = opaque; TCPCharDriver *s = chr->opaque; struct msghdr msg = { 0, }; struct iovec iov[1]; + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(int))]; + } msg_control; uint8_t buf[1024]; int len, size; @@ -1928,6 +1968,8 @@ static void tcp_chr_read(void *opaque) msg.msg_iov = iov; msg.msg_iovlen = 1; + msg.msg_control = &msg_control; + msg.msg_controllen = sizeof(msg_control); size = recvmsg(s->fd, &msg, 0); if (size == 0) { @@ -1940,10 +1982,16 @@ static void tcp_chr_read(void *opaque) closesocket(s->fd); s->fd = -1; } else if (size > 0) { + if (s->is_unix) + unix_process_msgfd(chr, &msg); if (s->do_telnetopt) tcp_chr_process_IAC_bytes(chr, s, buf, &size); if (size > 0) qemu_chr_read(chr, buf, size); + if (s->msgfd != -1) { + close(s->msgfd); + s->msgfd = -1; + } } } @@ -2105,12 +2153,14 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, s->connected = 0; s->fd = -1; s->listen_fd = -1; + s->msgfd = -1; s->is_unix = is_unix; s->do_nodelay = do_nodelay && !is_unix; chr->opaque = s; chr->chr_write = tcp_chr_write; chr->chr_close = tcp_chr_close; + chr->get_msgfd = tcp_get_msgfd; if (is_listen) { s->listen_fd = fd; diff --git a/qemu-char.h b/qemu-char.h index e1aa8db..77d4eda 100644 --- a/qemu-char.h +++ b/qemu-char.h @@ -51,6 +51,7 @@ struct CharDriverState { int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); void (*chr_update_read_handler)(struct CharDriverState *s); int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg); + int (*get_msgfd)(struct CharDriverState *s); IOEventHandler *chr_event; IOCanRWHandler *chr_can_read; IOReadHandler *chr_read; @@ -81,6 +82,7 @@ void qemu_chr_reset(CharDriverState *s); void qemu_chr_initial_reset(void); int qemu_chr_can_read(CharDriverState *s); void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len); +int qemu_chr_get_msgfd(CharDriverState *s); void qemu_chr_accept_input(CharDriverState *s); void qemu_chr_info(Monitor *mon); -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH] Add getfd and closefd monitor commands 2009-07-21 16:40 ` Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Make tcp_chr_read() use recvmsg() Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin @ 2009-07-21 16:53 ` Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add monitor_get_fd() command for fetching named fds Mark McLoughlin ` (2 subsequent siblings) 5 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-21 16:53 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin Add monitor commands to support passing file descriptors via SCM_RIGHTS. getfd assigns the passed file descriptor a name for use with other monitor commands. closefd allows passed file descriptors to be closed. If a monitor command actually uses a named file descriptor, closefd will not be required. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- monitor.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ qemu-monitor.hx | 18 ++++++++++++++ 2 files changed, 87 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index e38c86e..817e4b7 100644 --- a/monitor.c +++ b/monitor.c @@ -70,6 +70,14 @@ typedef struct mon_cmd_t { const char *help; } mon_cmd_t; +/* file descriptors passed via SCM_RIGHTS */ +typedef struct mon_fd_t mon_fd_t; +struct mon_fd_t { + char *name; + int fd; + LIST_ENTRY(mon_fd_t) next; +}; + struct Monitor { CharDriverState *chr; int flags; @@ -80,6 +88,7 @@ struct Monitor { CPUState *mon_cpu; BlockDriverCompletionFunc *password_completion_cb; void *password_opaque; + LIST_HEAD(,mon_fd_t) fds; LIST_ENTRY(Monitor) entry; }; @@ -1705,6 +1714,66 @@ static void do_inject_mce(Monitor *mon, } #endif +static void do_getfd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + int fd; + + fd = qemu_chr_get_msgfd(mon->chr); + if (fd == -1) { + monitor_printf(mon, "getfd: no file descriptor supplied via SCM_RIGHTS\n"); + return; + } + + if (qemu_isdigit(fdname[0])) { + monitor_printf(mon, "getfd: monitor names may not begin with a number\n"); + return; + } + + fd = dup(fd); + if (fd == -1) { + monitor_printf(mon, "Failed to dup() file descriptor: %s\n", + strerror(errno)); + return; + } + + LIST_FOREACH(monfd, &mon->fds, next) { + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + close(monfd->fd); + monfd->fd = fd; + return; + } + + monfd = qemu_mallocz(sizeof(mon_fd_t)); + monfd->name = qemu_strdup(fdname); + monfd->fd = fd; + + LIST_INSERT_HEAD(&mon->fds, monfd, next); +} + +static void do_closefd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + + LIST_FOREACH(monfd, &mon->fds, next) { + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + LIST_REMOVE(monfd, next); + close(monfd->fd); + qemu_free(monfd->name); + qemu_free(monfd); + return; + } + + monitor_printf(mon, "Failed to find file descriptor named %s\n", + fdname); +} + static const mon_cmd_t mon_cmds[] = { #include "qemu-monitor.h" { NULL, NULL, }, diff --git a/qemu-monitor.hx b/qemu-monitor.hx index 70e2475..11bdb2c 100644 --- a/qemu-monitor.hx +++ b/qemu-monitor.hx @@ -628,6 +628,24 @@ STEXI Inject an MCE on the given CPU (x86 only). ETEXI + { "getfd", "s", do_getfd, "getfd name", + "receive a file descriptor via SCM rights and assign it a name" }, +STEXI +@item getfd @var{fdname} +If a file descriptor is passed alongside this command using the SCM_RIGHTS +mechanism on unix sockets, it is stored using the name @var{fdname} for +later use by other monitor commands. +ETEXI + + { "closefd", "s", do_closefd, "closefd name", + "close a file descriptor previously passed via SCM rights" }, +STEXI +@item closefd @var{fdname} +Close the file descriptor previously assigned to @var{fdname} using the +@code{getfd} command. This is only needed if the file descriptor was never +used by another monitor command. +ETEXI + STEXI @end table ETEXI -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH] Add monitor_get_fd() command for fetching named fds 2009-07-21 16:40 ` Mark McLoughlin ` (2 preceding siblings ...) 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add getfd and closefd monitor commands Mark McLoughlin @ 2009-07-21 16:53 ` Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add support for fd=name to tap and socket networking Mark McLoughlin 2009-07-22 2:20 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Anthony Liguori 5 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-21 16:53 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- monitor.c | 24 ++++++++++++++++++++++++ monitor.h | 2 ++ 2 files changed, 26 insertions(+), 0 deletions(-) diff --git a/monitor.c b/monitor.c index 817e4b7..6ad2e14 100644 --- a/monitor.c +++ b/monitor.c @@ -1774,6 +1774,30 @@ static void do_closefd(Monitor *mon, const char *fdname) fdname); } +int monitor_get_fd(Monitor *mon, const char *fdname) +{ + mon_fd_t *monfd; + + LIST_FOREACH(monfd, &mon->fds, next) { + int fd; + + if (strcmp(monfd->name, fdname) != 0) { + continue; + } + + fd = monfd->fd; + + /* caller takes ownership of fd */ + LIST_REMOVE(monfd, next); + qemu_free(monfd->name); + qemu_free(monfd); + + return fd; + } + + return -1; +} + static const mon_cmd_t mon_cmds[] = { #include "qemu-monitor.h" { NULL, NULL, }, diff --git a/monitor.h b/monitor.h index 13e8cc7..f6a43c0 100644 --- a/monitor.h +++ b/monitor.h @@ -20,6 +20,8 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, BlockDriverCompletionFunc *completion_cb, void *opaque); +int monitor_get_fd(Monitor *mon, const char *fdname); + void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap); void monitor_printf(Monitor *mon, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* [Qemu-devel] [PATCH] Add support for fd=name to tap and socket networking 2009-07-21 16:40 ` Mark McLoughlin ` (3 preceding siblings ...) 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add monitor_get_fd() command for fetching named fds Mark McLoughlin @ 2009-07-21 16:53 ` Mark McLoughlin 2009-07-22 2:20 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Anthony Liguori 5 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-21 16:53 UTC (permalink / raw) To: qemu-devel; +Cc: Mark McLoughlin This allows a program to initialize a host networking device using a file descriptor passed over a unix monitor socket. The program must first pass the file descriptor using SCM_RIGHTS ancillary data with the getfd monitor command. It then may do "host_net_add tap fd=name" to use the named file descriptor. Signed-off-by: Mark McLoughlin <markmc@redhat.com> --- net.c | 42 +++++++++++++++++++++++++++++++++++------- 1 files changed, 35 insertions(+), 7 deletions(-) diff --git a/net.c b/net.c index 90cf912..1838692 100644 --- a/net.c +++ b/net.c @@ -2410,6 +2410,23 @@ void qemu_check_nic_model_list(NICInfo *nd, const char * const *models, exit(exit_status); } +static int net_handle_fd_param(Monitor *mon, const char *param) +{ + if (!qemu_isdigit(param[0])) { + int fd; + + fd = monitor_get_fd(mon, param); + if (fd == -1) { + config_error(mon, "No file descriptor named %s found", param); + return -1; + } + + return fd; + } else { + return strtol(param, NULL, 0); + } +} + int net_client_init(Monitor *mon, const char *device, const char *p) { char buf[1024]; @@ -2650,14 +2667,20 @@ int net_client_init(Monitor *mon, const char *device, const char *p) static const char * const fd_params[] = { "vlan", "name", "fd", "sndbuf", NULL }; + ret = -1; if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) { config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); - ret = -1; goto out; } - fd = strtol(buf, NULL, 0); + fd = net_handle_fd_param(mon, buf); + if (fd == -1) { + goto out; + } fcntl(fd, F_SETFL, O_NONBLOCK); s = net_tap_fd_init(vlan, device, name, fd); + if (!s) { + close(fd); + } } else { static const char * const tap_params[] = { "vlan", "name", "ifname", "script", "downscript", "sndbuf", NULL @@ -2697,15 +2720,20 @@ int net_client_init(Monitor *mon, const char *device, const char *p) "vlan", "name", "fd", NULL }; int fd; + ret = -1; if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) { config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); - ret = -1; goto out; } - fd = strtol(buf, NULL, 0); - ret = -1; - if (net_socket_fd_init(vlan, device, name, fd, 1)) - ret = 0; + fd = net_handle_fd_param(mon, buf); + if (fd == -1) { + goto out; + } + if (!net_socket_fd_init(vlan, device, name, fd, 1)) { + close(fd); + goto out; + } + ret = 0; } else if (get_param_value(buf, sizeof(buf), "listen", p) > 0) { static const char * const listen_params[] = { "vlan", "name", "listen", NULL -- 1.6.2.5 ^ permalink raw reply related [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-21 16:40 ` Mark McLoughlin ` (4 preceding siblings ...) 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add support for fd=name to tap and socket networking Mark McLoughlin @ 2009-07-22 2:20 ` Anthony Liguori 2009-07-22 8:09 ` Mark McLoughlin 5 siblings, 1 reply; 53+ messages in thread From: Anthony Liguori @ 2009-07-22 2:20 UTC (permalink / raw) To: Mark McLoughlin; +Cc: Avi Kivity, qemu-devel Mark McLoughlin wrote: > My take on it is that we're all agreed that it's never valid with the > current monitor protocol for a client to queue up multiple fds. It's a > synchronous protocol, you can't send multiple commands at once. > I think there's a subtle point that was lost in the thread. While we'll only need to queue one fd per MonitorState, we'll still need to deal with multiple fds per CharDriverState. I think the way this would most logically work would be a push interface verses a pull interface so that there wasn't double queuing. That is, whenever the CharDriverState gets an fd, it calls a function registered by the consumer of the CharDriverState. Regards, Anthony Liguori ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-22 2:20 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Anthony Liguori @ 2009-07-22 8:09 ` Mark McLoughlin 2009-07-23 7:00 ` [Qemu-devel] " Jan Kiszka 0 siblings, 1 reply; 53+ messages in thread From: Mark McLoughlin @ 2009-07-22 8:09 UTC (permalink / raw) To: Anthony Liguori; +Cc: Avi Kivity, qemu-devel On Tue, 2009-07-21 at 21:20 -0500, Anthony Liguori wrote: > Mark McLoughlin wrote: > > My take on it is that we're all agreed that it's never valid with the > > current monitor protocol for a client to queue up multiple fds. It's a > > synchronous protocol, you can't send multiple commands at once. > > > > I think there's a subtle point that was lost in the thread. While we'll > only need to queue one fd per MonitorState, we'll still need to deal > with multiple fds per CharDriverState. Why? For a theoretical use case, or for the current monitor interface? If the latter, then I don't follow. The flow is as follows: client server ------ ------ send request -> wait for response read request process msgfd, allowing only a single fd monitor handles request <- send reply handle response close msgfd if unused send next request -> If the client sends multiple requests at once, it is broken - it must wait for a "(qemu) " reply before sending another request. If the client sends multiple fds in a single request, it is broken - no monitor commands support multiple fds. If the client is broken and sends multiple fds, we only read the first one and the kernel frees the others. If the client sends an fd along with a request which does not require an fd, we just close that fd after we've processed the request. If we get a new protocol which allows multiple requests per message or multiple fds per request, we can easily add a queue then. Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] Re: [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-22 8:09 ` Mark McLoughlin @ 2009-07-23 7:00 ` Jan Kiszka 2009-07-23 7:51 ` Mark McLoughlin 0 siblings, 1 reply; 53+ messages in thread From: Jan Kiszka @ 2009-07-23 7:00 UTC (permalink / raw) To: Mark McLoughlin; +Cc: Avi Kivity, qemu-devel [-- Attachment #1: Type: text/plain, Size: 1896 bytes --] Mark McLoughlin wrote: > On Tue, 2009-07-21 at 21:20 -0500, Anthony Liguori wrote: >> Mark McLoughlin wrote: >>> My take on it is that we're all agreed that it's never valid with the >>> current monitor protocol for a client to queue up multiple fds. It's a >>> synchronous protocol, you can't send multiple commands at once. >>> >> I think there's a subtle point that was lost in the thread. While we'll >> only need to queue one fd per MonitorState, we'll still need to deal >> with multiple fds per CharDriverState. > > Why? For a theoretical use case, or for the current monitor interface? > There can be multiple monitors attached at the same time, already today. > If the latter, then I don't follow. > > The flow is as follows: > > client server > ------ ------ > send request -> > wait for response > read request > process msgfd, allowing only a single fd > monitor handles request > <- send reply > handle response close msgfd if unused > send next request -> > > If the client sends multiple requests at once, it is broken - it must > wait for a "(qemu) " reply before sending another request. > > If the client sends multiple fds in a single request, it is broken - no > monitor commands support multiple fds. > > If the client is broken and sends multiple fds, we only read the first > one and the kernel frees the others. > > If the client sends an fd along with a request which does not require an > fd, we just close that fd after we've processed the request. > > If we get a new protocol which allows multiple requests per message or > multiple fds per request, we can easily add a queue then. > > Cheers, > Mark. > Jan [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 257 bytes --] ^ permalink raw reply [flat|nested] 53+ messages in thread
* [Qemu-devel] Re: [PATCH 3/5] Add getfd and closefd monitor commands 2009-07-23 7:00 ` [Qemu-devel] " Jan Kiszka @ 2009-07-23 7:51 ` Mark McLoughlin 0 siblings, 0 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-23 7:51 UTC (permalink / raw) To: Jan Kiszka; +Cc: Avi Kivity, qemu-devel On Thu, 2009-07-23 at 09:00 +0200, Jan Kiszka wrote: > Mark McLoughlin wrote: > > On Tue, 2009-07-21 at 21:20 -0500, Anthony Liguori wrote: > >> Mark McLoughlin wrote: > >>> My take on it is that we're all agreed that it's never valid with the > >>> current monitor protocol for a client to queue up multiple fds. It's a > >>> synchronous protocol, you can't send multiple commands at once. > >>> > >> I think there's a subtle point that was lost in the thread. While we'll > >> only need to queue one fd per MonitorState, we'll still need to deal > >> with multiple fds per CharDriverState. > > > > Why? For a theoretical use case, or for the current monitor interface? > > > > There can be multiple monitors attached at the same time, already today. But each monitor has its own socket, CharDriverState and Monitor ... multiple monitors is irrelevant to the need for an fd queue on CharDriverState. Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices 2009-07-08 14:57 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Mark McLoughlin @ 2009-07-08 15:25 ` Avi Kivity 2009-07-08 16:04 ` Mark McLoughlin 1 sibling, 1 reply; 53+ messages in thread From: Avi Kivity @ 2009-07-08 15:25 UTC (permalink / raw) To: Mark McLoughlin; +Cc: qemu-devel On 07/08/2009 05:57 PM, Mark McLoughlin wrote: > If a file descriptor is passed via a message with SCM_RIGHTS ancillary > data on a unix socket, store the file descriptor for use in the > chr_read() handler. Close the file descriptor if it was not used. > > The qemu_chr_get_msgfd() API provides access to the passed descriptor. > > Signed-off-by: Mark McLoughlin<markmc@redhat.com> > --- > qemu-char.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ > qemu-char.h | 2 ++ > 2 files changed, 52 insertions(+), 0 deletions(-) > > diff --git a/qemu-char.c b/qemu-char.c > index e0d7220..f06a614 100644 > --- a/qemu-char.c > +++ b/qemu-char.c > @@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) > s->chr_read(s->handler_opaque, buf, len); > } > > +int qemu_chr_get_msgfd(CharDriverState *s) > +{ > + return s->get_msgfd ? s->get_msgfd(s) : -1; > +} > + > void qemu_chr_accept_input(CharDriverState *s) > { > if (s->chr_accept_input) > @@ -1832,6 +1837,7 @@ typedef struct { > int do_telnetopt; > int do_nodelay; > int is_unix; > + int msgfd; > } TCPCharDriver; > SCM_RIGHTS messages can contain multiple fds, and multiple messages can arrive. I think you need to queue fds here in case the client sends two getfd commands back-to-back and does buffering. -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices 2009-07-08 15:25 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Avi Kivity @ 2009-07-08 16:04 ` Mark McLoughlin 2009-07-08 16:17 ` Avi Kivity 2009-07-08 18:11 ` Anthony Liguori 0 siblings, 2 replies; 53+ messages in thread From: Mark McLoughlin @ 2009-07-08 16:04 UTC (permalink / raw) To: Avi Kivity; +Cc: qemu-devel On Wed, 2009-07-08 at 18:25 +0300, Avi Kivity wrote: > On 07/08/2009 05:57 PM, Mark McLoughlin wrote: > > If a file descriptor is passed via a message with SCM_RIGHTS ancillary > > data on a unix socket, store the file descriptor for use in the > > chr_read() handler. Close the file descriptor if it was not used. > > > > The qemu_chr_get_msgfd() API provides access to the passed descriptor. > > > > Signed-off-by: Mark McLoughlin<markmc@redhat.com> > > --- > > qemu-char.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ > > qemu-char.h | 2 ++ > > 2 files changed, 52 insertions(+), 0 deletions(-) > > > > diff --git a/qemu-char.c b/qemu-char.c > > index e0d7220..f06a614 100644 > > --- a/qemu-char.c > > +++ b/qemu-char.c > > @@ -168,6 +168,11 @@ void qemu_chr_read(CharDriverState *s, uint8_t *buf, int len) > > s->chr_read(s->handler_opaque, buf, len); > > } > > > > +int qemu_chr_get_msgfd(CharDriverState *s) > > +{ > > + return s->get_msgfd ? s->get_msgfd(s) : -1; > > +} > > + > > void qemu_chr_accept_input(CharDriverState *s) > > { > > if (s->chr_accept_input) > > @@ -1832,6 +1837,7 @@ typedef struct { > > int do_telnetopt; > > int do_nodelay; > > int is_unix; > > + int msgfd; > > } TCPCharDriver; > > > > SCM_RIGHTS messages can contain multiple fds, It only makes sense to have one per getfd command and ... > and multiple messages can arrive. I think you need to queue fds here > in case the client sends two getfd commands back-to-back and does > buffering. it doesn't look to me like the current monitor code can handle multiple commands in the one message. Cheers, Mark. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices 2009-07-08 16:04 ` Mark McLoughlin @ 2009-07-08 16:17 ` Avi Kivity 2009-07-08 18:11 ` Anthony Liguori 1 sibling, 0 replies; 53+ messages in thread From: Avi Kivity @ 2009-07-08 16:17 UTC (permalink / raw) To: Mark McLoughlin; +Cc: qemu-devel On 07/08/2009 07:04 PM, Mark McLoughlin wrote: > >> and multiple messages can arrive. I think you need to queue fds here >> in case the client sends two getfd commands back-to-back and does >> buffering. >> > > it doesn't look to me like the current monitor code can handle multiple > commands in the one message. > How does qemu have any control over the division of messages and packets? I can send commands byte by byte or queue them up and send a gigabyte's worth in one go (when we have -monitor ib:blah). -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices 2009-07-08 16:04 ` Mark McLoughlin 2009-07-08 16:17 ` Avi Kivity @ 2009-07-08 18:11 ` Anthony Liguori 2009-07-08 18:17 ` Avi Kivity 1 sibling, 1 reply; 53+ messages in thread From: Anthony Liguori @ 2009-07-08 18:11 UTC (permalink / raw) To: Mark McLoughlin; +Cc: Avi Kivity, qemu-devel Mark McLoughlin wrote: > It only makes sense to have one per getfd command and ... > It would be silly to pass many fds. fds are scarce resources and you don't want to get into a position where you're queuing fds. If a management tool wants to send an fd, it should issue the monitor command that needs the fd along with the fd via SCM_RIGHTS, and then wait for that command to complete before issuing another command that needs an fd. Regards, Anthony Liguori ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices 2009-07-08 18:11 ` Anthony Liguori @ 2009-07-08 18:17 ` Avi Kivity 2009-07-11 1:15 ` Jamie Lokier 0 siblings, 1 reply; 53+ messages in thread From: Avi Kivity @ 2009-07-08 18:17 UTC (permalink / raw) To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel On 07/08/2009 09:11 PM, Anthony Liguori wrote: > Mark McLoughlin wrote: >> It only makes sense to have one per getfd command and ... > > It would be silly to pass many fds. fds are scarce resources and you > don't want to get into a position where you're queuing fds. If you issue N getfd commands, you've queued N fds. > If a management tool wants to send an fd, it should issue the monitor > command that needs the fd along with the fd via SCM_RIGHTS, and then > wait for that command to complete before issuing another command that > needs an fd. > Why impose unnecessary restrictions? I agree that the guest shouldn't use qemu as an fd store. But putting such limits in the code is laying a trap for the client, which will show up in rare cases, for example two client threads issuing unrelated getfd commands with the client author not knowing it should serialize them. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices 2009-07-08 18:17 ` Avi Kivity @ 2009-07-11 1:15 ` Jamie Lokier 0 siblings, 0 replies; 53+ messages in thread From: Jamie Lokier @ 2009-07-11 1:15 UTC (permalink / raw) To: Avi Kivity; +Cc: Mark McLoughlin, qemu-devel Avi Kivity wrote: > Why impose unnecessary restrictions? I agree that the guest shouldn't > use qemu as an fd store. But putting such limits in the code is laying > a trap for the client, which will show up in rare cases, for example two > client threads issuing unrelated getfd commands with the client author > not knowing it should serialize them. If there is an fd queue, then it clearly must be limited on the QEMU side to avoid becoming an fd store. A client issuing unrelated commands must be aware of that limitation. The queue length could be 1, or it could be 10 per monitor to allow some command overlap, but the client will need to be aware of it and limit overlap. That means the limit must be documented in any (future :-) monitor protocol documentation. -- Jamie ^ permalink raw reply [flat|nested] 53+ messages in thread
end of thread, other threads:[~2009-08-14 6:39 UTC | newest] Thread overview: 53+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-07-06 17:30 [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors Mark McLoughlin 2009-07-06 17:30 ` [Qemu-devel] [PATCH 1/3] Make tcp_chr_read() use recvmsg() Mark McLoughlin 2009-07-06 17:31 ` [Qemu-devel] [PATCH 2/3] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin 2009-07-06 17:32 ` [Qemu-devel] [PATCH 3/3] Add support for fd=msgfd for tap and socket networking Mark McLoughlin 2009-07-07 5:28 ` [Qemu-devel] [PATCH 0/3] Allow host_net_add monitor command accept file descriptors Avi Kivity 2009-07-07 7:43 ` Mark McLoughlin 2009-07-07 7:52 ` Avi Kivity 2009-07-07 8:13 ` Mark McLoughlin 2009-07-07 9:03 ` Avi Kivity 2009-07-07 10:06 ` Daniel P. Berrange 2009-07-08 14:56 ` Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 1/5] Make tcp_chr_read() use recvmsg() Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 4/5] Add monitor_get_fd() command for fetching named fds Mark McLoughlin 2009-07-08 14:57 ` [Qemu-devel] [PATCH 5/5] Add support for fd=name to tap and socket networking Mark McLoughlin 2009-07-08 15:26 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Avi Kivity 2009-07-08 16:03 ` Mark McLoughlin 2009-07-08 16:15 ` Avi Kivity 2009-07-08 18:08 ` Anthony Liguori 2009-07-08 18:11 ` Avi Kivity 2009-07-08 18:21 ` Anthony Liguori 2009-07-08 18:32 ` Avi Kivity 2009-07-08 18:50 ` Anthony Liguori 2009-07-08 19:52 ` Avi Kivity 2009-07-11 1:12 ` Jamie Lokier 2009-07-21 16:40 ` Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Make tcp_chr_read() use recvmsg() Mark McLoughlin 2009-07-21 17:13 ` Blue Swirl 2009-07-22 0:00 ` Jamie Lokier 2009-07-22 8:10 ` Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 1/5] " Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin 2009-08-13 16:20 ` Cam Macdonell 2009-08-14 6:38 ` Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 4/5] Add monitor_get_fd() command for fetching named fds Mark McLoughlin 2009-07-22 8:11 ` [Qemu-devel] [PATCH 5/5] Add support for fd=name to tap and socket networking Mark McLoughlin 2009-07-23 13:37 ` Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add SCM_RIGHTS support to unix socket character devices Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add getfd and closefd monitor commands Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add monitor_get_fd() command for fetching named fds Mark McLoughlin 2009-07-21 16:53 ` [Qemu-devel] [PATCH] Add support for fd=name to tap and socket networking Mark McLoughlin 2009-07-22 2:20 ` [Qemu-devel] [PATCH 3/5] Add getfd and closefd monitor commands Anthony Liguori 2009-07-22 8:09 ` Mark McLoughlin 2009-07-23 7:00 ` [Qemu-devel] " Jan Kiszka 2009-07-23 7:51 ` Mark McLoughlin 2009-07-08 15:25 ` [Qemu-devel] [PATCH 2/5] Add SCM_RIGHTS support to unix socket character devices Avi Kivity 2009-07-08 16:04 ` Mark McLoughlin 2009-07-08 16:17 ` Avi Kivity 2009-07-08 18:11 ` Anthony Liguori 2009-07-08 18:17 ` Avi Kivity 2009-07-11 1:15 ` Jamie Lokier
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).