7

I'm using unshare to perform things like bind mounts local to a certain process without requiring root access, e.g.:

unshare -mr bash mount --bind a b

(Yes, this seems kinda dumb; in my actual use case; unshare is running a bash script that performs the bind mount. I didn't do that here so that it's a smaller example.)

However, if I try a loop mount, it fails:

ryan@DevPC-LX ~/stuff/util-linux master $ unshare -mr mount -o loop x.img a
mount: no permission to look at /dev/loop<N>

:/

I've tried using mknod to create a fake loop device (requires privileges not available to non-root), manually running losetup (still requires root privileges), and a bunch of other stuff that doesn't work.

Of course, I could just do chown myuser /dev/loop*, but that seems like it could become a major security issue.

In addition, guestmount is too slow for my use case, and fuseext2 has a warning about possible data loss in write mode (and it's also too slow).

Is there any way to do...this? At all?

  • "Of course I could just do chown..." nope. "Note however, that mounting block-based filesystems can be done only by a process that holds CAP_SYS_ADMIN in the initial user namespace." – sourcejedi May 12 '17 at 22:30
2
+25

In order to run unshare, you have to have root capabilities to create a separate mount space.

I tried this that seems to do what you want (I think):

Ishtar:> mkdir -p /tmp/unshare/home
Ishtar:> cd /tmp/unshare
Ishtar:/tmp/unshare> sudo unshare -m /bin/bash
Ishtar:/tmp/unshare# mount --rbind /home/packages /tmp/unshare/home
Ishtar:/tmp/unshare# tty
/dev/pts/4
Ishtar:/tmp/unshare# # ls home
BUILD@      RPMS@     build/           linux@    sources/           tmp/
BUILDROOT@  SOURCES@  buildroot/       logs/     specs/
OSbuild/    SPECS@    config-scripts/  perlsrc/  srpms/
OTHER/      SRPMS@    debug@           rpms/     sysvinit-288.spec

So the above process has '/home/packages mounted @ /tmp/unshare/home.

In another tty-window, with any user, I can try to see: what is in /tmp/unshare/home:

Ishtar:/> tty
/dev/pts/5
Ishtar:/> ll /tmp/unshare/home
total 0
Ishtar:/> cd tmp/unshare
Ishtar:/tmp/unshare> sudo
Ishtar:/tmp/unshare# ls home
Ishtar:/tmp/unshare# ll home
total 0
# create file in original "bound" dir from 1st usr above:
Ishtar:/tmp/unshare# touch /home/packages/PACKAGES.DIR 
Ishtar:/tmp/unshare# ll home  #home still empty
total 0
Ishtar:/> tty
/dev/pts/5
# now on other user again
Ishtar:/tmp/unshare# tty
/dev/pts/4
Ishtar:/tmp/unshare# ls home
BUILD@        RPMS@     buildroot/       perlsrc/  sysvinit-288.spec
BUILDROOT@    SOURCES@  config-scripts/  rpms/     tmp/
OSbuild/      SPECS@    debug@           sources/
OTHER/        SRPMS@    linux@           specs/
PACKAGES.DIR  build/    logs/            srpms/
#^^^ see PACKAGES.DIR appear (as created in original dir by another
# user

Once you have your "private dir mounted for user in "pts/4" you can change to the UID you want to run under for the program:

Ishtar:/tmp/unshare# su astara
Ishtar:/tmp/unshare> whoami
astara
Ishtar:/tmp/unshare> ls home/PACK*
home/PACKAGES.DIR

Note mount is still there for the unpriv'd user.

To be save, I'd put the 'su to other user' in a script file followed by a 'unmount /tmp/unshare/home', (since when su OTHERUSER exits, it will become root again, and unmount the file in the private space,). Then you can exit.

Does this come close to what you want? -- You have to use 'root' to setup your child env, but then run the child -- and only it has access to the mount created in the new mount namespace.

(update) BTW -- just noticed unshare has a --map-root-user that to specifically allow using either root or caps to setup options in the new namespace. The manpage says (about this switch):

....This makes it possible to  conveniently
gain  capabilities needed to manage various aspects of the newly
created namespaces (such as configuring interfaces in  the  net-
work  namespace  or mounting filesystems in the mount namespace)
even when run unprivileged.

This could allow you to manage your loop dev w/o being root (or so says the manpage). Likely CAP_SYS_ADMIN is the cap needed for doing this.

| improve this answer | |
  • Well, actually, no, you don't need to be root to use unshare...and bind mounts already work. It's loop mounts that are giving me trouble. – kirbyfan64sos May 15 '17 at 13:18
  • hmmm....for some reason I got a perm-denied (never used it before, so was probably something else). There is a switch to allow gaining caps in the new namespace to do specifically what you want to do...will update my answer to mention that @ end. – Astara May 17 '17 at 19:41
  • I'm already using --map-root-user (-r in the original question) and it still doesn't work because /dev is still off limits. – kirbyfan64sos May 19 '17 at 0:04
  • 1
    If you create a new user namespace, this makes it possible to create a new mount namespace (and other kinds). This is how the example in the question works. – linuxhackerman May 23 '17 at 8:30
  • 1
    As far as I understand --map-root-user implies -U. – linuxhackerman May 24 '17 at 11:20
2

As you have clearly understood, creating a loop mount consists of two steps:

  1. Setting up the loop device
  2. Mounting it

Of course, I could just do chown myuser /dev/loop*, but that seems like it could become a major security issue.

I believe this would permit the creation of the appropriate loop device (by giving access to /dev/loopcontrol). I don't know if there's also some sort of namespacing available that affects the view of loop devices. This would presumably allow doing this more securely.

Step 2 is still a no-go though: User namespaces do allow the creation of new mount namespaces in which it's possible for users to create new mounts, but it's fairly limited — CAP_SYS_ADMIN in the initial namespace is still required to mount block devices: as user_namespaces(7) says…

Note however, that mounting block-based filesystems can be done only by a process that holds CAP_SYS_ADMIN in the initial user namespace.

Loop devices are block devices backed by files, so that's still a no-go. This is unfortunate, I do think there should be a way for this to work securely. But I imagine there are a lot of intricacies to it (particularly with setuid) which are the reason it hasn't been implemented yet.

So as far as I understand, all you can really do is work around the issue. Maybe you could extract the files from the image (if worst comes to worst, i.e. there are no tools available for working with the particular format directly, you could mount it in a temporary VM to do this), then bind-mount the resulting directory.

| improve this answer | |
  • If all they wanted was to extract files from a mountable image, like an 'iso', they can use 7z. It treats "iso"s as a type of archive and can extract files or the whole image into a directory (w/files owned by the running user). It's also the case that running 7z doesn't take root-privs. But since the original Q didn't say they wanted to extract files from the image, but instead "mount it "privately" w/o needing root access", finding a workaround to extract files wouldn't answer the question either. – Astara May 23 '17 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.