mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 11:31:16 +00:00
virnetdevtap.c: Disallow pre-existing TAP devices
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>
This commit is contained in:
parent
6cbbc71e0d
commit
a2ae3d299c
@ -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;
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user