Re: Dilemma using ostree as regular user, losing permission bits



On Wed, 2017-06-07 at 11:06 -0400, Colin Walters wrote:
 
[...]

Hi again,

First I should prefix this message with stating that yes, creating real
packages and filesystem images as an unprivileged user is a "hard
problem", and most existing solutions out there now are extremely
complex. We are hoping to get as close as possible without too much
baggage.

That said, after some internal discussions; I have concluded that if we
already cannot get arbitrary file ownership with a simple approach, it
just does not make any sense to argue for getting the setuid/setgid
bits in with the same simple approach.

Of course the simple approach has some limitations, but these are quite
fine now that we have https://github.com/ostreedev/ostree/pull/908, and
everything is preserved within reason in user mode checkouts.

Testing with this shows that user mode checkouts really only ever strip
the undesired suid/sgid bits, but all other file permissions are still
preserved, this is great thanks :)

Related to the following, I have one question: is there currently any
way in the OSTree public API to read the real uids/gids and file
attributes of an entire tree, without actually checking out the tree ?

I suppose that using a similar recursive algorithm as in ostree-repo
checkout.c would let us call ostree_repo_load_file() on every file and
get all the information we want ?


The rest of this email is mostly unrelated, just some fun facts and
wild ideas...

[...]
On the other hand, if you want to create a bootable image as a regular
user, and you want that image to contain a /usr/bin/sudo that is
setuid, the typical way to do that is:
 
   1.) Create a sysroot somehow
 
   2.) Run mkfs.ext4 filesys.img -d ${sysroot}
 
Now it is conceivable to have userspace utilities to modify permissions
of files inside an image without mounting it, so we could set the suid
bit on 'sudo' inside filesys.img, but:
 
Right, generating filesystem images is basically outside of ostree's
domain.  Yep, AIUI OpenEmbedded uses genext2fs by default for this,
although I think they also experimented with libguestfs?
gnome-continuous uses libguestfs, although that bit is currently
broken for other reasons.

Actually OE uses mkfs -d ${sysroot} (here: [0]), and as I understand it
they have went to some length to ensure that the -d option is supported
for the filesystems they care about.

It's pretty interesting how this is done with pseudo[1], they are
basically spoofing the filesystem metadata with an LD_PRELOAD library
which will record the intended file attributes in an SQLite database,
giving the illusion of doing rooty things like creating device nodes
and assigning ownership to arbitrary UID/GIDs.

As I understand it, running the `mkfs -d` with the LD_PRELOAD in place
will simply cause mkfs to create a filesystem image with the intended
file attributes instead of the ones really on the rootfs.

In the future, I may be interested in creating something similar which
is backed directly by ostree so that I can create a similarly spoofed
environment, hopefully through bubblewrap. This probably just means
using the OstreeRepoCommitModifier API at commit time; and manually
populating the spoofed environment with the real metadata in ostree,
even if the actual checkout is usermode.

I'm not sure how I could get that to work without requiring that the
runtime environment inside bubblewrap actually have the said LD_PRELOAD
library available, for now it's just a wild but I think interesting
idea :)

For the Fedora/Project Atomic space in practice we end up using
Anaconda-in-a-VM (via a tool called imagefactory) - and remember
one can create VMs unprivileged.
 
And then the installer reads content from the host via a temporary webserver,
although with some work we could inject a virtio channel.
 
 
       The guestfish project shows promise, but is immensely complicated
       to build and then run inside a bubblewrap sandbox (requires qemu,
       and needs some custom supporting code to define an "appliance").
 
       This is especially tricky because we are striving for fully
       deterministic builds, which means any such tooling should be
       made available to the sandbox, usually by building it, there
       should never be a host tool dependency for deployments.
 
Yeah.  I haven't tried libguestfs-in-bwrap...I do use libguestfs inside
some privileged Docker containers though.
 
Pratically speaking though, it feels to me like requiring libguestfs on
the host shouldn't be too onerous for builders, although you *do* get
into reproducibility issues because of the way it will e.g. use the host
`mkfs.ext4` to make filesystems.
 
On the other hand, if you want things to be reproducible you'll need
to hardcode mkfs options anyways, right?

We currently use an mkfs inside the sandbox, so we either built mkfs,
or we are using a binary imported sysroot that is revisioned with
ostree (like this repo[2], created by this script[3]).

Any options we pass to mkfs, or any instructions executed in the build
sandbox, is project data. Since all project data and source input
revisions contribute to a cache key, we should (other reproducibility
concerns aside) be able to assert that a given cache key will always
produce bit-for-bit identical outputs.

 
   b.) It would be convoluted, the authors of build metadata would have
       to express this separately and the suid-ness of things would have
       to be carried beside the filesystem data itself separately.
 
The suid state *is* carried inside both "archive" and "bare-user" mode
ostree repos, by design.  It's only when you go to use a "bare" repository
(that could be a libguestfs mount or simply a filesystem in a VM)
that the suid bits are applied.

I may be wrong but I think the guest mount with libguestfs will still
have the same security concern of owning setuid binaries, however
guestfish will allow you to script the filesys modifications without
ever exposing a mount (I started down this road a couple months ago but
found that producing libguestfs from scratch, without "being a distro"
required too much effort in the short term at least, but I very much
like the model).

That said, assuming we have API to read what the attributes are as a
regular user, without needing to checkout; there are surely a hand full
of tricks we can play indeed.

Cheers,
    -Tristan


[0]: http://cgit.openembedded.org/openembedded-core/tree/scripts/lib/wic/partition.py#n246
[1]: http://git.yoctoproject.org/cgit/cgit.cgi/pseudo/
[2]: https://gnome7.codethink.co.uk/repo/
[3]: https://gitlab.com/BuildStream/debootstrap-ostree/



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