[libvirt] [PATCH 01/12] Make security drivers responsible for checking dynamic vs static labelling

Daniel Veillard veillard at redhat.com
Wed Jan 20 15:43:58 UTC 2010


On Wed, Jan 20, 2010 at 03:14:58PM +0000, Daniel P. Berrange wrote:
> The QEMU driver is doing 90% of the calls to check for static vs
> dynamic labelling. Except it is forgetting todo so in many places,
> in particular hotplug is mistakenly assigning disk labels. Move
> all this logic into the security drivers themselves, so the HV
> drivers don't have to think about it.
> 
> * src/security/security_driver.h: Add virDomainObjPtr parameter
>   to virSecurityDomainRestoreHostdevLabel and to
>   virSecurityDomainRestoreSavedStateLabel
> * src/security/security_selinux.c, src/security/security_apparmor.c:
>   Add explicit checks for VIR_DOMAIN_SECLABEL_STATIC and skip all
>   chcon() code in those cases
> * src/qemu/qemu_driver.c: Remove all checks for VIR_DOMAIN_SECLABEL_STATIC
>   or VIR_DOMAIN_SECLABEL_DYNAMIC. Add missing checks for possibly NULL
>   driver entry points.
> ---
>  src/qemu/qemu_driver.c           |   40 ++++++++++++-------
>  src/security/security_apparmor.c |   46 +++++++++++++++-------
>  src/security/security_driver.h   |    2 +
>  src/security/security_selinux.c  |   78 ++++++++++++++++++++++++++++----------
>  4 files changed, 117 insertions(+), 49 deletions(-)
> 
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 2d80774..446f6ff 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -855,8 +855,7 @@ qemuReconnectDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaq
>          goto error;
>      }
>  
> -    if (obj->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
> -        driver->securityDriver &&
> +    if (driver->securityDriver &&
>          driver->securityDriver->domainReserveSecurityLabel &&
>          driver->securityDriver->domainReserveSecurityLabel(NULL, obj) < 0)
>          goto error;
> @@ -2441,11 +2440,14 @@ cleanup:
>  
>  static int qemudDomainSetSecurityLabel(virConnectPtr conn, struct qemud_driver *driver, virDomainObjPtr vm)
>  {
> -    if (vm->def->seclabel.label != NULL)
> -        if (driver->securityDriver && driver->securityDriver->domainSetSecurityLabel)
> -            return driver->securityDriver->domainSetSecurityLabel(conn, driver->securityDriver,
> -                                                                 vm);
> -    return 0;
> +    int rc = 0;
> +
> +    if (driver->securityDriver &&
> +        driver->securityDriver->domainSetSecurityLabel &&
> +        driver->securityDriver->domainSetSecurityLabel(conn, driver->securityDriver, vm) < 0)
> +        rc = -1;
> +
> +    return rc;
>  }
>  
>  
> @@ -2758,8 +2760,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
>  
>      /* If you are using a SecurityDriver with dynamic labelling,
>         then generate a security label for isolation */
> -    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
> -        driver->securityDriver &&
> +    if (driver->securityDriver &&
>          driver->securityDriver->domainGenSecurityLabel &&
>          driver->securityDriver->domainGenSecurityLabel(conn, vm) < 0)
>          return -1;
> @@ -3054,7 +3055,8 @@ static void qemudShutdownVMDaemon(virConnectPtr conn,
>      virKillProcess(vm->pid, SIGKILL);
>  
>      /* Reset Security Labels */
> -    if (driver->securityDriver)
> +    if (driver->securityDriver &&
> +        driver->securityDriver->domainRestoreSecurityLabel)
>          driver->securityDriver->domainRestoreSecurityLabel(conn, vm);
>  
>      /* Clear out dynamically assigned labels */
> @@ -4166,7 +4168,7 @@ static int qemudDomainSave(virDomainPtr dom,
>  
>      if (driver->securityDriver &&
>          driver->securityDriver->domainRestoreSavedStateLabel &&
> -        driver->securityDriver->domainRestoreSavedStateLabel(dom->conn, path) == -1)
> +        driver->securityDriver->domainRestoreSavedStateLabel(dom->conn, vm, path) == -1)
>          goto endjob;
>  
>      ret = 0;
> @@ -4296,7 +4298,7 @@ static int qemudDomainCoreDump(virDomainPtr dom,
>  
>      if (driver->securityDriver &&
>          driver->securityDriver->domainRestoreSavedStateLabel &&
> -        driver->securityDriver->domainRestoreSavedStateLabel(dom->conn, path) == -1)
> +        driver->securityDriver->domainRestoreSavedStateLabel(dom->conn, vm, path) == -1)
>          goto endjob;
>  
>  endjob:
> @@ -5871,6 +5873,7 @@ static int qemudDomainAttachHostDevice(virConnectPtr conn,
>      if (qemuDomainSetDeviceOwnership(conn, driver, dev, 0) < 0)
>          return -1;
>      if (driver->securityDriver &&
> +        driver->securityDriver->domainSetSecurityHostdevLabel &&
>          driver->securityDriver->domainSetSecurityHostdevLabel(conn, vm, dev->data.hostdev) < 0)
>          return -1;
>  
> @@ -5947,7 +5950,8 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
>          switch (dev->data.disk->device) {
>          case VIR_DOMAIN_DISK_DEVICE_CDROM:
>          case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
> -            if (driver->securityDriver)
> +            if (driver->securityDriver &&
> +                driver->securityDriver->domainSetSecurityImageLabel)
>                  driver->securityDriver->domainSetSecurityImageLabel(dom->conn, vm, dev->data.disk);
>  
>              if (qemuDomainSetDeviceOwnership(dom->conn, driver, dev, 0) < 0)
> @@ -5957,7 +5961,8 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
>              break;
>  
>          case VIR_DOMAIN_DISK_DEVICE_DISK:
> -            if (driver->securityDriver)
> +            if (driver->securityDriver &&
> +                driver->securityDriver->domainSetSecurityImageLabel)
>                  driver->securityDriver->domainSetSecurityImageLabel(dom->conn, vm, dev->data.disk);
>  
>              if (qemuDomainSetDeviceOwnership(dom->conn, driver, dev, 0) < 0)
> @@ -6347,6 +6352,7 @@ static int qemudDomainDetachHostDevice(virConnectPtr conn,
>      }
>  
>      if (driver->securityDriver &&
> +        driver->securityDriver->domainSetSecurityHostdevLabel &&
>          driver->securityDriver->domainSetSecurityHostdevLabel(conn, vm, dev->data.hostdev) < 0)
>          VIR_WARN0("Failed to restore device labelling");
>  
> @@ -6392,7 +6398,8 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
>          dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
>          dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) {
>          ret = qemudDomainDetachPciDiskDevice(dom->conn, driver, vm, dev);
> -        if (driver->securityDriver)
> +        if (driver->securityDriver &&
> +            driver->securityDriver->domainRestoreSecurityImageLabel)
>              driver->securityDriver->domainRestoreSecurityImageLabel(dom->conn, vm, dev->data.disk);
>          if (qemuDomainSetDeviceOwnership(dom->conn, driver, dev, 1) < 0)
>              VIR_WARN0("Fail to restore disk device ownership");
> @@ -6409,6 +6416,9 @@ static int qemudDomainDetachDevice(virDomainPtr dom,
>          }
>      } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
>          ret = qemudDomainDetachHostDevice(dom->conn, driver, vm, dev);
> +        if (driver->securityDriver &&
> +            driver->securityDriver->domainRestoreSecurityHostdevLabel)
> +            driver->securityDriver->domainRestoreSecurityHostdevLabel(dom->conn, vm, dev->data.hostdev);
>      } else {
>          qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
>                           "%s", _("This type of device cannot be hot unplugged"));
> diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
> index 5844768..0f9ff95 100644
> --- a/src/security/security_apparmor.c
> +++ b/src/security/security_apparmor.c
> @@ -327,6 +327,9 @@ AppArmorGenSecurityLabel(virConnectPtr conn, virDomainObjPtr vm)
>      int rc = -1;
>      char *profile_name = NULL;
>  
> +    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      if ((vm->def->seclabel.label) ||
>          (vm->def->seclabel.model) || (vm->def->seclabel.imagelabel)) {
>          virSecurityReportError(conn, VIR_ERR_INTERNAL_ERROR,
> @@ -425,7 +428,7 @@ AppArmorRestoreSecurityLabel(virConnectPtr conn, virDomainObjPtr vm)
>      const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
>      int rc = 0;
>  
> -    if (secdef->imagelabel) {
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
>          if ((rc = remove_profile(secdef->label)) != 0) {
>              virSecurityReportError(conn, VIR_ERR_INTERNAL_ERROR,
>                                     _("could not remove profile for \'%s\'"),
> @@ -486,21 +489,23 @@ AppArmorRestoreSecurityImageLabel(virConnectPtr conn,
>      int rc = -1;
>      char *profile_name = NULL;
>  
> -    if (secdef->imagelabel) {
> -        if ((profile_name = get_profile_name(conn, vm)) == NULL)
> -            return rc;
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
>  
> -        /* Update the profile only if it is loaded */
> -        if (profile_loaded(secdef->imagelabel) >= 0) {
> -            if (load_profile(conn, secdef->imagelabel, vm, NULL) < 0) {
> -                virSecurityReportError(conn, VIR_ERR_INTERNAL_ERROR,
> -                                       _("cannot update AppArmor profile "
> -                                       "\'%s\'"),
> -                                       secdef->imagelabel);
> -                goto clean;
> -            }
> +    if ((profile_name = get_profile_name(conn, vm)) == NULL)
> +        return rc;
> +
> +    /* Update the profile only if it is loaded */
> +    if (profile_loaded(secdef->imagelabel) >= 0) {
> +        if (load_profile(conn, secdef->imagelabel, vm, NULL) < 0) {
> +            virSecurityReportError(conn, VIR_ERR_INTERNAL_ERROR,
> +                                   _("cannot update AppArmor profile "
> +                                     "\'%s\'"),
> +                                   secdef->imagelabel);
> +            goto clean;
>          }
>      }
> +
>      rc = 0;
>    clean:
>      VIR_FREE(profile_name);
> @@ -517,6 +522,9 @@ AppArmorSetSecurityImageLabel(virConnectPtr conn,
>      int rc = -1;
>      char *profile_name;
>  
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      if (!disk->src)
>          return 0;
>  
> @@ -576,19 +584,29 @@ AppArmorReserveSecurityLabel(virConnectPtr conn ATTRIBUTE_UNUSED,
>  
>  static int
>  AppArmorSetSecurityHostdevLabel(virConnectPtr conn ATTRIBUTE_UNUSED,
> -                                virDomainObjPtr vm ATTRIBUTE_UNUSED,
> +                                virDomainObjPtr vm,
>                                  virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)
>  
>  {
> +    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
> +
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      /* TODO: call load_profile with an update vm->def */
>      return 0;
>  }
>  
>  static int
>  AppArmorRestoreSecurityHostdevLabel(virConnectPtr conn ATTRIBUTE_UNUSED,
> +                                    virDomainObjPtr vm,
>                                      virDomainHostdevDefPtr dev ATTRIBUTE_UNUSED)
>  
>  {
> +    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      /* TODO: call load_profile (needs virDomainObjPtr vm) */
>      return 0;
>  }
> diff --git a/src/security/security_driver.h b/src/security/security_driver.h
> index 5514962..97c9002 100644
> --- a/src/security/security_driver.h
> +++ b/src/security/security_driver.h
> @@ -38,6 +38,7 @@ typedef int (*virSecurityDomainSetImageLabel) (virConnectPtr conn,
>                                                 virDomainObjPtr vm,
>                                                 virDomainDiskDefPtr disk);
>  typedef int (*virSecurityDomainRestoreHostdevLabel) (virConnectPtr conn,
> +                                                     virDomainObjPtr vm,
>                                                       virDomainHostdevDefPtr dev);
>  typedef int (*virSecurityDomainSetHostdevLabel) (virConnectPtr conn,
>                                                   virDomainObjPtr vm,
> @@ -46,6 +47,7 @@ typedef int (*virSecurityDomainSetSavedStateLabel) (virConnectPtr conn,
>                                                      virDomainObjPtr vm,
>                                                      const char *savefile);
>  typedef int (*virSecurityDomainRestoreSavedStateLabel) (virConnectPtr conn,
> +                                                        virDomainObjPtr vm,
>                                                          const char *savefile);
>  typedef int (*virSecurityDomainGenLabel) (virConnectPtr conn,
>                                            virDomainObjPtr sec);
> diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
> index cb585ed..c48f4c8 100644
> --- a/src/security/security_selinux.c
> +++ b/src/security/security_selinux.c
> @@ -165,6 +165,9 @@ SELinuxGenSecurityLabel(virConnectPtr conn,
>      int c1 = 0;
>      int c2 = 0;
>  
> +    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      if (vm->def->seclabel.label ||
>          vm->def->seclabel.model ||
>          vm->def->seclabel.imagelabel) {
> @@ -225,6 +228,9 @@ SELinuxReserveSecurityLabel(virConnectPtr conn,
>      context_t ctx = NULL;
>      const char *mcs;
>  
> +    if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      if (getpidcon(vm->pid, &pctx) == -1) {
>          virReportSystemError(conn, errno,
>                               _("unable to get PID %d security context"), vm->pid);
> @@ -376,9 +382,14 @@ err:
>  
>  static int
>  SELinuxRestoreSecurityImageLabel(virConnectPtr conn,
> -                                 virDomainObjPtr vm ATTRIBUTE_UNUSED,
> +                                 virDomainObjPtr vm,
>                                   virDomainDiskDefPtr disk)
>  {
> +    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
> +
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      /* Don't restore labels on readoly/shared disks, because
>       * other VMs may still be accessing these
>       * Alternatively we could iterate over all running
> @@ -405,6 +416,9 @@ SELinuxSetSecurityImageLabel(virConnectPtr conn,
>      const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
>      const char *path;
>  
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      if (!disk->src)
>          return 0;
>  
> @@ -474,8 +488,12 @@ SELinuxSetSecurityHostdevLabel(virConnectPtr conn,
>                                 virDomainHostdevDefPtr dev)
>  
>  {
> +    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
>      int ret = -1;
>  
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
>          return 0;
>  
> @@ -541,11 +559,16 @@ SELinuxRestoreSecurityUSBLabel(virConnectPtr conn,
>  
>  static int
>  SELinuxRestoreSecurityHostdevLabel(virConnectPtr conn,
> +                                   virDomainObjPtr vm,
>                                     virDomainHostdevDefPtr dev)
>  
>  {
> +    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
>      int ret = -1;
>  
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
>          return 0;
>  
> @@ -601,25 +624,28 @@ SELinuxRestoreSecurityLabel(virConnectPtr conn,
>  
>      VIR_DEBUG("Restoring security label on %s", vm->def->name);
>  
> -    if (secdef->imagelabel) {
> -        for (i = 0 ; i < vm->def->nhostdevs ; i++) {
> -            if (SELinuxRestoreSecurityHostdevLabel(conn, vm->def->hostdevs[i]) < 0)
> -                rc = -1;
> -        }
> -        for (i = 0 ; i < vm->def->ndisks ; i++) {
> -            if (SELinuxRestoreSecurityImageLabel(conn, vm,
> -                                                 vm->def->disks[i]) < 0)
> -                rc = -1;
> -        }
> -        VIR_FREE(secdef->model);
> -        VIR_FREE(secdef->label);
> -        context_t con = context_new(secdef->imagelabel);
> -        if (con) {
> -            mcsRemove(context_range_get(con));
> -            context_free(con);
> -        }
> -        VIR_FREE(secdef->imagelabel);
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
> +    for (i = 0 ; i < vm->def->nhostdevs ; i++) {
> +        if (SELinuxRestoreSecurityHostdevLabel(conn, vm, vm->def->hostdevs[i]) < 0)
> +            rc = -1;
>      }
> +    for (i = 0 ; i < vm->def->ndisks ; i++) {
> +        if (SELinuxRestoreSecurityImageLabel(conn, vm,
> +                                             vm->def->disks[i]) < 0)
> +            rc = -1;
> +    }
> +    context_t con = context_new(secdef->label);
> +    if (con) {
> +        mcsRemove(context_range_get(con));
> +        context_free(con);
> +    }
> +
> +    VIR_FREE(secdef->model);
> +    VIR_FREE(secdef->label);
> +    VIR_FREE(secdef->imagelabel);
> +
>      return rc;
>  }
>  
> @@ -631,14 +657,23 @@ SELinuxSetSavedStateLabel(virConnectPtr conn,
>  {
>      const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
>  
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      return SELinuxSetFilecon(conn, savefile, secdef->imagelabel);
>  }
>  
>  
>  static int
>  SELinuxRestoreSavedStateLabel(virConnectPtr conn,
> +                              virDomainObjPtr vm,
>                                const char *savefile)
>  {
> +    const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
> +
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC)
> +        return 0;
> +
>      return SELinuxRestoreSecurityFileLabel(conn, savefile);
>  }
>  
> @@ -666,6 +701,9 @@ SELinuxSetSecurityLabel(virConnectPtr conn,
>      const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
>      int i;
>  
> +    if (vm->def->seclabel.label == NULL)
> +        return 0;
> +
>      if (!STREQ(drv->name, secdef->model)) {
>          virSecurityReportError(conn, VIR_ERR_INTERNAL_ERROR,
>                                 _("security label driver mismatch: "
> @@ -684,7 +722,7 @@ SELinuxSetSecurityLabel(virConnectPtr conn,
>              return -1;
>      }
>  
> -    if (secdef->imagelabel) {
> +    if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
>          for (i = 0 ; i < vm->def->ndisks ; i++) {
>              /* XXX fixme - we need to recursively label the entriy tree :-( */
>              if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR)

  ACK, also adds some missing check for some driver->securityDriver
entry point. My only concern is dereferencing vm->def->seclabel without
any check for NULL, I would feel better if that extra safety belt was
added,

Daniel

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list