[Libguestfs] [PATCH] daemon: always provide stdin when running chroot commands (RHBZ#1280029)
Mateusz Guzik
mguzik at redhat.com
Tue Dec 1 16:05:51 UTC 2015
On Tue, Dec 01, 2015 at 04:16:57PM +0100, Pino Toscano wrote:
> On Tuesday 01 December 2015 15:59:56 Mateusz Guzik wrote:
> > I would argue that /dev has to be at least partially populated for anything
> > that gets executed in the chroot. At the very least special nodes like null,
> > zero and {u,}random are needed.
>
> We do not assume anything about guests, which could be Linux with a
> static /dev (rare these days), but also non-Linux guests, including
> Windows.
>
I have to confess to ignorance about this project, I only found it after
seeing a suspicious commit in dnf.
However, your description does not look right. The code seems to assume
it is possible to execve binaries in a chroot, which for practical
purposes means linux binaries. Further, do_command sets up
/etc/resolv.conf for the "guest".
My argument is that executing linux binaries in an environment without
properly populated /dev is a recipe for trouble and will one day come
back with weird failures or improperly constructed images.
> > CHROOT_IN/OUT around commandvf are definitely problematic. chroot should be
> > done in the child, which also removes the need to chroot out in the
> > parent.
>
> That could be another way to make the command* functions in the daemon
> safer, which wouldn't solve the issue of this email thread: even if you
> fork and then chroot, the guest has nothing in /dev, so you cannot
> open /dev/null at that point. This means you still need to carry on an
> open /dev/null from the appliance.
>
> > Assuming populated /dev is problematic/not feasible, at the very least
> > the open(/dev/null) should be performed in the child just prior to
> > chroot.
>
> See above.
>
The issue would be solved in a less hackish manner. If the process is
not chrooted, it can open /dev/null. So you fork, open /dev/null and
only then proceed to chroot.
But as noted earlier, unpopulated /dev seems to be the real bug here.
> > Current patch seems to work around shortcomings of the current API.
> >
> > Side content:
> > if (flag_copy_stdin) close (flag_copy_fd);
> > waitpid (pid, NULL, 0);
> > return -1;
>
> This is done only in the main "while (quit < 2)" loop, and only on
> error there, which will return with -1.
>
> > but some lines below there is:
> > if (flag_copy_stdin && close (flag_copy_fd) == -1) {
> > perror ("close");
> > return -1;
> > }
> >
> > /* Get the exit status of the command. */
> > if (waitpid (pid, &r, 0) != pid) {
> > perror ("waitpid");
> > return -1;
> > }
> >
> >
> > close() does not return an error unless extraterrestial circumstances occur,
> > and even then the fd is no longer in use by the process. As such, I would argue
> > checking for errors here is not necessary. Note that prior sample does not check.
>
> The code for flag_copy_stdin & flag_copy_fd is unrelated to the bit
> quoted above, see above for the explanation.
>
The point was that cleanup is duplicated and inconsistent.
--
Mateusz Guzik
More information about the Libguestfs
mailing list