Sharing folder with VM through libvirt, 9p, permission denied

An Ubuntu Server 14.04 Host hosts an Ubuntu Server 14.04 guest via libvirt/qemu-kvm. The system runs fine, but - as guest - I have issues writing to a shared folder (<filesystem>) that drive me nuts. Both machines are relative vanilla installations.

I attached the given folder like this:

[host] $ virsh edit guest-vm-name
# ...
<filesystem type='mount' accessmode='mapped'>
  <source dir='/data'/>
  <target dir='/data'/>
  <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</filesystem>
# ...

From the guest I mount the filesystem as following:

[guest] $ sudo -u www-data mkdir /tmp/mnt
[guest] $ sudo mount -t 9p -otrans=virtio,rw,version=9p2000.L /data /tmp/mnt

I use the www-data user as that will be the efftive user later on, and group and user ids have to match if p9 is used, afaiu. That also means that on the host, /data (which is ext4 partition, LVM on RAID btw) looks like

[host] $ ls -lha /data
[host] $ drwxrwxr-x  4 www-data www-data 4.0K Nov 11 08:34 .
[host] $ drwxr-xr-x 24 root     root     4.0K Nov  7 16:58 ..
[host] $ drwxr-xr-x  2 www-data www-data 4.0K Nov 11 08:34 jail
# ...

In the guest, if I try to write to anything on the shared filesystem, I get permission errors (irrespective of the used user):

[guest] $ sudo -u www-data touch /tmp/mnt/jail/letmeout
touch: cannot touch ‘/tmp/mnt/jail/letmeout’: Permission denied

I can read files though

[guest] $ cat /tmp/mnt/jail/throughthewindow
Great Weather!

I tried various things, especially:

  • stopped apparmor service and called aa-complain (i hope that was effective)
  • set security to none in /etc/libvirt/qemu.conf
  • set user and group to root in /etc/libvirt/qemu.conf

/var/log/syslog and dmesg do not show anything suspicous.

Any pointers?! Thanks.


Solution 1:

I know, that this is an old thread, but I just came across a similar problem and found a solution that works at least in parts.

I also changed the user and group values in /etc/libvirt/qemu.conf to root, like you did.
But I also changed the dynamic_ownership setting, because the description sounded promising:

# Whether libvirt should dynamically change file ownership
# to match the configured user/group above. Defaults to 1.
# Set to 0 to disable file ownership changes.

My setup is:

  • Host: Debian 8 (Jessie)
  • Guest: Debian 8 (Jessie)
  • shared folder on host belongs to root
  • local user w/ id 1000 is member of the group libvirt (might be important)
  • mount point on the guest (/mnt/data) belongs to user 1000 ("alexander")

I can now finally write files in the mounted shared folder with both root(0) and alexander(1000). (before I did that, only root was allowed to write files here)

Setting dynamic_ownership to 0 is what has to be done in "mapped" accessmode.

Here's some more information about my setup:

/etc/libvirt/qemu.conf:

user = "root"
group = "root"
dynamic_ownership = 0

filesystem (virsh edit):

<!-- ... -->
    <filesystem type='mount' accessmode='mapped'>
      <source dir='/share/vm.localdomain/owncloud_data'/>
      <target dir='/data'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
    </filesystem>
<!-- ... -->

Host:

ls -al /share/vm.localdomain/owncloud_data/
total 8
drwxr-xr-x 2 root      root      4096 Sep  8 00:15 .
drwxr-xr-x 7 root      root      4096 Sep  8 00:10 ..

fstab on guest:

/data  /mnt/data/  9p  trans=virtio  0  0

Guest:

root@debian:~# cd /mnt/data
root@debian:/mnt/data# touch touched_by_root
root@debian:/mnt/data# su - alexander
alexander@debian:~$ cd /mnt/data
alexander@debian:/mnt/data$ touch touched_by_user
alexander@debian:/mnt/data$ ls -al
total 16
drwxr-xr-x 2 alexander alexander 4096 Sep  8 00:30 .
drwxr-xr-x 6 root      root      4096 Sep  7 18:13 ..
-rw-r--r-- 1 root      root         0 Sep  8 00:30 touched_by_root
-rw-r--r-- 1 alexander alexander    0 Sep  8 00:30 touched_by_user

back on host:

root@Host /share/vm.localdomain # ls -al /share/vm.localdomain/owncloud_data/
total 16
drwxr-xr-x 2 root      root         4096 Sep  8 00:30 .
drwxr-xr-x 7 root      root         4096 Sep  8 00:10 ..
-rw------- 1 root      libvirt-qemu    0 Sep  8 00:30 touched_by_root
-rw------- 1 root      libvirt-qemu    0 Sep  8 00:30 touched_by_user

conclusion

The strange thing is that on the guest these two files belong to different users (root vs. alexander), whereas on the host, both files belong to the same user (root:libvirt-qemu). :-O
I don't know exactly how this magic works, but apparently it does.

Hope this helps,
Alexander

Solution 2:

@Alexander gave a great answer. I didn't do everything that he did, but this is what I did do to get same-user rights working both ways across the 9p file system. (This way is intended to just get 9p to work, both ways, without security hassles. For more security, you will need a different method or settings)

HOST (order is unimportant)

  • I added my host user to the following group: <kvm> (I am also a member of <libvirtd>). This step may be unnecessary because:

  • in the file /etc/libvirt/qemu.conf you can change the user and group with which all of your VMs authenticate and execute.

(this is a powerful little change, and the repercussions need to be mapped out if you are trying to accomplish this on something like a production server)

user = "billy"    #### No, my name isn't billy, but it's cute. 
                  #### Alternatively you can declare your <uid>, like
                  ## user = "+1000" ####        << That's what I did.
                  #### (They tell you everything you need to know about
                  #### this stuff inside /etc/libvirt/qemu.conf)
group = "billy"
dynamic_ownership = 1

(What the above change does is tells the virtual machine host to convert all libvirt cross-VM-requests for any guest VMs you are running to the <user> that you set; including guest-VM <root>. *Note again that it is a system-wide setting with regard to libvirt and by extension qemu if libvirt is your sole qemu interface.)

  • Setup you host as found in this excellent official document https://www.linux-kvm.org/page/9p_virtio

(by the way, "Squash" references a 9p security model. It means "none" and is the most permissive setting for this context)

GUEST

  • Inside the guest VM, mount the 9p share using <root> privileges, also found at the bottom of the document https://www.linux-kvm.org/page/9p_virtio

(I also added one option as explained in the document below) My mount command is:

mount -t 9p -o trans=virtio,access=any,version=9p2000.L /hostshare /tmp/host_files

Nore that if you don't have permission to write to the share or have limited permission after you have set this up, the excellent suggestion by @randomocean 's answer should help. That is, have <root> create a folder under the share, and set chmod 777 to it.

-Even More Info: https://wiki.qemu.org/Documentation/9psetup