mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 14:45:24 +00:00
audit: audit use of /dev/net/tun, /dev/tapN, /dev/vhost-net
Opening raw network devices with the intent of passing those fds to qemu is worth an audit point. This makes a multi-part audit: first, we audit the device(s) that libvirt opens on behalf of the MAC address of a to-be-created interface (which can independently succeed or fail), then we audit whether qemu actually started the network device with the same MAC (so searching backwards for successful audits with the same MAC will show which fd(s) qemu is actually using). Note that it is possible for the fd to be successfully opened but no attempt made to pass the fd to qemu (for example, because intermediate nwfilter operations failed) - no interface start audit will occur in that case; so the audit for a successful opened fd does not imply rights given to qemu unless there is a followup audit about the attempt to start a new interface. Likewise, when a network device is hot-unplugged, there is only one audit message about the MAC being discontinued; again, searching back to the earlier device open audits will show which fds that qemu quits using (and yes, I checked via /proc/<qemu-pid>/fd that qemu _does_ close out the fds associated with an interface on hot-unplug). The code would require much more refactoring to be able to definitively state which device(s) were discontinued at that point, since we currently don't record anywhere in the XML whether /dev/vhost-net was opened for a given interface. * src/qemu/qemu_audit.h (qemuAuditNetDevice): New prototype. * src/qemu/qemu_audit.c (qemuAuditNetDevice): New function. * src/qemu/qemu_command.h (qemuNetworkIfaceConnect) (qemuPhysIfaceConnect, qemuOpenVhostNet): Adjust prototype. * src/qemu/qemu_command.c (qemuNetworkIfaceConnect) (qemuPhysIfaceConnect, qemuOpenVhostNet): Add audit points and adjust parameters. (qemuBuildCommandLine): Adjust caller. * src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
This commit is contained in:
parent
c52cbe487c
commit
9516a0eca3
@ -127,6 +127,47 @@ qemuAuditNet(virDomainObjPtr vm,
|
||||
VIR_FREE(vmname);
|
||||
}
|
||||
|
||||
/**
|
||||
* qemuAuditNetDevice:
|
||||
* @vm: domain opening a network-related device
|
||||
* @def: details of network device that fd will be tied to
|
||||
* @device: device being opened (such as /dev/vhost-net,
|
||||
* /dev/net/tun, /dev/tanN). Note that merely opening a device
|
||||
* does not mean that qemu owns it; a followup qemuAuditNet
|
||||
* shows whether the fd was passed on.
|
||||
* @success: true if the device was opened
|
||||
*
|
||||
* Log an audit message about an attempted network device open.
|
||||
*/
|
||||
void
|
||||
qemuAuditNetDevice(virDomainDefPtr vmDef, virDomainNetDefPtr netDef,
|
||||
const char *device, bool success)
|
||||
{
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
char macstr[VIR_MAC_STRING_BUFLEN];
|
||||
char *vmname;
|
||||
char *devname;
|
||||
char *rdev;
|
||||
|
||||
virUUIDFormat(vmDef->uuid, uuidstr);
|
||||
virFormatMacAddr(netDef->mac, macstr);
|
||||
rdev = qemuAuditGetRdev(device);
|
||||
|
||||
if (!(vmname = virAuditEncode("vm", vmDef->name)) ||
|
||||
!(devname = virAuditEncode("path", device))) {
|
||||
VIR_WARN0("OOM while encoding audit message");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_AUDIT(VIR_AUDIT_RECORD_RESOURCE, success,
|
||||
"resrc=net reason=open %s uuid=%s net='%s' %s rdev=%s",
|
||||
vmname, uuidstr, macstr, devname, VIR_AUDIT_STR(rdev));
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(vmname);
|
||||
VIR_FREE(devname);
|
||||
VIR_FREE(rdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* qemuAuditHostdev:
|
||||
|
@ -46,6 +46,11 @@ void qemuAuditNet(virDomainObjPtr vm,
|
||||
const char *reason,
|
||||
bool success)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4);
|
||||
void qemuAuditNetDevice(virDomainDefPtr vmDef,
|
||||
virDomainNetDefPtr netDef,
|
||||
const char *device,
|
||||
bool success)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||
void qemuAuditHostdev(virDomainObjPtr vm,
|
||||
virDomainHostdevDefPtr def,
|
||||
const char *reason,
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "uuid.h"
|
||||
#include "c-ctype.h"
|
||||
#include "domain_nwfilter.h"
|
||||
#include "qemu_audit.h"
|
||||
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/stat.h>
|
||||
@ -97,20 +98,20 @@ uname_normalize (struct utsname *ut)
|
||||
|
||||
/**
|
||||
* qemuPhysIfaceConnect:
|
||||
* @def: the definition of the VM (needed by 802.1Qbh and audit)
|
||||
* @conn: pointer to virConnect object
|
||||
* @driver: pointer to the qemud_driver
|
||||
* @net: pointer to he VM's interface description with direct device type
|
||||
* @qemuCaps: flags for qemu
|
||||
* @vmuuid: The UUID of the VM (needed by 802.1Qbh)
|
||||
*
|
||||
* Returns a filedescriptor on success or -1 in case of error.
|
||||
*/
|
||||
int
|
||||
qemuPhysIfaceConnect(virConnectPtr conn,
|
||||
qemuPhysIfaceConnect(virDomainDefPtr def,
|
||||
virConnectPtr conn,
|
||||
struct qemud_driver *driver,
|
||||
virDomainNetDefPtr net,
|
||||
virBitmapPtr qemuCaps,
|
||||
const unsigned char *vmuuid,
|
||||
enum virVMOperationType vmop)
|
||||
{
|
||||
int rc;
|
||||
@ -124,9 +125,10 @@ qemuPhysIfaceConnect(virConnectPtr conn,
|
||||
vnet_hdr = 1;
|
||||
|
||||
rc = openMacvtapTap(net->ifname, net->mac, net->data.direct.linkdev,
|
||||
net->data.direct.mode, vnet_hdr, vmuuid,
|
||||
net->data.direct.mode, vnet_hdr, def->uuid,
|
||||
&net->data.direct.virtPortProfile, &res_ifname,
|
||||
vmop);
|
||||
qemuAuditNetDevice(def, net, res_ifname, rc >= 0);
|
||||
if (rc >= 0) {
|
||||
VIR_FREE(net->ifname);
|
||||
net->ifname = res_ifname;
|
||||
@ -152,11 +154,11 @@ qemuPhysIfaceConnect(virConnectPtr conn,
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)def;
|
||||
(void)conn;
|
||||
(void)net;
|
||||
(void)qemuCaps;
|
||||
(void)driver;
|
||||
(void)vmuuid;
|
||||
(void)vmop;
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("No support for macvtap device"));
|
||||
@ -167,7 +169,8 @@ qemuPhysIfaceConnect(virConnectPtr conn,
|
||||
|
||||
|
||||
int
|
||||
qemuNetworkIfaceConnect(virConnectPtr conn,
|
||||
qemuNetworkIfaceConnect(virDomainDefPtr def,
|
||||
virConnectPtr conn,
|
||||
struct qemud_driver *driver,
|
||||
virDomainNetDefPtr net,
|
||||
virBitmapPtr qemuCaps)
|
||||
@ -247,13 +250,10 @@ qemuNetworkIfaceConnect(virConnectPtr conn,
|
||||
|
||||
memcpy(tapmac, net->mac, VIR_MAC_BUFLEN);
|
||||
tapmac[0] = 0xFE; /* Discourage bridge from using TAP dev MAC */
|
||||
if ((err = brAddTap(driver->brctl,
|
||||
brname,
|
||||
&net->ifname,
|
||||
tapmac,
|
||||
vnet_hdr,
|
||||
true,
|
||||
&tapfd))) {
|
||||
err = brAddTap(driver->brctl, brname, &net->ifname, tapmac,
|
||||
vnet_hdr, true, &tapfd);
|
||||
qemuAuditNetDevice(def, net, "/dev/net/tun", tapfd >= 0);
|
||||
if (err) {
|
||||
if (err == ENOTSUP) {
|
||||
/* In this particular case, give a better diagnostic. */
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
@ -304,7 +304,8 @@ cleanup:
|
||||
|
||||
|
||||
int
|
||||
qemuOpenVhostNet(virDomainNetDefPtr net,
|
||||
qemuOpenVhostNet(virDomainDefPtr def,
|
||||
virDomainNetDefPtr net,
|
||||
virBitmapPtr qemuCaps,
|
||||
int *vhostfd)
|
||||
{
|
||||
@ -342,6 +343,7 @@ qemuOpenVhostNet(virDomainNetDefPtr net,
|
||||
}
|
||||
|
||||
*vhostfd = open("/dev/vhost-net", O_RDWR);
|
||||
qemuAuditNetDevice(def, net, "/dev/vhost-net", *vhostfd >= 0);
|
||||
|
||||
/* If the config says explicitly to use vhost and we couldn't open it,
|
||||
* report an error.
|
||||
@ -3460,7 +3462,7 @@ qemuBuildCommandLine(virConnectPtr conn,
|
||||
|
||||
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
|
||||
net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
|
||||
int tapfd = qemuNetworkIfaceConnect(conn, driver, net,
|
||||
int tapfd = qemuNetworkIfaceConnect(def, conn, driver, net,
|
||||
qemuCaps);
|
||||
if (tapfd < 0)
|
||||
goto error;
|
||||
@ -3472,10 +3474,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
||||
tapfd) >= sizeof(tapfd_name))
|
||||
goto no_memory;
|
||||
} else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
int tapfd = qemuPhysIfaceConnect(conn, driver, net,
|
||||
qemuCaps,
|
||||
def->uuid,
|
||||
vmop);
|
||||
int tapfd = qemuPhysIfaceConnect(def, conn, driver, net,
|
||||
qemuCaps, vmop);
|
||||
if (tapfd < 0)
|
||||
goto error;
|
||||
|
||||
@ -3494,7 +3494,7 @@ qemuBuildCommandLine(virConnectPtr conn,
|
||||
network device */
|
||||
int vhostfd;
|
||||
|
||||
if (qemuOpenVhostNet(net, qemuCaps, &vhostfd) < 0)
|
||||
if (qemuOpenVhostNet(def, net, qemuCaps, &vhostfd) < 0)
|
||||
goto error;
|
||||
if (vhostfd >= 0) {
|
||||
virCommandTransferFD(cmd, vhostfd);
|
||||
|
@ -116,20 +116,22 @@ char * qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev);
|
||||
|
||||
|
||||
|
||||
int qemuNetworkIfaceConnect(virConnectPtr conn,
|
||||
int qemuNetworkIfaceConnect(virDomainDefPtr def,
|
||||
virConnectPtr conn,
|
||||
struct qemud_driver *driver,
|
||||
virDomainNetDefPtr net,
|
||||
virBitmapPtr qemuCaps)
|
||||
ATTRIBUTE_NONNULL(1);
|
||||
ATTRIBUTE_NONNULL(2);
|
||||
|
||||
int qemuPhysIfaceConnect(virConnectPtr conn,
|
||||
int qemuPhysIfaceConnect(virDomainDefPtr def,
|
||||
virConnectPtr conn,
|
||||
struct qemud_driver *driver,
|
||||
virDomainNetDefPtr net,
|
||||
virBitmapPtr qemuCaps,
|
||||
const unsigned char *vmuuid,
|
||||
enum virVMOperationType vmop);
|
||||
|
||||
int qemuOpenVhostNet(virDomainNetDefPtr net,
|
||||
int qemuOpenVhostNet(virDomainDefPtr def,
|
||||
virDomainNetDefPtr net,
|
||||
virBitmapPtr qemuCaps,
|
||||
int *vhostfd);
|
||||
|
||||
|
@ -576,9 +576,10 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((tapfd = qemuNetworkIfaceConnect(conn, driver, net, qemuCaps)) < 0)
|
||||
if ((tapfd = qemuNetworkIfaceConnect(vm->def, conn, driver, net,
|
||||
qemuCaps)) < 0)
|
||||
return -1;
|
||||
if (qemuOpenVhostNet(net, qemuCaps, &vhostfd) < 0)
|
||||
if (qemuOpenVhostNet(vm->def, net, qemuCaps, &vhostfd) < 0)
|
||||
goto cleanup;
|
||||
} else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
|
||||
if (priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
|
||||
@ -589,12 +590,11 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((tapfd = qemuPhysIfaceConnect(conn, driver, net,
|
||||
if ((tapfd = qemuPhysIfaceConnect(vm->def, conn, driver, net,
|
||||
qemuCaps,
|
||||
vm->def->uuid,
|
||||
VIR_VM_OP_CREATE)) < 0)
|
||||
return -1;
|
||||
if (qemuOpenVhostNet(net, qemuCaps, &vhostfd) < 0)
|
||||
if (qemuOpenVhostNet(vm->def, net, qemuCaps, &vhostfd) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user