Introduce a read-only `tapfd` element for direct interfaces (macvtap),
which contains the path to the backing tapfd for that interface
(e.g. `/dev/tapXX`).

The element is only included when the domain is being formatted for
internal consumption (VIR_DOMAIN_DEF_FORMAT_STATUS) and is not accepted
in user-provided XML (!VIR_DOMAIN_DEF_PARSE_INACTIVE).

This will be used by the AppArmor security driver when re-generating
profiles.

Reviewed-by: Peter Krempa <[email protected]>
Signed-off-by: Wesley Hershberger <[email protected]>
---
 src/conf/domain_conf.c                    |  8 ++++++++
 src/conf/domain_conf.h                    |  1 +
 src/hypervisor/domain_interface.c         |  2 +-
 src/lxc/lxc_process.c                     |  1 +
 src/qemu/qemu_interface.c                 |  1 +
 src/util/virnetdevmacvlan.c               | 18 +++++++++++-------
 src/util/virnetdevmacvlan.h               |  4 +++-
 tests/qemustatusxml2xmldata/modern-in.xml |  7 +++++++
 8 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b1ee519ff6..3497e84bf5 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2971,6 +2971,7 @@ virDomainNetDefFree(virDomainNetDef *def)
     g_free(def->virtio);
     g_free(def->coalesce);
     g_free(def->sourceDev);
+    g_free(def->tapfdpath);
 
     virNetDevIPInfoClear(&def->guestIP);
     virNetDevIPInfoClear(&def->hostIP);
@@ -10635,6 +10636,10 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
             return NULL;
     }
 
+    if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) {
+        def->tapfdpath = virXPathString("string(./tapfd/@path)", ctxt);
+    }
+
     if (virNetworkPortOptionsParseXML(ctxt, &def->isolatedPort) < 0)
         return NULL;
 
