Bug#844459: autopkgtest: Please add autopkgtest-virt-uchroot

Johannes Schauer josch at debian.org
Wed Nov 16 13:13:09 UTC 2016


Hi,

Quoting Martin Pitt (2016-11-16 13:37:50)
> >  - the lxc package installed for lxc-usernsexec and lxc-unshare
> 
> I'd like to eliminate this even. util-linux' unshare has known about
> --user/-U for a while now, and thus replaces lxc-unshare and
> lxc-usernsexec:
> 
>   $ unshare -rmU  sh -c 'whoami; mount -t tmpfs foo /mnt; touch /mnt/foo; ls -l /mnt/foo'
>   root
>   -rw-r--r-- 1 root root 0 Nov 16 12:59 /mnt/foo
> 
> And you can use util-linux' nsenter to enter an existing namespace.
> 
> These lxc-* tools were written before util-linux learned about those,
> and I'm not sure if they are going to stick around forever as they are
> basically obsolete. It would also avoid the lxc dependency.
> 
> Would you be willing to try this?

I would also like to eliminate the lxc dependency.

Unfortunately, I was unable to achieve the same I'm currently doing with
lxc-usernsexec and lxc-unshare with unshare and nsenter.

This is why I initially wrote the whole thing in C because I didn't see
anything other than unshare and nsenter. Only when I discovered how it worked
with lxc-usernsexec and lxc-unshare did I do the whole thing in Python.

> >  - sbuild from git (a tiny fix to its autopkgtest backend is required)
> 
> OOI, is that required for running autopkgtest with uchroot itself, or
> "just" sbuild's integration with automatically running autopkgtest
> after a package build?

It's a change which makes the autopkgtest chroot backend integration of sbuild
more flexible. Until recently, the chroot name was implicitly appended to the
autopkgtest-virt-* call. This works well for most backends but it's
inconvenient for the ssh or qemu backend for example. This "fix" is also not
strictly required. It works without it. But the command line you'd need to use
is very awkward and unintuitive.

> I think it would be more comfortable to use mkdtemp() by default, and provide
> --unpack-dir as an option?

Yes, I'm considering that possibility as well. I'm not against such a change.

> > I don't think there is an existing backend which allows unprivileged
> > package building with so little overhead in terms of configuration.
> 
> lxd is quite nice and similarly easy (and a bit more powerful too),
> but unfortunately not available in Debian right now.

Despite reports claiming otherwise, I never got lxc to run without superuser
privileges. Is it easier with lxd?

> > It would be great if this backend could be added to autopkgtest itself.  If
> > you think that it is not a good fit for autopkgtest, then I can maintain it
> > in a separate package.
> 
> I think it would be a great fit, but in order to accept it I have some
> stricter requirements:
> 
>  * tests/autopkgtest should run at least the standard
>    DebTestsVirtContainer tests. Look at classes LxcRunner and LxdRunner, should
>    be a fairly simple extension.
> 
>    This will show the limits of what the backend can do, uncover
>    possible encoding/locale/whatever issues, and ensure that this will
>    keep working over time.
> 
>  * It should get a manpage, probably starting from
>    virt/autopkgtest-virt-chroot.1.

Awesome! Yes, testcases and a man page are of course required before this can
be integrated. I didn't supply them yet because I didn't know what you thought
about this idea yet.

> As building such a chroot tarball doesn't require new tools, that should be
> it (the manpage should just explain how to build them, with
> sbuild-createchroot or mk-sbuild).

Yup.

> I actually have wanted to deprecate the "chroot" backend for a long time, as
> it's inherently insecure and I never use it myself any more.  I wonder if
> uschroot could completely replace that? At first sight it should have the
> same isolation and robustness capabilities like lxc/lxd (at least wrt. the
> file system and mounting), except with a lot fewer dependencies.

I would keep the chroot backend if only as an example how to implement a simple
autopkgtest backend. Its existence helped me with learning how to begin
implementing this.

Also note, that uchroot is Linux specific.

