New test eliminating libvirt from the equation: # Create one backing chain and one normal image $ qemu-img create -f qcow2 /var/lib/libvirt/images/testdisk-nosnap.qcow2 100M $ qemu-img create -f qcow2 /var/lib/libvirt/images/testdisk-snap-base.qcow2 100M $ qemu-img create -f qcow2 -b /var/lib/libvirt/images/testdisk-snap-base.qcow2 /var/lib/libvirt/images/testdisk-snap-snapshot.qcow2
# Use a profile similar to those created by libvirt - our guest doesn't do much, so he doesn't need much $ cat > /etc/apparmor.d/qemu-testprofile << EOF # Test profile for bug LP: #1912214 #include <tunables/global> profile qemu-testprofile flags=(attach_disconnected) { #include <abstractions/libvirt-qemu> #include <local/extrarules> } EOF $ touch /etc/apparmor.d/local/extrarules $ apparmor_parser -r /etc/apparmor.d/qemu-testprofile # Start qemu into the monitor under control of an apparmor profile $ aa-exec -p qemu-testprofile -- qemu-system-x86_64 -serial none -monitor stdio -m 64 -display none # Attach and detach the disk (qemu) drive_add 0 if=none,file=/var/lib/libvirt/images/testdisk-nosnap.qcow2,format=qcow2,id=disk1 # This can be detached (e.g. to iterate the test) via (qemu) drive_del disk1 As-is this fails (expected) since it gets the access to the file blocked: [58147.954482] audit: type=1400 audit(1611040852.319:86): apparmor="DENIED" operation="open" profile="qemu-testprofile" name="/var/lib/libvirt/images/testdisk-nosnap.qcow2" pid=23222 comm="qemu-system-x86" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 Now we can "manually play to be libvirt" and append the rule and reload the profile. In another console we can do: $ echo '"/var/lib/libvirt/images/testdisk-nosnap.qcow2" rwk,' > /etc/apparmor.d/local/extrarules $ apparmor_parser -r /etc/apparmor.d/qemu-testprofile Once that is done the `drive_add` command above will work. Now if we allow the snapshot file but not the base image in apparmor. And then attach the snapshot, we expect qemu to parse the snapshot, identify the backing file and fail to access that. $ echo '"/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2" rwk,' > /etc/apparmor.d/local/extrarules $ apparmor_parser -r /etc/apparmor.d/qemu-testprofile (qemu) drive_add 0 if=none,file=/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2,format=qcow2,id=disk1 Could not open backing file: Could not open '/var/lib/libvirt/images/testdisk-snap-base.qcow2': Permission denied [58777.551226] audit: type=1400 audit(1611041481.906:96): apparmor="DENIED" operation="open" profile="qemu-testprofile" name="/var/lib/libvirt/images/testdisk-snap-base.qcow2" pid=23222 comm="qemu-system-x86" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 Perfect - still as expected. Now if we add both rules we expect this to work. $ echo '"/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2" rwk,' > /etc/apparmor.d/local/extrarules $ echo '"/var/lib/libvirt/images/testdisk-snap-base.qcow2" rwk,' >> /etc/apparmor.d/local/extrarules $ apparmor_parser -r /etc/apparmor.d/qemu-testprofile (qemu) drive_add 0 if=none,file=/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2,format=qcow2,id=disk1 And indeed it does work fine. This also works fine in the containers ... good, but no help for debugging this. ** Description changed: Hi, to be clear I consider it quite likely that the error is on my side, but I'd appreciate guidance how to continue resolve. I have rubber ducked my setup with a coworker and talked to jjohansen if the profile would contain an obvious fault (it did not). So hereby I'm filing a bug hoping to get some help on this case. ## 1. What happened I was trying to add a feature to libvirt to support chained qcow files. That means instead of adding just one path libvirt has to process the chain of backing files and add all of those. That works already on guest start, but not on hot-add of devices. But while I see my code appending the rules I'd expect and issuing the apparmor_parser calls I'd expect it still fails. I'd love to get the profile at runtime to ensure things really are loaded as expected. But as discussed on IRC that won't work. So I tested and simplified and wonder for the test below why things fail. ## 2. how to reproduce I was taking my new code out of the equation - and to do so I was adding the path that is needed to the local overrides. But it still is blocked. So - right now - I'm assuming that my code worked in adding the lines, but the access is still blocked. Therefore let us try to fix this one first and only then I can debug into what might be failing on the new code. # Allow the access that libvirt does not yet allow $ echo '"/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2" rwk,' > /etc/apparmor.d/local/abstractions/libvirt-qemu # prep the disk chain to be hot-added qemu-img create -f qcow2 /var/lib/libvirt/images/testdisk-snap-base.qcow2 100M qemu-img create -f qcow2 -b /var/lib/libvirt/images/testdisk-snap-base.qcow2 /var/lib/libvirt/images/testdisk-snap-snapshot.qcow2 cat > hot-add-test.xml << EOF <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> - <source file='/var/lib/libvirt/images/testdisk-snap-base.qcow2' index='1'/> + <source file='/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2' index='1'/> <backingStore type='file' index='2'> <format type='qcow2'/> - <source file='/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2'/> + <source file='/var/lib/libvirt/images/testdisk-snap-base.qcow2'/> <backingStore/> </backingStore> <target dev='vdc' bus='virtio'/> </disk> EOF # prep a guest to attach to uvt-simplestreams-libvirt --verbose sync --source http://cloud-images.ubuntu.com/daily arch=amd64 label=daily release=focal uvt-kvm create --host-passthrough --password=ubuntu f-test2 release=focal arch=amd64 label=daily We have checked the "effective" profile that is loaded. JJohanssen didn't see an obvious flaw in it. But for reference here: root@h-libvirt-orig:~# apparmor_parser -p /etc/apparmor.d/libvirt/libvirt-e033b910-be06-4975-826f-b6fba368d928 | pastebinit https://paste.ubuntu.com/p/yxdmMT6638/ # attach the disk virsh attach-device f-test2 hot-add-test.xml Libvirt/Qemu works as usual - except (known and expected) does not add a rule for "/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2". But for that we have added out local override. Yet it is denied access. apparmor="DENIED" operation="open" namespace="root//lxd-h-libvirt-new_ <var-snap-lxd-common-lxd>" profile="libvirt-a2caaf89-0682-464d-92ba- 5295cb5f5128" name="/var/lib/libvirt/images/testdisk-snap- snapshot.qcow2" pid=2889044 comm="qemu-system-x86" requested_mask="r" denied_mask="r" fsuid=64055 ouid=64055 ## 3. The rule is generally working To be clear, on the same system if I just open up a new profile and allow this path to be accessed it works fine. See the working example below. It must be somewhat that is tied to the way KVM guests get their profile updates/assigned. root@h-libvirt-orig:~# cat /etc/apparmor.d/test #include <tunables/global> profile test flags=(attach_disconnected) { #include <abstractions/base> "/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2" rwk, "/usr/bin/md5sum" rmix, } root@h-libvirt-orig:~# apparmor_parser -r /etc/apparmor.d/test; aa-exec -v -p test -- md5sum /var/lib/libvirt/images/testdisk-snap-snapshot.qcow2 [6939] aa_change_onexec("test") [6939] exec md5sum /var/lib/libvirt/images/testdisk-snap-snapshot.qcow2 0f7fc62d270b69ee1b51453fa614d3e4 /var/lib/libvirt/images/testdisk-snap-snapshot.qcow2 root@h-libvirt-orig:~# apparmor_parser -r /etc/apparmor.d/test; aa-exec -v -p test -- md5sum /var/lib/libvirt/images/testdisk-snap-base.qcow2 [6944] aa_change_onexec("test") [6944] exec md5sum /var/lib/libvirt/images/testdisk-snap-base.qcow2 md5sum: /var/lib/libvirt/images/testdisk-snap-base.qcow2: Permission denied ## 4. tracking apparmor_parser I was using (for debug) a wrapper for apparmro_parser but all really looks as expected $ cat /usr/sbin/apparmor_parser.wrap #!/bin/bash echo "ARGS $@" | /usr/bin/systemd-cat echo "Content of ${2}:" | /usr/bin/systemd-cat /usr/bin/ls -laF "${2}" | /usr/bin/systemd-cat /usr/bin/cat "${2}" | /usr/bin/systemd-cat echo "Content of ${2}.files:" | /usr/bin/systemd-cat /usr/bin/ls -laF "${2}.files" | /usr/bin/systemd-cat /usr/bin/cat "${2}.files" | /usr/bin/systemd-cat /usr/sbin/apparmor_parser.orig "$@" | /usr/bin/systemd-cat It is called with "-r filepath" and the content of that filepath contain the aforementioned rules. So what else might be wrong - why else could the access be denied despite the rule that should allow it. -- You received this bug notification because you are a member of Ubuntu Touch seeded packages, which is subscribed to apparmor in Ubuntu. https://bugs.launchpad.net/bugs/1912214 Title: qemu can't access files that are added as rules on hot-add Status in apparmor package in Ubuntu: New Bug description: Hi, to be clear I consider it quite likely that the error is on my side, but I'd appreciate guidance how to continue resolve. I have rubber ducked my setup with a coworker and talked to jjohansen if the profile would contain an obvious fault (it did not). So hereby I'm filing a bug hoping to get some help on this case. ## 1. What happened I was trying to add a feature to libvirt to support chained qcow files. That means instead of adding just one path libvirt has to process the chain of backing files and add all of those. That works already on guest start, but not on hot-add of devices. But while I see my code appending the rules I'd expect and issuing the apparmor_parser calls I'd expect it still fails. I'd love to get the profile at runtime to ensure things really are loaded as expected. But as discussed on IRC that won't work. So I tested and simplified and wonder for the test below why things fail. ## 2. how to reproduce I was taking my new code out of the equation - and to do so I was adding the path that is needed to the local overrides. But it still is blocked. So - right now - I'm assuming that my code worked in adding the lines, but the access is still blocked. Therefore let us try to fix this one first and only then I can debug into what might be failing on the new code. # Allow the access that libvirt does not yet allow $ echo '"/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2" rwk,' > /etc/apparmor.d/local/abstractions/libvirt-qemu # prep the disk chain to be hot-added qemu-img create -f qcow2 /var/lib/libvirt/images/testdisk-snap-base.qcow2 100M qemu-img create -f qcow2 -b /var/lib/libvirt/images/testdisk-snap-base.qcow2 /var/lib/libvirt/images/testdisk-snap-snapshot.qcow2 cat > hot-add-test.xml << EOF <disk type='file' device='disk'> <driver name='qemu' type='qcow2'/> <source file='/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2' index='1'/> <backingStore type='file' index='2'> <format type='qcow2'/> <source file='/var/lib/libvirt/images/testdisk-snap-base.qcow2'/> <backingStore/> </backingStore> <target dev='vdc' bus='virtio'/> </disk> EOF # prep a guest to attach to uvt-simplestreams-libvirt --verbose sync --source http://cloud-images.ubuntu.com/daily arch=amd64 label=daily release=focal uvt-kvm create --host-passthrough --password=ubuntu f-test2 release=focal arch=amd64 label=daily We have checked the "effective" profile that is loaded. JJohanssen didn't see an obvious flaw in it. But for reference here: root@h-libvirt-orig:~# apparmor_parser -p /etc/apparmor.d/libvirt/libvirt-e033b910-be06-4975-826f-b6fba368d928 | pastebinit https://paste.ubuntu.com/p/yxdmMT6638/ # attach the disk virsh attach-device f-test2 hot-add-test.xml Libvirt/Qemu works as usual - except (known and expected) does not add a rule for "/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2". But for that we have added out local override. Yet it is denied access. apparmor="DENIED" operation="open" namespace="root//lxd-h-libvirt-new_ <var-snap-lxd-common-lxd>" profile="libvirt-a2caaf89-0682-464d-92ba- 5295cb5f5128" name="/var/lib/libvirt/images/testdisk-snap- snapshot.qcow2" pid=2889044 comm="qemu-system-x86" requested_mask="r" denied_mask="r" fsuid=64055 ouid=64055 ## 3. The rule is generally working To be clear, on the same system if I just open up a new profile and allow this path to be accessed it works fine. See the working example below. It must be somewhat that is tied to the way KVM guests get their profile updates/assigned. root@h-libvirt-orig:~# cat /etc/apparmor.d/test #include <tunables/global> profile test flags=(attach_disconnected) { #include <abstractions/base> "/var/lib/libvirt/images/testdisk-snap-snapshot.qcow2" rwk, "/usr/bin/md5sum" rmix, } root@h-libvirt-orig:~# apparmor_parser -r /etc/apparmor.d/test; aa-exec -v -p test -- md5sum /var/lib/libvirt/images/testdisk-snap-snapshot.qcow2 [6939] aa_change_onexec("test") [6939] exec md5sum /var/lib/libvirt/images/testdisk-snap-snapshot.qcow2 0f7fc62d270b69ee1b51453fa614d3e4 /var/lib/libvirt/images/testdisk-snap-snapshot.qcow2 root@h-libvirt-orig:~# apparmor_parser -r /etc/apparmor.d/test; aa-exec -v -p test -- md5sum /var/lib/libvirt/images/testdisk-snap-base.qcow2 [6944] aa_change_onexec("test") [6944] exec md5sum /var/lib/libvirt/images/testdisk-snap-base.qcow2 md5sum: /var/lib/libvirt/images/testdisk-snap-base.qcow2: Permission denied ## 4. tracking apparmor_parser I was using (for debug) a wrapper for apparmro_parser but all really looks as expected $ cat /usr/sbin/apparmor_parser.wrap #!/bin/bash echo "ARGS $@" | /usr/bin/systemd-cat echo "Content of ${2}:" | /usr/bin/systemd-cat /usr/bin/ls -laF "${2}" | /usr/bin/systemd-cat /usr/bin/cat "${2}" | /usr/bin/systemd-cat echo "Content of ${2}.files:" | /usr/bin/systemd-cat /usr/bin/ls -laF "${2}.files" | /usr/bin/systemd-cat /usr/bin/cat "${2}.files" | /usr/bin/systemd-cat /usr/sbin/apparmor_parser.orig "$@" | /usr/bin/systemd-cat It is called with "-r filepath" and the content of that filepath contain the aforementioned rules. So what else might be wrong - why else could the access be denied despite the rule that should allow it. To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1912214/+subscriptions -- Mailing list: https://launchpad.net/~touch-packages Post to : touch-packages@lists.launchpad.net Unsubscribe : https://launchpad.net/~touch-packages More help : https://help.launchpad.net/ListHelp