@@ -26032,6 +26037,9 @@ virDomainNetDefFormat(virBuffer *buf,
     if (def->mtu)
         virBufferAsprintf(buf, "<mtu size='%u'/>\n", def->mtu);
 
+    if (def->tapfdpath && (flags & VIR_DOMAIN_DEF_FORMAT_STATUS))
+        virBufferEscapeString(buf, "<tapfd path='%s'/>\n", def->tapfdpath);
+
     virDomainNetDefCoalesceFormatXML(buf, def->coalesce);
 
     virDomainDeviceInfoFormat(buf, &def->info, flags | 
VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 75acfc46bf..a8f90803da 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1212,6 +1212,7 @@ struct _virDomainNetDef {
     char *downscript;
     char *domain_name; /* backend domain name */
     char *ifname; /* interface name on the host (<target dev='x'/>) */
+    char *tapfdpath; /* Path in /dev for macvtap (<tapfd path='/dev/tapXX'/>) 
*/
     virTristateBool managed_tap;
     virNetDevIPInfo hostIP;
     char *ifname_guest_actual;
diff --git a/src/hypervisor/domain_interface.c 
b/src/hypervisor/domain_interface.c
index 5bc698d272..37e3d453a0 100644
--- a/src/hypervisor/domain_interface.c
+++ b/src/hypervisor/domain_interface.c
@@ -111,7 +111,7 @@ virDomainInterfaceEthernetConnect(virDomainDef *def,
 
         if (virNetDevMacVLanIsMacvtap(net->ifname)) {
             auditdev = net->ifname;
-            if (virNetDevMacVLanTapOpen(net->ifname, tapfd, tapfdSize) < 0)
+            if (virNetDevMacVLanTapOpen(net->ifname, tapfd, tapfdSize, 
&net->tapfdpath) < 0)
                 goto cleanup;
             if (virNetDevMacVLanTapSetup(tapfd, tapfdSize,
                                          
virDomainInterfaceIsVnetCompatModel(net)) < 0) {
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index 1bca9e8dae..c731b28871 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -379,6 +379,7 @@ virLXCProcessSetupInterfaceDirect(virLXCDriver *driver,
             VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
             cfg->stateDir,
             NULL, 0,
+            &net->tapfdpath,
             macvlan_create_flags) < 0)
         return NULL;
 
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
index 23a23d201a..edc53d53b3 100644
--- a/src/qemu/qemu_interface.c
+++ b/src/qemu/qemu_interface.c
@@ -81,6 +81,7 @@ qemuInterfaceDirectConnect(virDomainDef *def,
                                                &res_ifname,
                                                vmop, cfg->stateDir,
                                                tapfd, tapfdSize,
+                                               &net->tapfdpath,
                                                macvlan_create_flags) < 0)
         goto cleanup;
 
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
index cde9d70eef..07ccef52d9 100644
--- a/src/util/virnetdevmacvlan.c
+++ b/src/util/virnetdevmacvlan.c
@@ -152,24 +152,24 @@ int virNetDevMacVLanDelete(const char *ifname)
 int
 virNetDevMacVLanTapOpen(const char *ifname,
                         int *tapfd,
-                        size_t tapfdSize)
+                        size_t tapfdSize,
+                        char **tapname)
 {
     int retries = 10;
     int ret = -1;
     int ifindex;
     size_t i = 0;
-    g_autofree char *tapname = NULL;
 
     if (virNetDevGetIndex(ifname, &ifindex) < 0)
         return -1;
 
-    tapname = g_strdup_printf("/dev/tap%d", ifindex);
+    *tapname = g_strdup_printf("/dev/tap%d", ifindex);
 
     for (i = 0; i < tapfdSize; i++) {
         int fd = -1;
 
         while (fd < 0) {
-            if ((fd = open(tapname, O_RDWR)) >= 0) {
+            if ((fd = open(*tapname, O_RDWR)) >= 0) {
                 tapfd[i] = fd;
             } else if (retries-- > 0) {
                 /* may need to wait for udev to be done */
@@ -178,7 +178,7 @@ virNetDevMacVLanTapOpen(const char *ifname,
                 /* However, if haven't succeeded, quit. */
                 virReportSystemError(errno,
                                      _("cannot open macvtap tap device %1$s"),
-                                     tapname);
+                                     *tapname);
                 goto cleanup;
             }
         }
@@ -188,6 +188,7 @@ virNetDevMacVLanTapOpen(const char *ifname,
 
  cleanup:
     if (ret < 0) {
+        g_clear_pointer(tapname, g_free);
         while (i--)
             VIR_FORCE_CLOSE(tapfd[i]);
     }
@@ -659,6 +660,7 @@ virNetDevMacVLanCreateWithVPortProfile(const char 
*ifnameRequested,
                                        char *stateDir,
                                        int *tapfd,
                                        size_t tapfdSize,
+                                       char **tapfdpath,
                                        unsigned int flags)
 {
     g_autofree char *ifname = NULL;
@@ -729,7 +731,7 @@ virNetDevMacVLanCreateWithVPortProfile(const char 
*ifnameRequested,
     }
 
     if (flags & VIR_NETDEV_MACVLAN_CREATE_WITH_TAP) {
-        if (virNetDevMacVLanTapOpen(ifname, tapfd, tapfdSize) < 0)
+        if (virNetDevMacVLanTapOpen(ifname, tapfd, tapfdSize, tapfdpath) < 0)
             goto disassociate_exit;
 
         if (virNetDevMacVLanTapSetup(tapfd, tapfdSize, vnet_hdr) < 0)
@@ -888,7 +890,8 @@ int virNetDevMacVLanDelete(const char *ifname G_GNUC_UNUSED)
 int
 virNetDevMacVLanTapOpen(const char *ifname G_GNUC_UNUSED,
                         int *tapfd G_GNUC_UNUSED,
-                        size_t tapfdSize G_GNUC_UNUSED)
+                        size_t tapfdSize G_GNUC_UNUSED,
+                        char **tapname G_GNUC_UNUSED)
 {
     virReportSystemError(ENOSYS, "%s",
                          _("Cannot create macvlan devices on this platform"));
@@ -917,6 +920,7 @@ int virNetDevMacVLanCreateWithVPortProfile(const char 
*ifname G_GNUC_UNUSED,
                                            char *stateDir G_GNUC_UNUSED,
                                            int *tapfd G_GNUC_UNUSED,
                                            size_t tapfdSize G_GNUC_UNUSED,
+                                           char **tapfdpath G_GNUC_UNUSED,
                                            unsigned int unused_flags 
G_GNUC_UNUSED)
 {
     virReportSystemError(ENOSYS, "%s",
diff --git a/src/util/virnetdevmacvlan.h b/src/util/virnetdevmacvlan.h
index 31e4804cdc..7424b87965 100644
--- a/src/util/virnetdevmacvlan.h
+++ b/src/util/virnetdevmacvlan.h
@@ -72,13 +72,15 @@ int virNetDevMacVLanCreateWithVPortProfile(const char 
*ifname,
                                            char *stateDir,
                                            int *tapfd,
                                            size_t tapfdSize,
+                                           char **tapfdpath,
                                            unsigned int flags)
     ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(6)
     ATTRIBUTE_NONNULL(8) ATTRIBUTE_NONNULL(10) G_GNUC_WARN_UNUSED_RESULT;
 
 int virNetDevMacVLanTapOpen(const char *ifname,
                             int *tapfd,
-                            size_t tapfdSize)
+                            size_t tapfdSize,
+                            char **tapname)
    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2)
    G_GNUC_WARN_UNUSED_RESULT;
 
diff --git a/tests/qemustatusxml2xmldata/modern-in.xml 
b/tests/qemustatusxml2xmldata/modern-in.xml
index 3b3e831759..050669f554 100644
--- a/tests/qemustatusxml2xmldata/modern-in.xml
+++ b/tests/qemustatusxml2xmldata/modern-in.xml
@@ -437,6 +437,13 @@
         <alias name='net0'/>
         <address type='pci' domain='0x0000' bus='0x00' slot='0x03' 
function='0x0'/>
       </interface>
+      <interface type='direct'>
+        <mac address='52:54:00:36:bd:3c'/>
+        <source dev='eth0' mode='vepa'/>
+        <model type='rtl8139'/>
+        <tapfd path='/dev/tap8'/>
+        <address type='pci' domain='0x0000' bus='0x00' slot='0x0d' 
function='0x0'/>
+      </interface>
       <serial type='pty'>
         <source path='/dev/pts/67'/>
         <target type='isa-serial' port='0'>

-- 
2.53.0

Reply via email to