Thanks for the quick response!

On 02/23/2010 03:32 PM, Eric Blake wrote:
According to Laine Stump on 2/23/2010 12:54 PM:

Minor nits (I have not validated the overall patch in context; this is
just from a quick high-level review)

If qemudDomainRestore fails to open the domain save file, create a
pipe, then fork a process that does setuid(qemu_user) and opens the
file, then reads this file and stuffs it into the pipe. the parnet
s/. the parnet/.  The parent/

libvirtd process will use the other end of the pipe as its fd, then
reap the child process after its done reading.
s/its/it's/


Ah, yes. Those terrible typos that never seem worth the effort to fix after they're already checked in. Thanks for nipping it in the bud!


This makes domain restore work on a root-squash NFS share that is only
visible to the qemu user.
---
  src/qemu/qemu_driver.c |  158 +++++++++++++++++++++++++++++++++++++++++++++++-
  1 files changed, 155 insertions(+), 3 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ac6ef6a..f909a59 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4659,6 +4659,135 @@ cleanup:
      return ret;
  }

+/* qemudOpenAsUID() - pipe/fork/setuid/open a file, and return the
+   pipe fd to caller, so that it can read from the file. Also return
+   the pid of the child process, so the caller can wait for it to exit
+   after it's finished reading (to avoid a zombie, if nothing
+   else). */
+
+static int qemudOpenAsUID(const char *path, uid_t uid, pid_t *childpid) {
+    int pipefd[2] = {-1, -1};
Why the explicit initialization...


Mostly because I was following the example of util.c:__virExec(), which does the same thing. Following examples seems to get me into nearly as much trouble as ignoring them ;-)


+    int fd = -1;
+
+    *childpid = -1;
+
+    if (pipe(pipefd)<  0) {
...since I see nothing in POSIX that guarantees that pipe() will preserve
your initialized values across failure.  I think it's better to explicitly
set things to -1 on the failure path, rather than initializing that way.


Interesting point. If we can't rely on that, then __virExec() should be changed too. Of course this makes maintenance a bit more error prone, since we would have to make sure that *every* jump to the cleanup that happened prior to creating the pipe would set the pipe fds to -1 (or just leave the initialization in, and re-set them to -1 when pipe failed; that's probably the safest thing to do).


+        virReportSystemError(errno,
+                             _("failed to create pipe to read '%s'"),
+                             path);
+        goto parentcleanup;
+    }
+
+    int forkRet = virFork(childpid);
Unrelated to your patch, but we should probably start using pipe2 and
atomically marking pipes as CLOEXEC, so that use of libvirt in a
multithreaded environment does not have a race window where unrelated
threads can leak libvirt's fds across an exec (well, for new enough
kernels anyway; at least gnulib has a pipe2 fallback for older kernels).

...


I think I just heard someone volunteering! ;-)


+    /* child */
+
+    /* setuid to the qemu user, then open the file, read it,
+       and stuff it into the pipe for the parent process to
+       read */
+    int exit_code;
+    char *buf = NULL;
+    int bufsize = 1024 * 1024;
+    int bytesread;
+
+    /* child doesn't need the read side of the pipe */
+    close(pipefd[0]);
+
+    if (forkRet<  0) {
+        exit_code = errno;
+        virReportSystemError(errno,
+                             _("failed in child after forking to read '%s'"),
+                             path);
+        goto childcleanup;
+    }
+
+    if (setuid(uid) != 0) {
+        exit_code = errno;
+        virReportSystemError(errno,
+                             _("cannot setuid(%d) to read '%s'"),
+                             getuid(), path);
Is that the right uid to be reporting in the error message?


What's the proper emoticon for blushing in embarrassment? Bonehead typo ;-) Thanks for pointing it out.

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

Reply via email to