FYI, I just verified that the restore failures I was seeing after applying this patch were actually happening *without* the patch as well, and are unrelated to domain save (it's a race condition in domain restore that needs to be dealt with separately), so this patch is okay to put in

I verified I've been testing with an unmodified form of this patch, *EXCEPT* that I hadn't done make syntax-check on it (since I didn't really think that it was working code at the time ;-)), and there is one occurence of white-space at the end of a line.

Should I resend with that change? Or do you want to just fix it up?

Also, notice that this patch saves the domain file with 0660 permission (umask will normally turn it into 0640) as we had thought that would be part of the way to allow restore from a root-squashed NFS server (just make sure that the reader had group read permissions). Now it seems we will be using the trick of running the restore code setuid instead, so the 0660 mode will no longer necessary. Should I revise this patch to create the file as 0600, or just do that as part of the upcoming domain restore patch?

(a couple more comments are inline)

On 02/22/2010 11:57 AM, Daniel Veillard wrote:
On Fri, Feb 19, 2010 at 02:30:08AM -0500, Laine Stump wrote:
Move *all* file operations related to creation and writing of libvirt
header to the domain save file into a hook function that is called by
virFileOperation. First try to call virFileOperation as root. If that
fails with EACCESS, and (in the case of Linux) statfs says that we're
trying to save the file on an NFS share, rerun virFileOperation,
telling it to fork a child process and setuid to the qemu user. This
is the only way we can successfully create a file on a root-squashed
NFS server.

This patch (along with setting dynamic_ownership=0 in qemu.conf)
makes qemudDomainSave work on root-squashed NFS.
[...]
+#ifdef __linux__
+        /* On Linux we can also verify the FS-type of the directory. */
+        struct statfs st;
+        char *dirpath, *p;
[...]
+
+        if ((p = strrchr(dirpath, '/')) == NULL) {
+            qemuReportError(VIR_ERR_INVALID_ARG,
+                            _("Invalid path '%s' for domain save file"),
+                            path);
+            VIR_FREE(dirpath);
+            goto endjob;
+        }
+
+        if (p == dirpath)
+            *(p+1) = '\0';
+        else
+            *p = '\0';
   I wasn't sure why that was needed but since the man page states

"path is the pathname of any file within the mounted file  system"

so okay we have to get back to the directory which is an existing file.


Heh. Yeah, I tried to do it with the filename first, and that didn't work, so we're stuck with the silly char* calisthenics.


+        if (statfs(dirpath,&st) == -1) {
+            virReportSystemError(rc,
+                                 _("Failed to create domain save file '%s'"
+                                   " statfs of '%s' failed (%d)"),
+                                 path, errno);
+            VIR_FREE(dirpath);
+            goto endjob;
+        }
+
+        VIR_FREE(dirpath);
+
+        if (st.f_type != NFS_SUPER_MAGIC) {
+            virReportSystemError(rc,
+                                 _("Failed to create domain save file '%s' (fstype 
0x%X"),
+                                 path, st.f_type);
+            goto endjob;
+        }
   Okay, we really need to error out if not on NFS (I can't think of
   another kind of filesystem which would exhibit the same behaviour)


There is a bugzilla report that talks about similar behavior on an smbfs share (they were having problems with storage volumes, but it seemed to smell the same) but I haven't tried it out. If it turns out to work similarly, we can add a case for SMBFS_SUPER_MAGIC.

My problem with this piece of code is that it's Linux-only. Other systems either don't have statfs, or it is implemented differently and doesn't have the f_type property. It would be nice if there was a method that worked the same on all platforms...


+#endif
+
+        /* Retry creating the file as driver->user */
+
+        if ((rc = virFileOperation(path, O_CREAT|O_TRUNC|O_WRONLY,
+                                   S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
+                                   driver->user, driver->group,
+                                   qemudDomainSaveFileOpHook,&hdata,
+                                   VIR_FILE_OP_AS_UID)) != 0) {
+            virReportSystemError(rc, _("Error from child process creating 
'%s'"),
+                                 path);
+            goto endjob;
+        }
+
+        /* 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 */
+
+        bypassSecurityDriver = 1;
      }
-    fd = -1;

-    if (driver->securityDriver&&
+
+    if ((!bypassSecurityDriver)&&
+        driver->securityDriver&&
          driver->securityDriver->domainSetSavedStateLabel&&
          driver->securityDriver->domainSetSavedStateLabel(vm, path) == -1)
          goto endjob;
@@ -4081,7 +4181,8 @@ static int qemudDomainSave(virDomainPtr dom,
      if (rc<  0)
          goto endjob;

-    if (driver->securityDriver&&
+    if ((!bypassSecurityDriver)&&
+        driver->securityDriver&&
          driver->securityDriver->domainRestoreSavedStateLabel&&
          driver->securityDriver->domainRestoreSavedStateLabel(vm, path) == -1)
          goto endjob;
@@ -4106,8 +4207,6 @@ endjob:
          vm = NULL;

  cleanup:
-    if (fd != -1)
-        close(fd);
      VIR_FREE(xml);
      if (ret != 0)
          unlink(path);
   Okay, ACK,

Daniel


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

Reply via email to