]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virnetdevtap.c: Disallow pre-existing TAP devices
authorMichal Privoznik <mprivozn@redhat.com>
Thu, 8 Dec 2022 14:35:36 +0000 (15:35 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Fri, 9 Dec 2022 07:46:39 +0000 (08:46 +0100)
When starting a guest with <interface/> which has the target
device name set (i.e. not generated by us), it may happen that
the TAP device already exists. This then may lead to all sorts of
problems. For instance: for <interface type='network'/> the TAP
device is plugged into the network's bridge, but since the TAP
device is persistent it remains plugged there even after the
guest is shut off. We don't have a code that unplugs TAP devices
from the bridge because TAP devices we create are transient, i.e.
are removed automatically when QEMU closes their FD.

The only exception is <interface type='ethernet'/> with <target
managed='no'/> where we specifically want to let users use
pre-created TAP device and basically not touch it at all.

There's another reason for denying to use a pre-created TAP
devices: if we ever have bug in TAP name generation, we may
re-use a TAP device from another domain.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2144738
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Laine Stump <laine@redhat.com>
src/qemu/qemu_interface.c
src/util/virnetdevtap.c
src/util/virnetdevtap.h

index 4cc76e07a50bf628429ab2f9e9f498c13922a675..264d5e060cf7ffd60d49136f4e435d59ca9d5620 100644 (file)
@@ -461,6 +461,8 @@ qemuInterfaceEthernetConnect(virDomainDef *def,
         if (!net->ifname)
             template_ifname = true;
 
+        tap_create_flags |= VIR_NETDEV_TAP_CREATE_ALLOW_EXISTING;
+
         if (virNetDevTapCreate(&net->ifname, tunpath, tapfd, tapfdSize,
                                tap_create_flags) < 0) {
             goto cleanup;
index 112a1e8b99f9521f4f71a98b4b7dcf4ef844e672..a4ead0ae93f150a3f3cb17e0df303d4b9f5dfbf0 100644 (file)
@@ -148,12 +148,15 @@ virNetDevTapGetRealDeviceName(char *ifname G_GNUC_UNUSED)
  * @tunpath: path to the tun device (if NULL, /dev/net/tun is used)
  * @tapfds: array of file descriptors return value for the new tap device
  * @tapfdSize: number of file descriptors in @tapfd
- * @flags: OR of virNetDevTapCreateFlags. Only one flag is recognized:
+ * @flags: OR of virNetDevTapCreateFlags. Only the following flags are
+ *         recognized:
  *
  *   VIR_NETDEV_TAP_CREATE_VNET_HDR
  *     - Enable IFF_VNET_HDR on the tap device
  *   VIR_NETDEV_TAP_CREATE_PERSIST
  *     - The device will persist after the file descriptor is closed
+ *   VIR_NETDEV_TAP_CREATE_ALLOW_EXISTING
+ *     - The device creation fails if @ifname already exists
  *
  * Creates a tap interface. The caller must use virNetDevTapDelete to
  * remove a persistent TAP device when it is no longer needed. In case
@@ -170,6 +173,7 @@ int virNetDevTapCreate(char **ifname,
 {
     size_t i = 0;
     struct ifreq ifr;
+    int rc;
     int ret = -1;
     int fd = -1;
 
@@ -179,9 +183,24 @@ int virNetDevTapCreate(char **ifname,
      * can lead to race conditions).  if ifname is just a
      * user-provided name, virNetDevGenerateName leaves it
      * unchanged. */
-    if (virNetDevGenerateName(ifname, VIR_NET_DEV_GEN_NAME_VNET) < 0)
+    rc = virNetDevGenerateName(ifname, VIR_NET_DEV_GEN_NAME_VNET);
+    if (rc < 0)
         return -1;
 
+    if (rc > 0 &&
+        !(flags & VIR_NETDEV_TAP_CREATE_ALLOW_EXISTING)) {
+        rc = virNetDevExists(*ifname);
+
+        if (rc < 0) {
+            return -1;
+        } else if (rc > 0) {
+            virReportError(VIR_ERR_OPERATION_INVALID,
+                           _("The %s interface already exists"),
+                           *ifname);
+            return -1;
+        }
+    }
+
     if (!tunpath)
         tunpath = "/dev/net/tun";
 
index 197ea10f94a2661e8682dce60eda23aa22f1cb96..c9d29c0384b7ba192cb951546f5f9492005f4663 100644 (file)
@@ -56,6 +56,8 @@ typedef enum {
    VIR_NETDEV_TAP_CREATE_USE_MAC_FOR_BRIDGE = 1 << 2,
    /* The device will persist after the file descriptor is closed */
    VIR_NETDEV_TAP_CREATE_PERSIST            = 1 << 3,
+   /* The device is allowed to exist before creation */
+   VIR_NETDEV_TAP_CREATE_ALLOW_EXISTING     = 1 << 4,
 } virNetDevTapCreateFlags;
 
 int