Hi,

I encountered the same problem.

It looks like libvirt denies write access to guest base image by modifying the guest related apparmor profile once the guest runs on a snapshot referring to this base image.

Here's what i tried:

Guest runs on base image:

    root@host/storage/vm# virsh domblklist test
     Target   Source
    --------------------------------
     vda      /storage/vm/test.img

Generated aa profile not contains deny rule for base image:

    root@host/storage/vm# cat /etc/apparmor.d/libvirt/libvirt-<uuid>.files
    # DO NOT EDIT THIS FILE DIRECTLY. IT IS MANAGED BY LIBVIRT.
      "/var/log/libvirt/**/test.log" w,
      "/var/lib/libvirt/qemu/domain-test/monitor.sock" rw,
      "/var/lib/libvirt/qemu/domain-8-test/*" rw,
      "/var/run/libvirt/**/test.pid" rwk,
      "/run/libvirt/**/test.pid" rwk,
      "/var/run/libvirt/**/*.tunnelmigrate.dest.test" rw,
      "/run/libvirt/**/*.tunnelmigrate.dest.test" rw,
      "/storage/vm/test.img" rwk,  <---------------------------------------
      "/dev/vhost-net" rw,
      "/var/lib/libvirt/qemu/domain-8-test/{,**}" rwk,
      "/var/lib/libvirt/qemu/channel/target/domain-8-test/{,**}" rwk,
      "/var/lib/libvirt/qemu/domain-8-test/master-key.aes" rwk,
      "/dev/net/tun" rwk,

After generating the snapshot, there's still no deny rule (but we also not 
tried to merge back to base image yet):

    root@host/storage/vm# virsh snapshot-create-as --domain test --name 
backup_overlay --no-metadata --atomic --disk-only --diskspec 
vda,snapshot=external
    Domain snapshot backup_overlay created

    root@host/storage/vm# cat /etc/apparmor.d/libvirt/libvirt-<uuid>.files
    # DO NOT EDIT THIS FILE DIRECTLY. IT IS MANAGED BY LIBVIRT.
      "/var/log/libvirt/**/test.log" w,
      "/var/lib/libvirt/qemu/domain-test/monitor.sock" rw,
      "/var/lib/libvirt/qemu/domain-8-test/*" rw,
      "/var/run/libvirt/**/test.pid" rwk,
      "/run/libvirt/**/test.pid" rwk,
      "/var/run/libvirt/**/*.tunnelmigrate.dest.test" rw,
      "/run/libvirt/**/*.tunnelmigrate.dest.test" rw,
      "/storage/vm/test.img" rwk,  <---------------------------------------
      "/dev/pts/2" rw,
      "/dev/pts/2" rw,
      
"/var/lib/libvirt/qemu/channel/target/domain-8-test/org.qemu.guest_agent.0" rw,
      "/dev/vhost-net" rw,
      "/storage/vm/test.backup_overlay" rwk,

When shutting down and starting guest again, host specific aa profile gets 
regenerated.
Now the deny rule is present. Note that guest runs on snapshot:

    root@host/storage/vm# virsh domblklist test
     Target   Source
    -------------------------------------------
     vda      /storage/vm/test.backup_overlay

    root@host/storage/vm# virsh shutdown test
    Domain test is being shutdown

    root@host/storage/vm# virsh start test
    Domain test started

    root@host/storage/vm# cat /etc/apparmor.d/libvirt/libvirt-<uuid>.files
    # DO NOT EDIT THIS FILE DIRECTLY. IT IS MANAGED BY LIBVIRT.
      ...
      "/storage/vm/test.img" rk,   <-------------------------------------------
      # don't audit writes to readonly files
      deny "/storage/vm/test.img" w,  <----------------------------------------
      "/dev/vhost-net" rw,
      ...

And it seems like this rule prevents us from merging snapshot back to base 
image:

    root@host/storage/vm# virsh blockcommit test vda --active --pivoterror: 
internal error: unable to execute QEMU command 'block-commit': Could not reopen 
file: Permission denied

As soon as the guest aa profile gets disabled, blockcommit works as expected:

    root@host/storage/vm# aa-disable /etc/apparmor.d/libvirt/libvirt-<uuid>
    Disabling /etc/apparmor.d/libvirt/libvirt-<uuid>.

    root@host/storage/vm# virsh blockcommit test vda --active --pivot
    Successfully pivoted

After merge, stop and start guest, the deny rule is gone again:

    root@host/storage/vm# virsh shutdown test
    Domain test is being shutdown

    root@host/storage/vm# virsh start test
    Domain test started

    root@host/storage/vm# cat /etc/apparmor.d/libvirt/libvirt-<uuid>.files
    # DO NOT EDIT THIS FILE DIRECTLY. IT IS MANAGED BY LIBVIRT.
      ...
      "/storage/vm/test.img" rwk,
      "/dev/vhost-net" rw,
      ...

    root@host/storage/vm# virsh domblklist test
     Target   Source
    --------------------------------
     vda      /storage/vm/test.img

As stated above, the deny rule is not created immediately when creating the 
snapshot
if guest not gets stopped/started. But it gets added as soon as we try to merge 
back
to the base image:

    root@host/storage/vm# virsh snapshot-create-as --domain test --name 
backup_overlay --no-metadata --atomic --disk-only --diskspec 
vda,snapshot=external
    Domain snapshot backup_overlay created

    root@host/storage/vm# cat /etc/apparmor.d/libvirt/libvirt-<uuid>.files
    # DO NOT EDIT THIS FILE DIRECTLY. IT IS MANAGED BY LIBVIRT.
      ...
      "/storage/vm/test.img" rwk,
      ...

    root@host/storage/vm# virsh blockcommit test vda --active --pivoterror: 
internal error: unable to execute QEMU command 'block-commit': Could not reopen 
file: Permission denied

    root@host/storage/vm# cat /etc/apparmor.d/libvirt/libvirt-<uuid>.files
    # DO NOT EDIT THIS FILE DIRECTLY. IT IS MANAGED BY LIBVIRT.
      ...
      "/storage/vm/test.img" rk,
      # don't audit writes to readonly files
      deny "/storage/vm/test.img" w,  
<--------------------------------------------
      "/dev/pts/2" rw,
      "/dev/pts/2" rw,
      
"/var/lib/libvirt/qemu/channel/target/domain-10-test/org.qemu.guest_agent.0" rw,
      "/dev/vhost-net" rw,
      "/storage/vm/test.img" rwk,

I fear this is not solvable by just fixing some apparmor base profiles because 
libvirt creates and modifies aa profiles on the fly via virt-aa-helper.
Would be good to know if this procedure fails as well on other distros if 
apparmor is enabled, then it's probably a general problem with libvirt and 
apparmor.

Thanks,

Kind Regards,

Robert

Reply via email to