> |     # We want to find out our user and group id inside the chroot but we want
> |     # to avoid having to parse /etc/subuid and /etc/subgid. We solve the
> |     # situation by creating a temporary file from inside the user namespace
> |     # and then checking its user and group ids from outside the user namespace.
> |     probe = VirtSubproc.check_exec(['lxc-usernsexec', 'mktemp',
> |                                     '/tmp/uchroot.XXXXXX'], outp=True)
> |     inner_uid = os.stat(probe)[stat.ST_UID]
> |     inner_gid = os.stat(probe)[stat.ST_GID]
> |     VirtSubproc.check_exec(['lxc-usernsexec', 'rm', probe])
> |     outer_uid = os.getuid()
> |     outer_gid = os.getgid()
> 
> This dance wouldn't even be necessary with unshare -rU -- you know
> that the outside uid/gid is just the normal user, and the inside one
> is root/root.
> 
> I'm not sure if there is something to be gained from the UID shift --
> that isolates the chroot test better, but also makes it much harder to
> clean up after a failed tests, as your normal user cannot touch/rm the
> temporary directories? But if you want this, there's newuidmap(1).

As I said in the beginning, patches that simplify this even further and/or
remove the lxc dependency are welcome. I just didn't get it to work without the
tools from the lxc package...

> |     # Unpack the tarball into the new directory.
> |     # Make sure not to extract any character special files because we cannot
> |     # mknod.
> |     VirtSubproc.check_exec(['lxc-usernsexec', '--', 'tar',
> |                             '--exclude=./dev/urandom',
> 
> Eek, do chroot tarballs regularly have /dev in them? Might be easier
> and safer to exclude /dev/ wholesale, as you provide a minimal /dev
> later on anyway?

sbuild-createchroot currently include character special devices, yes. But I
also don't think that uchroot should make many special requirements for the
tarballs that it is able to grok. So I thought it best to prepare for the worst
and filter out the paths that would otherwise require mknod.

> |     touch {rootdir}/dev/null
> |     chmod -rwx {rootdir}/dev/null
> |     mount -o bind /dev/null {rootdir}/dev/null
> |     touch {rootdir}/dev/zero
> |     chmod -rwx {rootdir}/dev/zero
> |     mount -o bind /dev/zero {rootdir}/dev/zero
> |     touch {rootdir}/dev/full
> |     chmod -rwx {rootdir}/dev/full
> |     mount -o bind /dev/full {rootdir}/dev/full
> |     touch {rootdir}/dev/random
> |     chmod -rwx {rootdir}/dev/random
> |     mount -o bind /dev/random {rootdir}/dev/random
> |     touch {rootdir}/dev/urandom
> |     chmod -rwx {rootdir}/dev/urandom
> |     mount -o bind /dev/urandom {rootdir}/dev/urandom
> |     touch {rootdir}/dev/tty
> |     chmod -rwx {rootdir}/dev/tty
> |     mount -o bind /dev/tty {rootdir}/dev/tty
> 
> Would you mind putting this into a loop?

I do not mind at all.

> |     # Test whether the auxverb is able to successfully run /bin/true
> |     status = VirtSubproc.execute_timeout(None, 5,
> |                                          VirtSubproc.auxverb + ['true'])[0]
> |     if status != 0:
> |         VirtSubproc.bomb('failed to connect to VM')
> 
> s/connect to VM/enter user chroot/?

Certainly. A copypaste error from another backend.

> | def hook_capabilities():
> |     return ['revert', 'root-on-testbed']
> 
> Please arrange for downtmp-host= to be set (like in virt-chroot). A
> shared directory should be fairly simple to do for this runner, and
> it's much more efficient than squeezing everything through tar and a
> pipe.

If I understand correctly, then downtmp-host is the directory as seen from the
host that is shared with the testbed?

That can be done. It will just not be used by sbuild because sbuild makes no
requirements for the backend to provide that functionality and thus "squeezes
everything through a pape" independent of the backend.

I have another autopkgtest-specific question. Currently, when using this code
with sbuild and I hit Ctrl+C to send a SIGINT, it appears as if autopkgtest
would immediately call hook_cleanup(). Can that be? How do I prevent that from
happening? It only happens with my uchroot backend and not any other, so I'm
probably doing something wrong. Trapping SIGINT in the shell script doesn't
seem to have any effect.

Thanks!

cheers, josch
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: signature
URL: <http://lists.alioth.debian.org/pipermail/autopkgtest-devel/attachments/20161116/a6ba20c2/attachment-0001.sig>


More information about the autopkgtest-devel mailing list