Interface mount/umount cifs share permission

HI,

we are currently doing a proof-of-concept for a customer on ubuntu-core / snap.

The software is a simple iot gateway which will read files from windows cifs
shares.

  • The software will run as simple snap daemon
  • The daemon should run permanently, over a UI it is possible to add and remove
    watched shares
  • As the cifs shares can come and go during runtime it is necessary to mount
    and umount them as needed
  • The cifs shares are mounted in a subdirectory of $SNAP_COMMON

I successfully built a snap with the software and I am shipping the mount and umount binaries. When I install it in devmode everything works. When I install it in strict mode the mount works, but the umount does fail.

When I enter the snaps daemons namespace with:

snap run --shell mydaemon

I can issue the mount command to see the current mounts:

$SNAP/bin/mount | grep cifs

//192.168.123.123/SomeShare on /var/snap/mydaemon/common/data/shares/SomeShare type cifs (rw,relatime,vers=1.0,sec=ntlmv2,cache=strict,username=Administrator,domain=WORKGROUP,uid=0,noforceuid,gid=0,noforcegid,addr=192.168.123.123,file_mode=0755,dir_mode=0755,nounix,serverino,mapposix,rsize=61440,wsize=65536,echo_interval=60,actimeo=1)

When I issue umount the following error pops up:

$SNAP/bin/umount /var/snap/mydaemon/common/data/shares/SomeShare

umount: /var/snap/mydaemon/common/data/shares/SomeShare: block devices are not permitted on filesystem

I only found this mailing list entry which might be related. And as it works in devmode I assume this has to do with missing apparmor or seccomp rules.
https://lists.linuxcontainers.org/pipermail/lxc-users/2015-February/008392.html

I am shipping mount and umount in the parts section of my snap:

parts:
...
  mount:
    plugin: nil
    stage-packages:
      - mount
      - cifs-utils
    organize:
      sbin/mount.cifs: bin/mount.cifs
    prime:
      - bin/mount
      - bin/umount
      - bin/mount.cifs
...
apps:
  mydaemon-service:
    command: >
       mydaemon -sharedir $SNAP_COMMON/data/shares
    daemon: simple
    restart-condition: always
    plugs:
      - network
      - network-control
      - network-bind
      - network-manager
      - network-setup-control
      - network-setup-observe
      - network-observe
      - mount-observe
      - fuse-support

My first idea was to create an interface which allows to execute cifs mount and umount inside the $SNAP_COMMON directory of a snap. But I don’t know if this is possible or if there is a better idea.

since you say mounting works, did you try using fusectl directly for the unmounting (you might need to ship it in your snap)

@ogra I searched for a binary named fusectl but the search didn’t turn up any results. Also I didn’t find any reference to fusectl on the net (despite the fuse helper filesystem type fusectl).

Can you drop me some link with more info?

Actually I don’t think I am using fuse at all, the mount type is “cifs” which I think points directly to the cifs kernel module.

oh, sorry, what i meant was fusermount from the fuse package

This also fails (I tried it by entering the namespace via snap run --shell). I only added fusermount as part. Do I somehow have to specify the correct plugs on the parts as well? For my test I just assumed the run --shell will inherit all connected slots.

root@XXXX:/root# $SNAP/bin/fusermount -u /var/snap/mydaemon/common/data/shares/SomeShare
/snap/mydaemon/x33/bin/fusermount: failed to unmount /var/snap/mydaemon/common/data/shares/SomeShare: Permission denied

Here the apparmor message:

May 30 15:40:58 XXXX kernel: [544995.729214] audit: type=1400 audit(1527694858.978:137239): apparmor="DENIED" operation="umount" profile="snap.mydaemon.mydaemon" name="/var/snap/mydaemon/common/data/shares/SomeShare/" pid=28978 comm="fusermount"
  mount:
    plugin: nil
    stage-packages:
      - mount
      - cifs-utils
      - fuse
    organize:
      sbin/mount.cifs: bin/mount.cifs
    prime:
      - bin/mount
      - bin/umount
      - bin/mount.cifs
      - bin/fusermount

I think there might by some unintentional permission sideeffect that lets me use the mount -t cifs in the first place. I don’t think this was intended. That probably might be the reason the umount command isn’t available.

Basically I would need something like the udisks2 interface but for cifs mounts/umounts and the target-directories should lie inside $SNAP_COMMON.

