[PATCH RESEND 1/4] qemu: Expose file opening functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The qemuOpenFileAs and qemuOpenFile functions are gonna
be needed in later patches. However, they are static now.

Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx>
---
 src/qemu/qemu_domain.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_domain.h |  10 ++++
 src/qemu/qemu_driver.c | 155 -------------------------------------------------
 3 files changed, 156 insertions(+), 155 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index f2cca70..b5770c5 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -39,6 +39,7 @@
 #include "virstoragefile.h"
 #include "virstring.h"
 
+#include <sys/stat.h>
 #include <sys/time.h>
 #include <fcntl.h>
 
@@ -2355,3 +2356,148 @@ qemuDomainUpdateDeviceList(virQEMUDriverPtr driver,
     priv->qemuDevices = aliases;
     return 0;
 }
+
+/* Internal function to properly create or open existing files, with
+ * ownership affected by qemu driver setup and domain DAC label.  */
+int
+qemuOpenFile(virQEMUDriverPtr driver,
+             virDomainObjPtr vm,
+             const char *path, int oflags,
+             bool *needUnlink, bool *bypassSecurityDriver)
+{
+    int ret = -1;
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    uid_t user = cfg->user;
+    gid_t group = cfg->group;
+    bool dynamicOwnership = cfg->dynamicOwnership;
+    virSecurityLabelDefPtr seclabel;
+
+    virObjectUnref(cfg);
+
+    /* TODO: Take imagelabel into account? */
+    if (vm &&
+        (seclabel = virDomainDefGetSecurityLabelDef(vm->def, "dac")) != NULL &&
+        (virParseOwnershipIds(seclabel->label, &user, &group) < 0))
+        goto cleanup;
+
+    ret = qemuOpenFileAs(user, group, dynamicOwnership,
+                         path, oflags, needUnlink, bypassSecurityDriver);
+
+ cleanup:
+    return ret;
+}
+
+int
+qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
+               bool dynamicOwnership,
+               const char *path, int oflags,
+               bool *needUnlink, bool *bypassSecurityDriver)
+{
+    struct stat sb;
+    bool is_reg = true;
+    bool need_unlink = false;
+    bool bypass_security = false;
+    unsigned int vfoflags = 0;
+    int fd = -1;
+    int path_shared = virStorageFileIsSharedFS(path);
+    uid_t uid = getuid();
+    gid_t gid = getgid();
+
+    /* path might be a pre-existing block dev, in which case
+     * we need to skip the create step, and also avoid unlink
+     * in the failure case */
+    if (oflags & O_CREAT) {
+        need_unlink = true;
+
+        /* Don't force chown on network-shared FS
+         * as it is likely to fail. */
+        if (path_shared <= 0 || dynamicOwnership)
+            vfoflags |= VIR_FILE_OPEN_FORCE_OWNER;
+
+        if (stat(path, &sb) == 0) {
+            is_reg = !!S_ISREG(sb.st_mode);
+            /* If the path is regular file which exists
+             * already and dynamic_ownership is off, we don't
+             * want to change it's ownership, just open it as-is */
+            if (is_reg && !dynamicOwnership) {
+                uid = sb.st_uid;
+                gid = sb.st_gid;
+            }
+        }
+    }
+
+    /* First try creating the file as root */
+    if (!is_reg) {
+        if ((fd = open(path, oflags & ~O_CREAT)) < 0) {
+            fd = -errno;
+            goto error;
+        }
+    } else {
+        if ((fd = virFileOpenAs(path, oflags, S_IRUSR | S_IWUSR, uid, gid,
+                                vfoflags | VIR_FILE_OPEN_NOFORK)) < 0) {
+            /* If we failed as root, and the error was permission-denied
+               (EACCES or EPERM), assume it's on a network-connected share
+               where root access is restricted (eg, root-squashed NFS). If the
+               qemu user is non-root, just set a flag to
+               bypass security driver shenanigans, and retry the operation
+               after doing setuid to qemu user */
+            if ((fd != -EACCES && fd != -EPERM) || fallback_uid == getuid())
+                goto error;
+
+            /* On Linux we can also verify the FS-type of the directory. */
+            switch (path_shared) {
+                case 1:
+                    /* it was on a network share, so we'll continue
+                     * as outlined above
+                     */
+                    break;
+
+                case -1:
+                    virReportSystemError(-fd, oflags & O_CREAT
+                                         ? _("Failed to create file "
+                                             "'%s': couldn't determine fs type")
+                                         : _("Failed to open file "
+                                             "'%s': couldn't determine fs type"),
+                                         path);
+                    goto cleanup;
+
+                case 0:
+                default:
+                    /* local file - log the error returned by virFileOpenAs */
+                    goto error;
+            }
+
+            /* Retry creating the file as qemu user */
+
+            if ((fd = virFileOpenAs(path, oflags,
+                                    S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
+                                    fallback_uid, fallback_gid,
+                                    vfoflags | VIR_FILE_OPEN_FORK)) < 0) {
+                virReportSystemError(-fd, oflags & O_CREAT
+                                     ? _("Error from child process creating '%s'")
+                                     : _("Error from child process opening '%s'"),
+                                     path);
+                goto cleanup;
+            }
+
+            /* Since we had to setuid to create the file, and the fstype
+               is NFS, we assume it's a root-squashing NFS share, and that
+               the security driver stuff would have failed anyway */
+
+            bypass_security = true;
+        }
+    }
+cleanup:
+    if (needUnlink)
+        *needUnlink = need_unlink;
+    if (bypassSecurityDriver)
+        *bypassSecurityDriver = bypass_security;
+    return fd;
+
+error:
+    virReportSystemError(-fd, oflags & O_CREAT
+                         ? _("Failed to create file '%s'")
+                         : _("Failed to open file '%s'"),
+                         path);
+    goto cleanup;
+}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 21f116c..50987a4 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -368,4 +368,14 @@ extern virDomainDefParserConfig virQEMUDriverDomainDefParserConfig;
 int qemuDomainUpdateDeviceList(virQEMUDriverPtr driver,
                                virDomainObjPtr vm);
 
