]> xenbits.xensource.com Git - libvirt.git/commitdiff
security: DAC: Plumb usage of chown callback
authorPeter Krempa <pkrempa@redhat.com>
Thu, 10 Jul 2014 14:05:07 +0000 (16:05 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Thu, 24 Jul 2014 07:59:00 +0000 (09:59 +0200)
Use the callback to set disk and storage image labels by modifying the
existing functions and adding wrappers to avoid refactoring a lot of the
code.

src/security/security_dac.c

index 1fb0c86ea881c8092d7a36105d4ccdbed789ce0e..dfad01393aad7ecc38141e8b3025f8166e4ac761 100644 (file)
@@ -230,23 +230,56 @@ virSecurityDACPreFork(virSecurityManagerPtr mgr)
 }
 
 static int
-virSecurityDACSetOwnership(const char *path, uid_t uid, gid_t gid)
+virSecurityDACSetOwnershipInternal(virSecurityDACDataPtr priv,
+                                   virStorageSourcePtr src,
+                                   const char *path,
+                                   uid_t uid,
+                                   gid_t gid)
 {
+    int rc;
+    int chown_errno;
+
     VIR_INFO("Setting DAC user and group on '%s' to '%ld:%ld'",
-             path, (long) uid, (long) gid);
+             NULLSTR(src ? src->path : path), (long) uid, (long) gid);
+
+    if (priv && src && priv->chownCallback) {
+        rc = priv->chownCallback(src, uid, gid);
+        /* here path is used only for error messages */
+        path = NULLSTR(src->path);
+
+        /* on -2 returned an error was already reported */
+        if (rc == -2)
+            return -1;
 
-    if (chown(path, uid, gid) < 0) {
+        /* on -1 only errno was set */
+        chown_errno = errno;
+    } else {
         struct stat sb;
-        int chown_errno = errno;
 
-        if (stat(path, &sb) >= 0) {
+        if (!path) {
+            if (!src || !src->path)
+                return 0;
+
+            if (!virStorageSourceIsLocalStorage(src))
+                return 0;
+
+            path = src->path;
+        }
+
+        rc = chown(path, uid, gid);
+        chown_errno = errno;
+
+        if (rc < 0 &&
+            stat(path, &sb) >= 0) {
             if (sb.st_uid == uid &&
                 sb.st_gid == gid) {
                 /* It's alright, there's nothing to change anyway. */
                 return 0;
             }
         }
+    }
 
+    if (rc < 0) {
         if (chown_errno == EOPNOTSUPP || chown_errno == EINVAL) {
             VIR_INFO("Setting user and group to '%ld:%ld' on '%s' not "
                      "supported by filesystem",
@@ -270,13 +303,31 @@ virSecurityDACSetOwnership(const char *path, uid_t uid, gid_t gid)
     return 0;
 }
 
+
 static int
-virSecurityDACRestoreSecurityFileLabel(const char *path)
+virSecurityDACSetOwnership(const char *path, uid_t uid, gid_t gid)
+{
+    return virSecurityDACSetOwnershipInternal(NULL, NULL, path, uid, gid);
+}
+
+
+static int
+virSecurityDACRestoreSecurityFileLabelInternal(virSecurityDACDataPtr priv,
+                                               virStorageSourcePtr src,
+                                               const char *path)
 {
-    VIR_INFO("Restoring DAC user and group on '%s'", path);
+    VIR_INFO("Restoring DAC user and group on '%s'",
+             NULLSTR(src ? src->path : path));
 
     /* XXX record previous ownership */
-    return virSecurityDACSetOwnership(path, 0, 0);
+    return virSecurityDACSetOwnershipInternal(priv, src, path, 0, 0);
+}
+
+
+static int
+virSecurityDACRestoreSecurityFileLabel(const char *path)
+{
+    return virSecurityDACRestoreSecurityFileLabelInternal(NULL, NULL, path);
 }
 
 
@@ -294,10 +345,6 @@ virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr,
     if (!priv->dynamicOwnership)
         return 0;
 
-    /* XXX: Add support for gluster DAC permissions */
-    if (!src->path || !virStorageSourceIsLocalStorage(src))
-        return 0;
-
     secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
     if (secdef && !secdef->relabel)
         return 0;
@@ -315,7 +362,7 @@ virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr,
             return -1;
     }
 
-    return virSecurityDACSetOwnership(src->path, user, group);
+    return virSecurityDACSetOwnershipInternal(priv, src, NULL, user, group);
 }
 
 
@@ -349,9 +396,6 @@ virSecurityDACRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
     if (!priv->dynamicOwnership)
         return 0;
 
-    if (!src->path || !virStorageSourceIsLocalStorage(src))
-        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 domains and try to figure out if it is in use, but this would
@@ -373,9 +417,16 @@ virSecurityDACRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
      * ownership, because that kills access on the destination host which is
      * sub-optimal for the guest VM's I/O attempts :-) */
     if (migrated) {
-        int rc = virFileIsSharedFS(src->path);
-        if (rc < 0)
-            return -1;
+        int rc = 1;
+
+        if (virStorageSourceIsLocalStorage(src)) {
+            if (!src->path)
+                return 0;
+
+            if ((rc = virFileIsSharedFS(src->path)) < 0)
+                return -1;
+        }
+
         if (rc == 1) {
             VIR_DEBUG("Skipping image label restore on %s because FS is shared",
                       src->path);
@@ -383,7 +434,7 @@ virSecurityDACRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
         }
     }
 
-    return virSecurityDACRestoreSecurityFileLabel(src->path);
+    return virSecurityDACRestoreSecurityFileLabelInternal(priv, src, NULL);
 }