[libvirt] [dbus PATCH 0/4] Implement domain APIs with file descriptors

Pavel Hrdina (4): gdbus: fix memory and FD leak in virtDBusGDBusHandleMethod domain: Implement CreateWithFiles method domain: Implement OpenGraphicsFD method connect: Implement DomainCreateXMLWithFiles method data/org.libvirt.Connect.xml | 8 +++++ data/org.libvirt.Domain.xml | 13 ++++++++ src/connect.c | 40 ++++++++++++++++++++++ src/domain.c | 64 ++++++++++++++++++++++++++++++++++++ src/gdbus.c | 3 +- 5 files changed, 127 insertions(+), 1 deletion(-) -- 2.17.0

Signed-off-by: Pavel Hrdina <phrdina@redhat.com> --- src/gdbus.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gdbus.c b/src/gdbus.c index 3407116..2cce6ff 100644 --- a/src/gdbus.c +++ b/src/gdbus.c @@ -1,5 +1,6 @@ #include "gdbus.h" +#include <gio/gunixfdlist.h> #include <glib/gprintf.h> struct _virtDBusGDBusMethodData { @@ -201,7 +202,7 @@ virtDBusGDBusHandleMethod(GVariant *parameters, GDBusMessage *msg = g_dbus_method_invocation_get_message(invocation); GUnixFDList *inFDs = NULL; GVariant *outArgs = NULL; - GUnixFDList *outFDs = NULL; + g_autoptr(GUnixFDList) outFDs = NULL; g_autoptr(GError) error = NULL; for (gint i = 0; data->methods[i].name; i++) { -- 2.17.0

Signed-off-by: Pavel Hrdina <phrdina@redhat.com> --- data/org.libvirt.Domain.xml | 6 ++++++ src/domain.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/data/org.libvirt.Domain.xml b/data/org.libvirt.Domain.xml index e97ebe9..9743f25 100644 --- a/data/org.libvirt.Domain.xml +++ b/data/org.libvirt.Domain.xml @@ -136,6 +136,12 @@ value="See https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainCreateWithFlags"/> <arg name="flags" type="u" direction="in"/> </method> + <method name="CreateWithFiles"> + <annotation name="org.gtk.GDBus.DocString" + value="See https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainCreateWithFiles"/> + <arg name="files" type="ah" direction="in"/> + <arg name="flags" type="u" direction="in"/> + </method> <method name="DelIOThread"> <annotation name="org.gtk.GDBus.DocString" value="See https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainDelIOThread"/> diff --git a/src/domain.c b/src/domain.c index 3127f6c..3551e31 100644 --- a/src/domain.c +++ b/src/domain.c @@ -1,6 +1,7 @@ #include "domain.h" #include "util.h" +#include <gio/gunixfdlist.h> #include <libvirt/libvirt.h> static gchar * @@ -735,6 +736,37 @@ virtDBusDomainCreate(GVariant *inArgs, virtDBusUtilSetLastVirtError(error); } +static void +virtDBusDomainCreateWithFiles(GVariant *inArgs, + GUnixFDList *inFDs, + const gchar *objectPath, + gpointer userData, + GVariant **outArgs G_GNUC_UNUSED, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) +{ + virtDBusConnect *connect = userData; + g_autoptr(virDomain) domain = NULL; + const gint *files = NULL; + guint nfiles = 0; + guint flags; + + g_variant_get(inArgs, "(ahu)", NULL, &flags); + + if (inFDs) { + nfiles = g_unix_fd_list_get_length(inFDs); + if (nfiles > 0) + files = g_unix_fd_list_peek_fds(inFDs, NULL); + } + + domain = virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; + + if (virDomainCreateWithFiles(domain, nfiles, (gint *)files, flags) < 0) + virtDBusUtilSetLastVirtError(error); +} + static void virtDBusDomainDelIOThread(GVariant *inArgs, GUnixFDList *inFDs G_GNUC_UNUSED, @@ -2823,6 +2855,7 @@ static virtDBusGDBusMethodTable virtDBusDomainMethodTable[] = { { "BlockResize", virtDBusDomainBlockResize }, { "CoreDump", virtDBusDomainCoreDumpWithFormat }, { "Create", virtDBusDomainCreate }, + { "CreateWithFiles", virtDBusDomainCreateWithFiles }, { "DelIOThread", virtDBusDomainDelIOThread }, { "Destroy", virtDBusDomainDestroy }, { "DetachDevice", virtDBusDomainDetachDevice }, -- 2.17.0