+int qemuOpenFile(virQEMUDriverPtr driver,
+                 virDomainObjPtr vm,
+                 const char *path, int oflags,
+                 bool *needUnlink, bool *bypassSecurityDriver);
+
+int qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
+               bool dynamicOwnership,
+               const char *path, int oflags,
+               bool *needUnlink, bool *bypassSecurityDriver);
+
 #endif /* __QEMU_DOMAIN_H__ */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ae1948f..70b587f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -157,16 +157,6 @@ static int qemuDomainGetMaxVcpus(virDomainPtr dom);
 static int qemuDomainManagedSaveLoad(virDomainObjPtr vm,
                                      void *opaque);
 
-static int qemuOpenFile(virQEMUDriverPtr driver,
-                        virDomainObjPtr vm,
-                        const char *path, int oflags,
-                        bool *needUnlink, bool *bypassSecurityDriver);
-
-static int qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
-                          bool dynamicOwnership,
-                          const char *path, int oflags,
-                          bool *needUnlink, bool *bypassSecurityDriver);
-
 
 virQEMUDriverPtr qemu_driver = NULL;
 
@@ -2743,151 +2733,6 @@ qemuCompressGetCommand(virQEMUSaveFormat compression)
     return ret;
 }
 
-/* Internal function to properly create or open existing files, with
- * ownership affected by qemu driver setup and domain DAC label.  */
-static int
-qemuOpenFile(virQEMUDriverPtr driver,
-             virDomainObjPtr vm,
-             const char *path, int oflags,
-             bool *needUnlink, bool *bypassSecurityDriver)
-{
-    int ret = -1;
-    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
-    uid_t user = cfg->user;
-    gid_t group = cfg->group;
-    bool dynamicOwnership = cfg->dynamicOwnership;
-    virSecurityLabelDefPtr seclabel;
-
-    virObjectUnref(cfg);
-
-    /* TODO: Take imagelabel into account? */
-    if (vm &&
-        (seclabel = virDomainDefGetSecurityLabelDef(vm->def, "dac")) != NULL &&
-        (virParseOwnershipIds(seclabel->label, &user, &group) < 0))
-        goto cleanup;
-
-    ret = qemuOpenFileAs(user, group, dynamicOwnership,
-                         path, oflags, needUnlink, bypassSecurityDriver);
-
- cleanup:
-    return ret;
-}
-
-static int
-qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
-               bool dynamicOwnership,
-               const char *path, int oflags,
-               bool *needUnlink, bool *bypassSecurityDriver)
-{
-    struct stat sb;
-    bool is_reg = true;
-    bool need_unlink = false;
-    bool bypass_security = false;
-    unsigned int vfoflags = 0;
-    int fd = -1;
-    int path_shared = virStorageFileIsSharedFS(path);
-    uid_t uid = getuid();
-    gid_t gid = getgid();
-
-    /* path might be a pre-existing block dev, in which case
-     * we need to skip the create step, and also avoid unlink
-     * in the failure case */
-    if (oflags & O_CREAT) {
-        need_unlink = true;
-
-        /* Don't force chown on network-shared FS
-         * as it is likely to fail. */
-        if (path_shared <= 0 || dynamicOwnership)
-            vfoflags |= VIR_FILE_OPEN_FORCE_OWNER;
-
-        if (stat(path, &sb) == 0) {
-            is_reg = !!S_ISREG(sb.st_mode);
-            /* If the path is regular file which exists
-             * already and dynamic_ownership is off, we don't
-             * want to change it's ownership, just open it as-is */
-            if (is_reg && !dynamicOwnership) {
-                uid = sb.st_uid;
-                gid = sb.st_gid;
-            }
-        }
-    }
-
-    /* First try creating the file as root */
-    if (!is_reg) {
-        if ((fd = open(path, oflags & ~O_CREAT)) < 0) {
-            fd = -errno;
-            goto error;
-        }
-    } else {
-        if ((fd = virFileOpenAs(path, oflags, S_IRUSR | S_IWUSR, uid, gid,
-                                vfoflags | VIR_FILE_OPEN_NOFORK)) < 0) {
-            /* If we failed as root, and the error was permission-denied
-               (EACCES or EPERM), assume it's on a network-connected share
-               where root access is restricted (eg, root-squashed NFS). If the
-               qemu user is non-root, just set a flag to
-               bypass security driver shenanigans, and retry the operation
-               after doing setuid to qemu user */
-            if ((fd != -EACCES && fd != -EPERM) || fallback_uid == getuid())
-                goto error;
-
-            /* On Linux we can also verify the FS-type of the directory. */
-            switch (path_shared) {
-                case 1:
-                    /* it was on a network share, so we'll continue
-                     * as outlined above
-                     */
-                    break;
-
-                case -1:
-                    virReportSystemError(-fd, oflags & O_CREAT
-                                         ? _("Failed to create file "
-                                             "'%s': couldn't determine fs type")
-                                         : _("Failed to open file "
-                                             "'%s': couldn't determine fs type"),
-                                         path);
-                    goto cleanup;
-
-                case 0:
-                default:
-                    /* local file - log the error returned by virFileOpenAs */
-                    goto error;
-            }
-
-            /* Retry creating the file as qemu user */
-
-            if ((fd = virFileOpenAs(path, oflags,
-                                    S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
-                                    fallback_uid, fallback_gid,
-                                    vfoflags | VIR_FILE_OPEN_FORK)) < 0) {
-                virReportSystemError(-fd, oflags & O_CREAT
-                                     ? _("Error from child process creating '%s'")
-                                     : _("Error from child process opening '%s'"),
-                                     path);
-                goto cleanup;
-            }
-
-            /* Since we had to setuid to create the file, and the fstype
-               is NFS, we assume it's a root-squashing NFS share, and that
-               the security driver stuff would have failed anyway */
-
-            bypass_security = true;
-        }
-    }
-cleanup:
-    if (needUnlink)
-        *needUnlink = need_unlink;
-    if (bypassSecurityDriver)
-        *bypassSecurityDriver = bypass_security;
-    return fd;
-
-error:
-    virReportSystemError(-fd, oflags & O_CREAT
-                         ? _("Failed to create file '%s'")
-                         : _("Failed to open file '%s'"),
-                         path);
-    goto cleanup;
-}
-
 /* Helper function to execute a migration to file with a correct save header
  * the caller needs to make sure that the processors are stopped and do all other
  * actions besides saving memory */
-- 
1.8.1.5

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]