You are plugging the fuse-support interface which allows mounts of fstype=fuse.* into your SNAP_USER_DATA, SNAP_DATA, SNAP_USER_COMMON and SNAP_COMMON. The interface intentionally does not support unmounting (see https://github.com/snapcore/snapd/pull/1598#issuecomment-239952977) and does not support using setuid fusermount as non-root.

We also don’t have an interface to allow arbitrary cifs mounts into the snap’s private areas. This is perhaps possible and would be the path forward for your use case. I would be involved in this review. Since it sounds like you are up for trying to create the interface yourself, I suggest creating it and asking me to perform the review in github, then we can go from there. For me to be most helpful to you in the review process, please provide a test snap with minimal functionality to exercise the interface as well as instructions on the remote end’s configuration (eg, in a VM, install samba, do this, then that, now try to mount the volume with the snap). I am concerned about the accesses required for this interface and not sure what the name of it should be; perhaps cifs-mount-control as a first stab. If you are writing this interface, I suggest starting with network_control.go and network_control_test.go as inspiration.

as a quick interim hack/workaround it is possible to script a wrapper your snap runs as a daemon that the user can in turn trigger to call fusermount …

@jdstrand

It definitively lets me mount the kernel module cifs mounts (I am not 100% sure if it is the fuse-support interface, but one of the interfaces I plug lets me do that). If this is not intentional then maybe this should be investigated.

Regarding the interface name cifs-mount-control sounds reasonable for the start. Regarding worrying about the access. This is probably a requirement quite specific for our usecase. I was a bit surprised that I need a Pull-Request to snapd to add additional interfaces. Are there plans to have a more pluggable interface architecture (at least for Brand Stores)? I would guess there are more usecase specific access requests as soon as more and more people use ubuntu-core.

Also if you have a different better idea how to solve our problem (mount/unmount cifs shares) I am open for ideas.

For now we would just use devmode for the PoC and I would start developing the interface in a couple of weeks.

@ogra
Currently I am already running the fusermount -u -z .... calls from my daemon. The user interacts with this daemon via a webinterface. If this was what you suggested: it also gives me “permission denied” when I call the command. Or did you mean something else? I would be happy to use a workaround for now.

no, this was exactly what i meant (under the assumption that you use fuse, if fuse isnt involved at all it will most likely just be a no-op indeed :wink: )

The design of snapd is such that snapd provides all security policy. Adding and/or updating within snapd is not particularly difficult and we don’t mind specialized interfaces. When you have time to discuss this more, please provide me with the details I asked for and we can determine exactly how to proceed.

@jdstrand

I created some simple tools to reproduce my setup here, you find a detailed description in the Readme.md:

You can find a first try of the interface (I didn’t add tests yet) here. I deployed it following this article (http://www.zygoon.pl/2016/08/creating-your-first-snappy-interface.html , (I had to set the command prefix of the runbits script to empty due to some path checks in the cmd.go CMD_PREFIX="").

I see the interface and can connect it.

Mounting works, but unmounting does abort with the following error:

UMOUNT
ERROR: exit status 32
OUTPUT: Executing command: umount -l -t cifs /var/snap/smb-copier/common/shares

umount: /var/snap/smb-copier/common/shares: must be superuser to unmount

I am not sure why this happens, I thought adding the “sys_admin” capability would be enough?

It sounds like you are running your snap as non-root. If that is the case, ‘capability sys_admin’ doesn’t elevate your privileges to include sys_admin, it allows your snap to use a kernel resource that requires sys_admin if your process already has the capability. Put another way, if you run it as root, does it work?

I double checked and the service indeed ran as root (I think snap services even can only run as root). But I found the error. Seccomp/Apparmor still had some violations (which I found by sudo /snap/bin/snappy-debug.security scanlog). Which in turn caused umount to fail with the EPERM error. Which then was translated to the misleading error message.

Excerpt from this file:
(https://github.com/karelzak/util-linux/blob/master/libmount/src/context_umount.c)

case EPERM:
     snprintf(buf, bufsz, _("must be superuser to unmount"))

I added the missing permissions to the interface and now mount and umount works. But I didn’t think about any security implications of this interface yet. If you point me to some security problematic lines in the cifs-mount-control interface I can think about how to maybe mitigate these.

And another question: Should I try to include the necessary permissions from the mount-observe interface in my interface, or is it better if these two interfaces can only work together? Currently I need mount-observe to e.g. read @{PROC}/@{pid}/mounts r, , etc.

These were the changes which finally made it work:

I think you should submit this as a PR to snapcore and then we can discuss the feedback in the PR (ie, perhaps we’d want some things in mount-observe, but maybe not depending on how the PR discussion goes). It is actually an interesting PR since it is imaginable that it could be made generic where fstype is an interface attribute, but don’t change anything just yet.

Ok, I opened the PR

I already reviewed it.

Thx, I did the suggested cosmetic changes. Regarding “/run/mount/utab rw” and other security topics I will wait for the security review.

1 Like

The issue with /run/mount/utab is a bit more fundamental. I will open a dedicated thread to discuss this now. EDIT: Namespace awareness of /run/mount/utab (and libmount)