Signed-off-by: Pavel Hrdina <phrdina@redhat.com> --- In order to test it you need to disable SELinux, otherwise the libvirt-dbus daemon is disconnected from system bus by dbus-daemon. The issue is that dbus-daemon will get avc denied on the passed FD. The following policy will allow it: ------------------------------------------------------------------------ require { type svirt_t; type system_dbusd_t; class unix_stream_socket { read write }; } allow system_dbusd_t svirt_t:unix_stream_socket { read write }; ------------------------------------------------------------------------ data/org.libvirt.Domain.xml | 7 +++++++ src/domain.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/data/org.libvirt.Domain.xml b/data/org.libvirt.Domain.xml index 9743f25..bcd0779 100644 --- a/data/org.libvirt.Domain.xml +++ b/data/org.libvirt.Domain.xml @@ -390,6 +390,13 @@ value="See https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainMigrateStartPostCopy"/> <arg name="flags" type="u" direction="in"/> </method> + <method name="OpenGraphicsFD"> + <annotation name="org.gtk.GDBus.DocString" + value="See https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainOpenGraphicsFD"/> + <arg name="idx" type="u" direction="in"/> + <arg name="flags" type="u" direction="in"/> + <arg name="fd" type="h" direction="out"/> + </method> <method name="PinEmulator"> <annotation name="org.gtk.GDBus.DocString" value="See https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainPinEmulator"/> diff --git a/src/domain.c b/src/domain.c index 3551e31..eaef68c 100644 --- a/src/domain.c +++ b/src/domain.c @@ -2033,6 +2033,36 @@ virtDBusDomainMigrateStartPostCopy(GVariant *inArgs, virtDBusUtilSetLastVirtError(error); } +static void +virtDBusDomainOpenGraphicsFD(GVariant *inArgs, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath, + gpointer userData, + GVariant **outArgs, + GUnixFDList **outFDs, + GError **error) + +{ + virtDBusConnect *connect = userData; + g_autoptr(virDomain) domain = NULL; + guint idx; + guint flags; + gint fd; + + g_variant_get(inArgs, "(uu)", &idx, &flags); + + domain = virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; + + fd = virDomainOpenGraphicsFD(domain, idx, flags); + if (fd < 0) + return virtDBusUtilSetLastVirtError(error); + + *outArgs = g_variant_new("(h)", 0); + *outFDs = g_unix_fd_list_new_from_array(&fd, 1); +} + static void virtDBusDomainPinEmulator(GVariant *inArgs, GUnixFDList *inFDs G_GNUC_UNUSED, @@ -2896,6 +2926,7 @@ static virtDBusGDBusMethodTable virtDBusDomainMethodTable[] = { { "MigrateSetMaxDowntime", virtDBusDomainMigrateSetMaxDowntime }, { "MigrateSetMaxSpeed", virtDBusDomainMigrateSetMaxSpeed }, { "MigrateStartPostCopy", virtDBusDomainMigrateStartPostCopy }, + { "OpenGraphicsFD", virtDBusDomainOpenGraphicsFD }, { "PinEmulator", virtDBusDomainPinEmulator }, { "PinIOThread", virtDBusDomainPinIOThread }, { "PinVcpu", virtDBusDomainPinVcpu }, -- 2.17.0

Signed-off-by: Pavel Hrdina <phrdina@redhat.com> --- data/org.libvirt.Connect.xml | 8 ++++++++ src/connect.c | 40 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/data/org.libvirt.Connect.xml b/data/org.libvirt.Connect.xml index 0c009cd..2b82a76 100644 --- a/data/org.libvirt.Connect.xml +++ b/data/org.libvirt.Connect.xml @@ -49,6 +49,14 @@ <arg name="flags" type="u" direction="in"/> <arg name="domain" type="o" direction="out"/> </method> + <method name="DomainCreateXMLWithFiles"> + <annotation name="org.gtk.GDBus.DocString" + value="See https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainCreateXMLWithFiles"/> + <arg name="xml" type="s" direction="in"/> + <arg name="files" type="ah" direction="in"/> + <arg name="flags" type="u" direction="in"/> + <arg name="domain" type="o" direction="out"/> + </method> <method name="DomainDefineXML"> <annotation name="org.gtk.GDBus.DocString" value="See https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainDefineXML"/> diff --git a/src/connect.c b/src/connect.c index 79b5d8f..096671f 100644 --- a/src/connect.c +++ b/src/connect.c @@ -5,6 +5,7 @@ #include "storagepool.h" #include "util.h" +#include <gio/gunixfdlist.h> #include <glib/gprintf.h> static gint virtDBusConnectCredType[] = { @@ -309,6 +310,44 @@ virtDBusConnectDomainCreateXML(GVariant *inArgs, *outArgs = g_variant_new("(o)", path); } +static void +virtDBusConnectDomainCreateXMLWithFiles(GVariant *inArgs, + GUnixFDList *inFDs, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) +{ + virtDBusConnect *connect = userData; + g_autoptr(virDomain) domain = NULL; + g_autofree gchar *path = NULL; + gchar *xml; + const gint *files = NULL; + guint nfiles = 0; + guint flags; + + g_variant_get(inArgs, "(&sahu)", &xml, NULL, &flags); + + if (inFDs) { + nfiles = g_unix_fd_list_get_length(inFDs); + if (nfiles > 0) + files = g_unix_fd_list_peek_fds(inFDs, NULL); + } + + if (!virtDBusConnectOpen(connect, error)) + return; + + domain = virDomainCreateXMLWithFiles(connect->connection, xml, nfiles, + (gint *)files, flags); + if (!domain) + return virtDBusUtilSetLastVirtError(error); + + path = virtDBusUtilBusPathForVirDomain(domain, connect->domainPath); + + *outArgs = g_variant_new("(o)", path); +} + static void virtDBusConnectDomainDefineXML(GVariant *inArgs, GUnixFDList *inFDs G_GNUC_UNUSED, @@ -1176,6 +1215,7 @@ static virtDBusGDBusMethodTable virtDBusConnectMethodTable[] = { { "BaselineCPU", virtDBusConnectBaselineCPU }, { "CompareCPU", virtDBusConnectCompareCPU }, { "DomainCreateXML", virtDBusConnectDomainCreateXML }, + { "DomainCreateXMLWithFiles", virtDBusConnectDomainCreateXMLWithFiles }, { "DomainDefineXML", virtDBusConnectDomainDefineXML }, { "DomainLookupByID", virtDBusConnectDomainLookupByID }, { "DomainLookupByName", virtDBusConnectDomainLookupByName }, -- 2.17.0

On Thu, 2018-05-10 at 13:01 +0200, Pavel Hrdina wrote:
Pavel Hrdina (4): gdbus: fix memory and FD leak in virtDBusGDBusHandleMethod domain: Implement CreateWithFiles method domain: Implement OpenGraphicsFD method connect: Implement DomainCreateXMLWithFiles method
data/org.libvirt.Connect.xml | 8 +++++ data/org.libvirt.Domain.xml | 13 ++++++++ src/connect.c | 40 ++++++++++++++++++++++ src/domain.c | 64 ++++++++++++++++++++++++++++++++++++ src/gdbus.c | 3 +- 5 files changed, 127 insertions(+), 1 deletion(-)
Reviewed-by: Katerina Koukiou <kkoukiou@redhat.com>
participants (2)
-
Katerina Koukiou
-
Pavel Hrdina