[libvirt] [PATCHv3 2/2] audit: audit use of /dev/net/tun, /dev/tapN, /dev/vhost-net

Laine Stump laine at laine.org
Thu Mar 10 16:16:03 UTC 2011


On 03/09/2011 03:42 PM, Eric Blake wrote:
> 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.
> ---
>   src/qemu/qemu_audit.c   |   41 +++++++++++++++++++++++++++++++++++++++++
>   src/qemu/qemu_audit.h   |    5 +++++
>   src/qemu/qemu_command.c |   40 ++++++++++++++++++++--------------------
>   src/qemu/qemu_command.h |   12 +++++++-----
>   src/qemu/qemu_hotplug.c |    8 ++++----
>   5 files changed, 77 insertions(+), 29 deletions(-)
>
> diff --git a/src/qemu/qemu_audit.c b/src/qemu/qemu_audit.c
> index 5bdf655..40b68ff 100644
> --- a/src/qemu/qemu_audit.c
> +++ b/src/qemu/qemu_audit.c
> @@ -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:
> diff --git a/src/qemu/qemu_audit.h b/src/qemu/qemu_audit.h
> index a2fbe11..14c7da5 100644
> --- a/src/qemu/qemu_audit.h
> +++ b/src/qemu/qemu_audit.h
> @@ -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,
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 8cf1737..0fc466c 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -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);
> diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
> index 2ae364c..528031d 100644
> --- a/src/qemu/qemu_command.h
> +++ b/src/qemu/qemu_command.h
> @@ -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);
>
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index e8567ad..4646fd7 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -576,7 +576,8 @@ 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;
>       } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
>           if (priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
> @@ -587,9 +588,8 @@ 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;
>       }
> @@ -599,7 +599,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
>           net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
>           /* Attempt to use vhost-net mode for these types of
>              network device */
> -        if (qemuOpenVhostNet(net, qemuCaps,&vhostfd)<  0)
> +        if (qemuOpenVhostNet(vm->def, net, qemuCaps,&vhostfd)<  0)
>               goto cleanup;
>
>           if (vhostfd>= 0&&

ACK




More information about the libvir-list mailing list