Esteemed maintainer, First and foremost, thank you very much for your hard work: passt is awesome and allows one to run more useful user-space VM-s. I have encountered 2 particular issues with the usage of passt with Debian, and wanted to bring them to your attention as I think you are probably the best person to deal with this. I do plan on sending a report to the Debian team afterwards. For reference, I tested these on Debian Testing Daily Image dated 28 January 2025, with updates, and the version of passt available with it is passt 0.0~git20250121.4f2c8e7-1 - Passt's default Apparmor config needs to allow writes to $XDG_RUNTIME_DIR (which is at /run/user/$UID). Currently it doesn't. Virt-manager, at least, tries to create the necessary sockets in the directory but apparmor prevents that from happening (and the error message Virt-Manager gives isn't helpful either: the first time around I falsely believed it was a segfault or similar issue). I managed to get passt working past this flaw (pun intended) by manually disabling apparmor for the binary. Passt works just fine in Fedora 41 as it doesn't use Apparmor but uses SELinux, and thus the configs don't affect it. - This second issue is perhaps a bit more Debian-specific, but I am going to mention it so that you might drop some hints for the Debian maintainers to debug this: Once Apparmor is disabled and a VM is configured to work with passt, DNS resolution doesn't work in the VM (IP Addresses work just fine) i.e. ping fsf.org doesn't work but `ping 209.51.188.174` does. The hypervisor details follow: $ virsh version # on Debian Testing a.k.a. 'Trixie' Compiled against library: libvirt 11.0.0 Using library: libvirt 11.0.0 Using API: QEMU 11.0.0Running hypervisor: QEMU 9.2.0 This, again, isn't an issue with Fedora 41, where everything just works. The hypervisor details for Fedora 41 are: $ virsh version # on Fedora 41 Compiled against library: libvirt 10.6.0 Using library: libvirt 10.6.0 Using API: QEMU 10.6.0 Running hypervisor: QEMU 9.1.2 Again, I will be making a report to the Debian maintainers, should they wish to chime in regarding Apparmor configs or the DNS resolution issue. Thank you once again for this awesome tool.
Hi, On Wed, 29 Jan 2025 09:14:12 +0000 Prafulla Giri <prafulla.giri(a)protonmail.com> wrote:Esteemed maintainer, First and foremost, thank you very much for your hard work: passt is awesome and allows one to run more useful user-space VM-s. I have encountered 2 particular issues with the usage of passt with Debian, and wanted to bring them to your attention as I think you are probably the best person to deal with this. I do plan on sending a report to the Debian team afterwards. For reference, I tested these on Debian Testing Daily Image dated 28 January 2025, with updates, and the version of passt available with it is passt 0.0~git20250121.4f2c8e7-1 - Passt's default Apparmor config needs to allow writes to $XDG_RUNTIME_DIR (which is at /run/user/$UID). Currently it doesn't. Virt-manager, at least, tries to create the necessary sockets in the directory but apparmor prevents that from happening (and the error message Virt-Manager gives isn't helpful either: the first time around I falsely believed it was a segfault or similar issue). I managed to get passt working past this flaw (pun intended) by manually disabling apparmor for the binary. Passt works just fine in Fedora 41 as it doesn't use Apparmor but uses SELinux, and thus the configs don't affect it.Thanks for reporting this! I'm the maintainer of the Debian package, by the way. Cc'ing Andrea, who is a maintainer of the libvirt package for Debian and surely more knowledgeable about this. Note that virt-manager uses passt through libvirt (I think that's only possibility) and this should actually be allowed in libvirt's AppArmor policy, in the sub-profile for passt: https://gitlab.com/libvirt/libvirt/-/blob/0264a7704ada52f686cafe8f6402d5b60… the rationale is that passt itself doesn't know which directory libvirt will pick for its socket and PID files, so libvirt's policy has to specify that. So I think you should file an issue for the libvirt package in this case, unless Andrea has some pointers.- This second issue is perhaps a bit more Debian-specific, but I am going to mention it so that you might drop some hints for the Debian maintainers to debug this: Once Apparmor is disabled and a VM is configured to work with passt, DNS resolution doesn't work in the VM (IP Addresses work just fine) i.e. ping fsf.org doesn't work but `ping 209.51.188.174` does. The hypervisor details follow: $ virsh version # on Debian Testing a.k.a. 'Trixie' Compiled against library: libvirt 11.0.0 Using library: libvirt 11.0.0 Using API: QEMU 11.0.0Running hypervisor: QEMU 9.2.0 This, again, isn't an issue with Fedora 41, where everything just works. The hypervisor details for Fedora 41 are: $ virsh version # on Fedora 41 Compiled against library: libvirt 10.6.0 Using library: libvirt 10.6.0 Using API: QEMU 10.6.0 Running hypervisor: QEMU 9.1.2Oops. Can you share the command line of passt as run by libvirt (say, 'ps aux|grep passt') for this case? passt has some basic DNS forwarding capabilities, which are configured depending on the host's resolver configuration.Again, I will be making a report to the Debian maintainers, should they wish to chime in regarding Apparmor configs or the DNS resolution issue.Please file a separate issue, in case. This one would be for passt.Thank you once again for this awesome tool.And thanks again for trying it out and reporting issues! -- Stefano
Hello, On Wednesday, January 29th, 2025 at 3:26 PM, Stefano Brivio <sbrivio(a)redhat.com> wrote:Hi, On Wed, 29 Jan 2025 09:14:12 +0000 Prafulla Giri prafulla.giri(a)protonmail.com wrote:I'm glad to have bumped into you. Because of the email domain, I thought you weren't the Debian maintainer. Silly me.Esteemed maintainer, First and foremost, thank you very much for your hard work: passt is awesome and allows one to run more useful user-space VM-s. I have encountered 2 particular issues with the usage of passt with Debian, and wanted to bring them to your attention as I think you are probably the best person to deal with this. I do plan on sending a report to the Debian team afterwards. For reference, I tested these on Debian Testing Daily Image dated 28 January 2025, with updates, and the version of passt available with it is passt 0.0~git20250121.4f2c8e7-1 - Passt's default Apparmor config needs to allow writes to $XDG_RUNTIME_DIR (which is at /run/user/$UID). Currently it doesn't. Virt-manager, at least, tries to create the necessary sockets in the directory but apparmor prevents that from happening (and the error message Virt-Manager gives isn't helpful either: the first time around I falsely believed it was a segfault or similar issue). I managed to get passt working past this flaw (pun intended) by manually disabling apparmor for the binary. Passt works just fine in Fedora 41 as it doesn't use Apparmor but uses SELinux, and thus the configs don't affect it.Thanks for reporting this! I'm the maintainer of the Debian package, by the way. Cc'ing Andrea, who is a maintainer of the libvirt package for Debian and surely more knowledgeable about this.Note that virt-manager uses passt through libvirt (I think that's only possibility) and this should actually be allowed in libvirt's AppArmor policy, in the sub-profile for passt: https://gitlab.com/libvirt/libvirt/-/blob/0264a7704ada52f686cafe8f6402d5b60… the rationale is that passt itself doesn't know which directory libvirt will pick for its socket and PID files, so libvirt's policy has to specify that. So I think you should file an issue for the libvirt package in this case, unless Andrea has some pointers.I will wait for the maintainers input on this one.Certainly! I'm sorry I didn't do this earlier. I'd checked on this: there is no difference between the command that runs passt on Fedora 41 or Debian Trixie. This is the command on Fedora 41: passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/4-dragora-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/4-dragora-net0-passt.pid and this is the command on Debian Trixie: passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/1-vm1-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/1-vm1-net0-passt.pid Just for the record, I'm also putting in the QEMU commands for Fedora 41 and Debian Trixie, as well: Fedora 41: /usr/bin/qemu-system-x86_64 -name guest=debian-trixie,debug-threads=on -S -object {"qom-type":"secret","id":"masterKey0","format":"raw","file":"/home/larryboy/.config/libvirt/qemu/lib/domain-5-debian-trixie/master-key.aes"} -machine pc-q35-9.1,usb=off,vmport=off,dump-guest-core=off,memory-backend=pc.ram,hpet=off,acpi=on -accel kvm -cpu host,migratable=on -m size=8388608k -object {"qom-type":"memory-backend-ram","id":"pc.ram","size":8589934592} -overcommit mem-lock=off -smp 4,sockets=4,cores=1,threads=1 -uuid d00ad47e-3cfe-4a1a-af01-b23417aad670 -no-user-config -nodefaults -chardev socket,id=charmonitor,fd=31,server=on,wait=off -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-shutdown -global ICH9-LPC.disable_s3=1 -global ICH9-LPC.disable_s4=1 -boot strict=on -device {"driver":"pcie-root-port","port":16,"chassis":1,"id":"pci.1","bus":"pcie.0","multifunction":true,"addr":"0x2"} -device {"driver":"pcie-root-port","port":17,"chassis":2,"id":"pci.2","bus":"pcie.0","addr":"0x2.0x1"} -device {"driver":"pcie-root-port","port":18,"chassis":3,"id":"pci.3","bus":"pcie.0","addr":"0x2.0x2"} -device {"driver":"pcie-root-port","port":19,"chassis":4,"id":"pci.4","bus":"pcie.0","addr":"0x2.0x3"} -device {"driver":"pcie-root-port","port":20,"chassis":5,"id":"pci.5","bus":"pcie.0","addr":"0x2.0x4"} -device {"driver":"pcie-root-port","port":21,"chassis":6,"id":"pci.6","bus":"pcie.0","addr":"0x2.0x5"} -device {"driver":"pcie-root-port","port":22,"chassis":7,"id":"pci.7","bus":"pcie.0","addr":"0x2.0x6"} -device {"driver":"pcie-root-port","port":23,"chassis":8,"id":"pci.8","bus":"pcie.0","addr":"0x2.0x7"} -device {"driver":"pcie-root-port","port":24,"chassis":9,"id":"pci.9","bus":"pcie.0","multifunction":true,"addr":"0x3"} -device {"driver":"pcie-root-port","port":25,"chassis":10,"id":"pci.10","bus":"pcie.0","addr":"0x3.0x1"} -device {"driver":"pcie-root-port","port":26,"chassis":11,"id":"pci.11","bus":"pcie.0","addr":"0x3.0x2"} -device {"driver":"pcie-root-port","port":27,"chassis":12,"id":"pci.12","bus":"pcie.0","addr":"0x3.0x3"} -device {"driver":"pcie-root-port","port":28,"chassis":13,"id":"pci.13","bus":"pcie.0","addr":"0x3.0x4"} -device {"driver":"pcie-root-port","port":29,"chassis":14,"id":"pci.14","bus":"pcie.0","addr":"0x3.0x5"} -device {"driver":"qemu-xhci","p2":15,"p3":15,"id":"usb","bus":"pci.2","addr":"0x0"} -device {"driver":"virtio-serial-pci","id":"virtio-serial0","bus":"pci.3","addr":"0x0"} -blockdev {"driver":"file","filename":"/home/larryboy/.local/share/libvirt/images/debian-13-nocloud-amd64-daily.qcow2","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"} -blockdev {"node-name":"libvirt-2-format","read-only":true,"discard":"unmap","driver":"qcow2","file":"libvirt-2-storage","backing":null} -blockdev {"driver":"file","filename":"/home/larryboy/.local/share/libvirt/images/debian-trixie.qcow2","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"} -blockdev {"node-name":"libvirt-1-format","read-only":false,"discard":"unmap","driver":"qcow2","file":"libvirt-1-storage","backing":"libvirt-2-format"} -device {"driver":"virtio-blk-pci","bus":"pci.4","addr":"0x0","drive":"libvirt-1-format","id":"virtio-disk0","bootindex":1} -netdev {"type":"stream","addr":{"type":"unix","path":"/run/user/1000/libvirt/qemu/run/passt/5-debian-trixie-net0.socket"},"server":false,"reconnect":5,"id":"hostnet0"} -device {"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"52:54:00:8f:e7:c3","bus":"pci.1","addr":"0x0"} -chardev pty,id=charserial0 -device {"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0} -chardev socket,id=charchannel0,fd=30,server=on,wait=off -device {"driver":"virtserialport","bus":"virtio-serial0.0","nr":1,"chardev":"charchannel0","id":"channel0","name":"org.qemu.guest_agent.0"} -chardev spicevmc,id=charchannel1,name=vdagent -device {"driver":"virtserialport","bus":"virtio-serial0.0","nr":2,"chardev":"charchannel1","id":"channel1","name":"com.redhat.spice.0"} -device {"driver":"usb-tablet","id":"input0","bus":"usb.0","port":"1"} -audiodev {"id":"audio1","driver":"spice"} -spice port=5901,addr=127.0.0.1,disable-ticketing=on,image-compression=off,seamless-migration=on -display egl-headless,rendernode=/dev/dri/renderD128 -device {"driver":"virtio-vga-gl","id":"video0","max_outputs":1,"bus":"pcie.0","addr":"0x1"} -device {"driver":"ich9-intel-hda","id":"sound0","bus":"pcie.0","addr":"0x1b"} -device {"driver":"hda-duplex","id":"sound0-codec0","bus":"sound0.0","cad":0,"audiodev":"audio1"} -global ICH9-LPC.noreboot=off -watchdog-action reset -chardev spicevmc,id=charredir0,name=usbredir -device {"driver":"usb-redir","chardev":"charredir0","id":"redir0","bus":"usb.0","port":"2"} -chardev spicevmc,id=charredir1,name=usbredir -device {"driver":"usb-redir","chardev":"charredir1","id":"redir1","bus":"usb.0","port":"3"} -device {"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.5","addr":"0x0"} -object {"qom-type":"rng-random","id":"objrng0","filename":"/dev/urandom"} -device {"driver":"virtio-rng-pci","rng":"objrng0","id":"rng0","bus":"pci.6","addr":"0x0"} -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny -msg timestamp=on Debian Trixie: /usr/bin/qemu-system-x86_64 -name guest=vm1,debug-threads=on -S -object {"qom-type":"secret","id":"masterKey0","format":"raw","file":"/home/larryboy/.config/libvirt/qemu/lib/domain-1-vm1/master-key.aes"} -machine pc-i440fx-9.2,usb=off,vmport=off,dump-guest-core=off,memory-backend=pc.ram,hpet=off,acpi=on -accel kvm -cpu Denverton,vmx=on,fma=on,pdcm=on,pcid=on,avx=on,f16c=on,hypervisor=on,ss=on,tsc-adjust=on,bmi1=on,avx2=on,bmi2=on,invpcid=on,avx512f=on,avx512dq=on,adx=on,avx512ifma=on,clwb=on,avx512cd=on,avx512bw=on,avx512vl=on,avx512vbmi=on,umip=on,pku=on,avx512vbmi2=on,gfni=on,vaes=on,vpclmulqdq=on,avx512vnni=on,avx512bitalg=on,avx512-vpopcntdq=on,rdpid=on,movdiri=on,movdir64b=on,fsrm=on,avx512-vp2intersect=on,md-clear=on,stibp=on,flush-l1d=on,xsaves=on,abm=on,ibpb=on,ibrs=on,amd-stibp=on,amd-ssbd=on,ibrs-all=on,mds-no=on,pschange-mc-no=on,fbsdp-no=on,gds-no=on,rfds-no=on,vmx-activity-wait-sipi=on,vmx-xsaves=on,vmx-tsc-scaling=on,vmx-invvpid=on,mpx=off -m size=1048576k -object {"qom-type":"memory-backend-ram","id":"pc.ram","size":1073741824} -overcommit mem-lock=off -smp 1,sockets=1,cores=1,threads=1 -uuid aa332a62-1b7f-4a3c-b2c5-908e5e339b72 -no-user-config -nodefaults -chardev socket,id=charmonitor,fd=27,server=on,wait=off -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-shutdown -global PIIX4_PM.disable_s3=1 -global PIIX4_PM.disable_s4=1 -boot menu=on,strict=on -device {"driver":"ich9-usb-ehci1","id":"usb","bus":"pci.0","addr":"0x5.0x7"} -device {"driver":"ich9-usb-uhci1","masterbus":"usb.0","firstport":0,"bus":"pci.0","multifunction":true,"addr":"0x5"} -device {"driver":"ich9-usb-uhci2","masterbus":"usb.0","firstport":2,"bus":"pci.0","addr":"0x5.0x1"} -device {"driver":"ich9-usb-uhci3","masterbus":"usb.0","firstport":4,"bus":"pci.0","addr":"0x5.0x2"} -device {"driver":"virtio-serial-pci","id":"virtio-serial0","bus":"pci.0","addr":"0x6"} -blockdev {"driver":"file","filename":"/home/larryboy/.local/share/libvirt/images/vm1.qcow2","node-name":"libvirt-2-storage","auto-read-only":true,"discard":"unmap"} -blockdev {"node-name":"libvirt-2-format","read-only":false,"driver":"qcow2","file":"libvirt-2-storage","backing":null} -device {"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-2-format","id":"ide0-0-0","bootindex":2} -blockdev {"driver":"file","filename":"/home/larryboy/.local/share/libvirt/images/dsl-2024.rc7.iso","node-name":"libvirt-1-storage","read-only":true} -device {"driver":"ide-cd","bus":"ide.0","unit":1,"drive":"libvirt-1-storage","id":"ide0-0-1","bootindex":1} -netdev {"type":"stream","addr":{"type":"unix","path":"/run/user/1000/libvirt/qemu/run/passt/1-vm1-net0.socket"},"server":false,"reconnect-ms":5000,"id":"hostnet0"} -device {"driver":"rtl8139","netdev":"hostnet0","id":"net0","mac":"52:54:00:a0:e1:7c","bus":"pci.0","addr":"0x3"} -chardev pty,id=charserial0 -device {"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0} -chardev spicevmc,id=charchannel0,name=vdagent -device {"driver":"virtserialport","bus":"virtio-serial0.0","nr":1,"chardev":"charchannel0","id":"channel0","name":"com.redhat.spice.0"} -device {"driver":"usb-tablet","id":"input0","bus":"usb.0","port":"1"} -audiodev {"id":"audio1","driver":"spice"} -spice port=5900,addr=127.0.0.1,disable-ticketing=on,seamless-migration=on -display egl-headless,rendernode=/dev/dri/renderD128 -device {"driver":"virtio-vga-gl","id":"video0","max_outputs":1,"bus":"pci.0","addr":"0x2"} -device {"driver":"AC97","id":"sound0","audiodev":"audio1","bus":"pci.0","addr":"0x4"} -chardev spicevmc,id=charredir0,name=usbredir -device {"driver":"usb-redir","chardev":"charredir0","id":"redir0","bus":"usb.0","port":"2"} -chardev spicevmc,id=charredir1,name=usbredir -device {"driver":"usb-redir","chardev":"charredir1","id":"redir1","bus":"usb.0","port":"3"} -device {"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x7"} -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny -msg timestamp=on- This second issue is perhaps a bit more Debian-specific, but I am going to mention it so that you might drop some hints for the Debian maintainers to debug this: Once Apparmor is disabled and a VM is configured to work with passt, DNS resolution doesn't work in the VM (IP Addresses work just fine) i.e. ping fsf.org doesn't work but `ping 209.51.188.174` does. The hypervisor details follow: $ virsh version # on Debian Testing a.k.a. 'Trixie' Compiled against library: libvirt 11.0.0 Using library: libvirt 11.0.0 Using API: QEMU 11.0.0Running hypervisor: QEMU 9.2.0 This, again, isn't an issue with Fedora 41, where everything just works. The hypervisor details for Fedora 41 are: $ virsh version # on Fedora 41 Compiled against library: libvirt 10.6.0 Using library: libvirt 10.6.0 Using API: QEMU 10.6.0 Running hypervisor: QEMU 9.1.2Oops. Can you share the command line of passt as run by libvirt (say, 'ps aux|grep passt') for this case? passt has some basic DNS forwarding capabilities, which are configured depending on the host's resolver configuration.I think I no longer have to, since I have the Debian maintainer right here. (:Again, I will be making a report to the Debian maintainers, should they wish to chime in regarding Apparmor configs or the DNS resolution issue.Please file a separate issue, in case. This one would be for passt.I'm happy to be of some assistance (:Thank you once again for this awesome tool.And thanks again for trying it out and reporting issues!-- Stefano
On Wed, 29 Jan 2025 18:10:36 +0000 Prafulla Giri <prafulla.giri(a)protonmail.com> wrote:Hello, On Wednesday, January 29th, 2025 at 3:26 PM, Stefano Brivio <sbrivio(a)redhat.com> wrote::)Hi, On Wed, 29 Jan 2025 09:14:12 +0000 Prafulla Giri prafulla.giri(a)protonmail.com wrote:I'm glad to have bumped into you. Because of the email domain, I thought you weren't the Debian maintainer. Silly me.Esteemed maintainer, First and foremost, thank you very much for your hard work: passt is awesome and allows one to run more useful user-space VM-s. I have encountered 2 particular issues with the usage of passt with Debian, and wanted to bring them to your attention as I think you are probably the best person to deal with this. I do plan on sending a report to the Debian team afterwards. For reference, I tested these on Debian Testing Daily Image dated 28 January 2025, with updates, and the version of passt available with it is passt 0.0~git20250121.4f2c8e7-1 - Passt's default Apparmor config needs to allow writes to $XDG_RUNTIME_DIR (which is at /run/user/$UID). Currently it doesn't. Virt-manager, at least, tries to create the necessary sockets in the directory but apparmor prevents that from happening (and the error message Virt-Manager gives isn't helpful either: the first time around I falsely believed it was a segfault or similar issue). I managed to get passt working past this flaw (pun intended) by manually disabling apparmor for the binary. Passt works just fine in Fedora 41 as it doesn't use Apparmor but uses SELinux, and thus the configs don't affect it.Thanks for reporting this! I'm the maintainer of the Debian package, by the way. Cc'ing Andrea, who is a maintainer of the libvirt package for Debian and surely more knowledgeable about this.One thing that might help meanwhile is if you have a look at /var/log/audit/audit.log after the failure occurs. Look for 'passt' there. There should be a message logging a denied access to some file: what does it say?Note that virt-manager uses passt through libvirt (I think that's only possibility) and this should actually be allowed in libvirt's AppArmor policy, in the sub-profile for passt: https://gitlab.com/libvirt/libvirt/-/blob/0264a7704ada52f686cafe8f6402d5b60… the rationale is that passt itself doesn't know which directory libvirt will pick for its socket and PID files, so libvirt's policy has to specify that. So I think you should file an issue for the libvirt package in this case, unless Andrea has some pointers.I will wait for the maintainers input on this one.Okay, nothing unexpected so far. Could you also please compare the output of 'passt -f -d' between the two cases? Just terminate it with ^C once you have the output. How are resolvers configured on the two hosts? What does /etc/resolv.conf say? If nothing is visible from there, next check: 'virsh edit vm1' on Debian and add a log file in the XML, that is, replace this line: <backend type='passt'/> with: <backend type='passt' logFile='/tmp/passt.log'/> and then share the log. -- StefanoCertainly! I'm sorry I didn't do this earlier. I'd checked on this: there is no difference between the command that runs passt on Fedora 41 or Debian Trixie. This is the command on Fedora 41: passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/4-dragora-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/4-dragora-net0-passt.pid and this is the command on Debian Trixie: passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/1-vm1-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/1-vm1-net0-passt.pid- This second issue is perhaps a bit more Debian-specific, but I am going to mention it so that you might drop some hints for the Debian maintainers to debug this: Once Apparmor is disabled and a VM is configured to work with passt, DNS resolution doesn't work in the VM (IP Addresses work just fine) i.e. ping fsf.org doesn't work but `ping 209.51.188.174` does. The hypervisor details follow: $ virsh version # on Debian Testing a.k.a. 'Trixie' Compiled against library: libvirt 11.0.0 Using library: libvirt 11.0.0 Using API: QEMU 11.0.0Running hypervisor: QEMU 9.2.0 This, again, isn't an issue with Fedora 41, where everything just works. The hypervisor details for Fedora 41 are: $ virsh version # on Fedora 41 Compiled against library: libvirt 10.6.0 Using library: libvirt 10.6.0 Using API: QEMU 10.6.0 Running hypervisor: QEMU 9.1.2Oops. Can you share the command line of passt as run by libvirt (say, 'ps aux|grep passt') for this case? passt has some basic DNS forwarding capabilities, which are configured depending on the host's resolver configuration.
On Thursday, January 30th, 2025 at 12:33 AM, Stefano Brivio <sbrivio(a)redhat.com> wrote:On Wed, 29 Jan 2025 18:10:36 +0000 Prafulla Giri prafulla.giri(a)protonmail.com wrote:I didn't have auditd installed on Debian and installed it, and running everything with the default auditd config (with my Apparmor disabled for passt, as mentioned previously) does not result in anything. Do I have to configure auditd manually? Any pointers on that, please? On Fedora 41, which seems to have auditd preconfigured, there aren't any significant reports about passt.Hello, On Wednesday, January 29th, 2025 at 3:26 PM, Stefano Brivio sbrivio(a)redhat.com wrote::)Hi, On Wed, 29 Jan 2025 09:14:12 +0000 Prafulla Giri prafulla.giri(a)protonmail.com wrote:I'm glad to have bumped into you. Because of the email domain, I thought you weren't the Debian maintainer. Silly me.Esteemed maintainer, First and foremost, thank you very much for your hard work: passt is awesome and allows one to run more useful user-space VM-s. I have encountered 2 particular issues with the usage of passt with Debian, and wanted to bring them to your attention as I think you are probably the best person to deal with this. I do plan on sending a report to the Debian team afterwards. For reference, I tested these on Debian Testing Daily Image dated 28 January 2025, with updates, and the version of passt available with it is passt 0.0~git20250121.4f2c8e7-1 - Passt's default Apparmor config needs to allow writes to $XDG_RUNTIME_DIR (which is at /run/user/$UID). Currently it doesn't. Virt-manager, at least, tries to create the necessary sockets in the directory but apparmor prevents that from happening (and the error message Virt-Manager gives isn't helpful either: the first time around I falsely believed it was a segfault or similar issue). I managed to get passt working past this flaw (pun intended) by manually disabling apparmor for the binary. Passt works just fine in Fedora 41 as it doesn't use Apparmor but uses SELinux, and thus the configs don't affect it.Thanks for reporting this! I'm the maintainer of the Debian package, by the way. Cc'ing Andrea, who is a maintainer of the libvirt package for Debian and surely more knowledgeable about this.One thing that might help meanwhile is if you have a look at /var/log/audit/audit.log after the failure occurs. Look for 'passt' there. There should be a message logging a denied access to some file: what does it say?Note that virt-manager uses passt through libvirt (I think that's only possibility) and this should actually be allowed in libvirt's AppArmor policy, in the sub-profile for passt: https://gitlab.com/libvirt/libvirt/-/blob/0264a7704ada52f686cafe8f6402d5b60… the rationale is that passt itself doesn't know which directory libvirt will pick for its socket and PID files, so libvirt's policy has to specify that. So I think you should file an issue for the libvirt package in this case, unless Andrea has some pointers.I will wait for the maintainers input on this one.Here are the outputs: $ passt -f -d # on Debian Testing/Trixie 0.0016: No interfaces with usable IPv6 routes 0.0017: Failed to detect external interface for IPv6 0.0028: UNIX domain socket bound at /tmp/passt_1.socket 0.0029: Template interface: enp1s0 (IPv4) 0.0029: MAC: 0.0029: host: 9a:55:9a:55:9a:55 0.0029: NAT to host 127.0.0.1: 192.168.100.1 0.0029: DHCP: 0.0029: assign: 192.168.100.157 0.0029: mask: 255.255.255.0 0.0029: router: 192.168.100.1 0.0029: DNS: 0.0029: 192.168.100.1 0.0029: DNS search list: 0.0029: . 0.0056: You can now start qemu (>= 7.2, with commit 13c6be96618c): 0.0056: kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/tmp/passt_1.socket 0.0057: or qrap, for earlier qemu versions: 0.0057: ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio 0.0067: SO_PEEK_OFF supported 0.0067: TCP_INFO tcpi_snd_wnd field supported 0.0067: TCP_INFO tcpi_bytes_acked field supported 0.0067: TCP_INFO tcpi_min_rtt field supported $ passt -f -d 0.0022: UNIX domain socket bound at /tmp/passt_1.socket 0.0022: Template interface: wlp0s20f3 (IPv4) 0.0022: MAC: 0.0022: host: 9a:55:9a:55:9a:55 0.0022: NAT to host 127.0.0.1: 192.168.100.1 0.0023: DHCP: 0.0023: assign: 192.168.100.157 0.0023: mask: 255.255.255.0 0.0023: router: 192.168.100.1 0.0023: DNS: 0.0023: 192.168.100.1 0.0023: DNS search list: 0.0023: . 0.0047: You can now start qemu (>= 7.2, with commit 13c6be96618c): 0.0047: kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/tmp/passt_1.socket 0.0047: or qrap, for earlier qemu versions: 0.0047: ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio 0.0055: SO_PEEK_OFF supported 0.0055: TCP_INFO tcpi_snd_wnd field supported 0.0055: TCP_INFO tcpi_bytes_acked field supported 0.0055: TCP_INFO tcpi_min_rtt field supportedOkay, nothing unexpected so far. Could you also please compare the output of 'passt -f -d' between the two cases? Just terminate it with ^C once you have the output.Certainly! I'm sorry I didn't do this earlier. I'd checked on this: there is no difference between the command that runs passt on Fedora 41 or Debian Trixie. This is the command on Fedora 41: passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/4-dragora-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/4-dragora-net0-passt.pid and this is the command on Debian Trixie: passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/1-vm1-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/1-vm1-net0-passt.pid- This second issue is perhaps a bit more Debian-specific, but I am going to mention it so that you might drop some hints for the Debian maintainers to debug this: Once Apparmor is disabled and a VM is configured to work with passt, DNS resolution doesn't work in the VM (IP Addresses work just fine) i.e. ping fsf.org doesn't work but `ping 209.51.188.174` does. The hypervisor details follow: $ virsh version # on Debian Testing a.k.a. 'Trixie' Compiled against library: libvirt 11.0.0 Using library: libvirt 11.0.0 Using API: QEMU 11.0.0Running hypervisor: QEMU 9.2.0 This, again, isn't an issue with Fedora 41, where everything just works. The hypervisor details for Fedora 41 are: $ virsh version # on Fedora 41 Compiled against library: libvirt 10.6.0 Using library: libvirt 10.6.0 Using API: QEMU 10.6.0 Running hypervisor: QEMU 9.1.2Oops. Can you share the command line of passt as run by libvirt (say, 'ps aux|grep passt') for this case? passt has some basic DNS forwarding capabilities, which are configured depending on the host's resolver configuration.How are resolvers configured on the two hosts? What does /etc/resolv.conf say?$ cat /etc/resolv.conf # On Fedora 41 # This is /run/systemd/resolve/stub-resolv.conf managed by man:systemd-resolved(8). [...] nameserver 127.0.0.53 options edns0 trust-ad search . $ cat /etc/resolv.conf # On Debian Trixie # This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8). [...] nameserver 192.168.100.1 search . $ cat /etc/resolv.conf # On a Debian 11 OS # Generated by NetworkManager nameserver 192.168.100.1 Also the output of `resolvectl status` for good measure: # On Fedora 41 Global Protocols: LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported resolv.conf mode: stub Link 2 (wlp0s20f3) Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 Protocols: +DefaultRoute LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported Current DNS Server: 192.168.100.1 DNS Servers: 192.168.100.1 # On Debian Trixie Global Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported resolv.conf mode: uplink Link 2 (enp1s0) Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported DNS Servers: 192.168.100.1 Default Route: yesIf nothing is visible from there, next check: 'virsh edit vm1' on Debian and add a log file in the XML, that is, replace this line: <backend type='passt'/> with: <backend type='passt' logFile='/tmp/passt.log'/> and then share the log.The log from Debian Trixie host for VM1: passt 0.0~git20250121.4f2c8e7-1: /usr/bin/passt.avx2 (6428) 0.0017: info: No interfaces with usable IPv6 routes 0.0029: info: UNIX domain socket bound at /run/user/1000/libvirt/qemu/run/passt/2-vm1-net0.socket 0.0030: info: Template interface: enp1s0 (IPv4) 0.0030: info: MAC: 0.0030: info: host: 9a:55:9a:55:9a:55 0.0030: info: NAT to host 127.0.0.1: 192.168.100.1 0.0030: info: DHCP: 0.0031: info: assign: 192.168.100.157 0.0031: info: mask: 255.255.255.0 0.0031: info: router: 192.168.100.1 0.0031: info: DNS: 0.0031: info: 192.168.100.1 0.0031: info: DNS search list: 0.0031: info: . 0.0066: info: You can now start qemu (>= 7.2, with commit 13c6be96618c): 0.0066: info: kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/run/user/1000/libvirt/qemu/run/passt/2-vm1-net0.socket 0.0066: info: or qrap, for earlier qemu versions: 0.0066: info: ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio 0.0617: info: accepted connection from PID 0 38.6257: info: DHCP: offer to discover 38.6257: info: from 52:54:00:a0:e1:7c 38.6471: info: DHCP: ack to request 38.6471: info: from 52:54:00:a0:e1:7c 451.4989: info: Client connection closed, exiting The log from Fedora 41: passt 0^20250121.g4f2c8e7-2.fc41.x86_64: /usr/bin/passt.avx2 (3138) 0.0017: info: UNIX domain socket bound at /run/user/1000/libvirt/qemu/run/passt/3-debian-trixie-net0.socket 0.0018: info: Template interface: wlp0s20f3 (IPv4) 0.0018: info: MAC: 0.0018: info: host: 9a:55:9a:55:9a:55 0.0018: info: NAT to host 127.0.0.1: 192.168.100.1 0.0018: info: DHCP: 0.0018: info: assign: 192.168.100.157 0.0018: info: mask: 255.255.255.0 0.0018: info: router: 192.168.100.1 0.0018: info: DNS: 0.0018: info: 192.168.100.1 0.0018: info: DNS search list: 0.0018: info: . 0.0043: info: You can now start qemu (>= 7.2, with commit 13c6be96618c): 0.0043: info: kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/run/user/1000/libvirt/qemu/run/passt/3-debian-trixie-net0.socket 0.0043: info: or qrap, for earlier qemu versions: 0.0043: info: ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio 0.0591: info: accepted connection from PID 0 10.7894: info: DHCP: ack to discover (Rapid Commit) 10.7894: info: from 52:54:00:8f:e7:c3 99.6704: info: Client connection closed, exiting-- Stefano
On Thu, 30 Jan 2025 10:05:14 +0000 Prafulla Giri <prafulla.giri(a)protonmail.com> wrote:I didn't have auditd installed on Debian and installed it, and running everything with the default auditd config (with my Apparmor disabled for passt, as mentioned previously) does not result in anything. Do I have to configure auditd manually? Any pointers on that, please?No, the default configuration is just fine. But you should re-enable AppArmor for passt so that we can see meaningful messages in the logs.$ passt -f -d # on Debian Testing/Trixie 0.0016: No interfaces with usable IPv6 routes 0.0017: Failed to detect external interface for IPv6 0.0028: UNIX domain socket bound at /tmp/passt_1.socket 0.0029: Template interface: enp1s0 (IPv4) 0.0029: MAC: 0.0029: host: 9a:55:9a:55:9a:55 0.0029: NAT to host 127.0.0.1: 192.168.100.1 0.0029: DHCP: 0.0029: assign: 192.168.100.157 0.0029: mask: 255.255.255.0 0.0029: router: 192.168.100.1 0.0029: DNS: 0.0029: 192.168.100.1So, judging from this configuration, it looks like we advertise to the guest (via DHCP) 192.168.100.1 as resolver (copied from the host), and when we receive packets from the guest for 192.168.100.1, we'll re-map them to the host. Nothing strange so far, systemd-resolved is running on the host, it should get our queries and reply to them.$ cat /etc/resolv.conf # On Debian Trixie # This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8). [...] nameserver 192.168.100.1 search . $ cat /etc/resolv.conf # On a Debian 11 OS # Generated by NetworkManager nameserver 192.168.100.1 Also the output of `resolvectl status` for good measure: # On Fedora 41 Global Protocols: LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported resolv.conf mode: stub Link 2 (wlp0s20f3) Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 Protocols: +DefaultRoute LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported Current DNS Server: 192.168.100.1 DNS Servers: 192.168.100.1 # On Debian Trixie Global Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported resolv.conf mode: uplink Link 2 (enp1s0) Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported DNS Servers: 192.168.100.1 Default Route: yesEverything as expected here, I don't see any obvious reason why systemd-resolved should discard our queries.The log from Debian Trixie host for VM1: passt 0.0~git20250121.4f2c8e7-1: /usr/bin/passt.avx2 (6428) 0.0017: info: No interfaces with usable IPv6 routes 0.0029: info: UNIX domain socket bound at /run/user/1000/libvirt/qemu/run/passt/2-vm1-net0.socket 0.0030: info: Template interface: enp1s0 (IPv4) 0.0030: info: MAC: 0.0030: info: host: 9a:55:9a:55:9a:55 0.0030: info: NAT to host 127.0.0.1: 192.168.100.1 0.0030: info: DHCP: 0.0031: info: assign: 192.168.100.157 0.0031: info: mask: 255.255.255.0 0.0031: info: router: 192.168.100.1 0.0031: info: DNS: 0.0031: info: 192.168.100.1 0.0031: info: DNS search list: 0.0031: info: . 0.0066: info: You can now start qemu (>= 7.2, with commit 13c6be96618c): 0.0066: info: kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/run/user/1000/libvirt/qemu/run/passt/2-vm1-net0.socket 0.0066: info: or qrap, for earlier qemu versions: 0.0066: info: ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio 0.0617: info: accepted connection from PID 0 38.6257: info: DHCP: offer to discover 38.6257: info: from 52:54:00:a0:e1:7c 38.6471: info: DHCP: ack to request 38.6471: info: from 52:54:00:a0:e1:7c 451.4989: info: Client connection closed, exitingUnfortunately libvirt doesn't let us enable more verbose logging. I hoped to see DNS queries there, but without --debug given to passt, that won't work. Another idea: pasta(1) does the same job as passt(1) (it's the same code and same binary) and it's intended for containers, but it has a stand-alone mode that can probably help us to debug this, because it's a network namespace that will look like your guest, and it can also take packet captures. What happens if you run: pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org ? If the query fails (that's what I would expect), can you please attach the output and the resulting packet capture? Note that the packet capture might have sensitive data, please have a look at it with e.g. Wireshark/tshark before sharing it. By the way, if you run this without specifying any command, for example: pasta --config-net --pcap /tmp/dns.pcap you will get a shell where you can play around in a separate network namespace and with a network stack that looks pretty much the same as passt for your guest. -- Stefano
On Saturday, February 1st, 2025 at 2:05 AM, Stefano Brivio <sbrivio(a)redhat.com> wrote:On Thu, 30 Jan 2025 10:05:14 +0000 Prafulla Giri prafulla.giri(a)protonmail.com wrote:The following is the output of grep-ping 'passt' after re-enforcing the apparmor config and trying to start a VM: $ grep passt /var/log/audit/audit.log # Debian Trixie type=AVC msg=audit(1738501259.829:124): apparmor="STATUS" operation="profile_load" profile="unconfined" name="passt" pid=1935 comm="apparmor_parser" type=AVC msg=audit(1738501309.118:135): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2030 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738501309.118:135): arch=c000003e syscall=59 success=no exit=-13 a0=7faf24035fc0 a1=7faf24035210 a2=7ffc063280d0 a3=0 items=0 ppid=1964 pid=2030 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=ANOM_ABEND msg=audit(1738501309.118:136): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2030 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy" type=AVC msg=audit(1738501923.727:148): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2088 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738501923.727:148): arch=c000003e syscall=59 success=no exit=-13 a0=7ff564035d40 a1=7ff564039d00 a2=7fffe9aa1de0 a3=0 items=0 ppid=2060 pid=2088 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=ANOM_ABEND msg=audit(1738501923.727:149): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2088 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy" type=AVC msg=audit(1738502301.651:174): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2145 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738502301.651:174): arch=c000003e syscall=59 success=no exit=-13 a0=7fe208034ce0 a1=7fe208034350 a2=7fffd2e60120 a3=0 items=0 ppid=2117 pid=2145 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=ANOM_ABEND msg=audit(1738502301.651:175): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2145 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy"I didn't have auditd installed on Debian and installed it, and running everything with the default auditd config (with my Apparmor disabled for passt, as mentioned previously) does not result in anything. Do I have to configure auditd manually? Any pointers on that, please?No, the default configuration is just fine. But you should re-enable AppArmor for passt so that we can see meaningful messages in the logs.This one errors out. dns.pcap is attached. $ pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org # Debian Trixie/Testing 0.0015: No interfaces with usable IPv6 routes 0.0015: Failed to detect external interface for IPv6 0.0073: Template interface: enp1s0 (IPv4) 0.0073: Namespace interface: enp1s0 0.0074: MAC: 0.0074: host: 9a:55:9a:55:9a:55 0.0074: NAT to host 127.0.0.1: 192.168.100.1 0.0074: DHCP: 0.0074: assign: 192.168.100.157 0.0074: mask: 255.255.255.0 0.0075: router: 192.168.100.1 0.0075: DNS: 0.0075: 192.168.100.1 0.0076: DNS search list: 0.0076: . 0.0146: SO_PEEK_OFF supported 0.0146: TCP_INFO tcpi_snd_wnd field supported 0.0146: TCP_INFO tcpi_bytes_acked field supported 0.0146: TCP_INFO tcpi_min_rtt field supported 0.0147: Saving packet capture to /tmp/dns.pcap 0.0197: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0371: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0372: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0372: tap: protocol 17, 192.168.100.157:41892 -> 192.168.100.1:53 (1 packet) 0.0372: Flow 0 (NEW): FREE -> NEW 0.0372: Flow 0 (INI): NEW -> INI 0.0372: Flow 0 (INI): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => ? 0.0372: Flow 0 (TGT): INI -> TGT 0.0373: Flow 0 (TGT): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => HOST [0.0.0.0]:41892 -> [127.0.0.1]:53 0.0373: Flow 0 (UDP flow): TGT -> TYPED 0.0373: Flow 0 (UDP flow): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => HOST [0.0.0.0]:41892 -> [127.0.0.1]:53 0.0373: Flow 0 (UDP flow): Side 0 hash table insert: bucket: 31049 0.0374: Flow 0 (UDP flow): TYPED -> ACTIVE 0.0374: Flow 0 (UDP flow): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => HOST [0.0.0.0]:41892 -> [127.0.0.1]:53 0.0374: pasta: epoll event on UDP reply socket 95 (events: 0x00000008) 0.0374: ICMP error on UDP socket 95: Connection refused 0.5320: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.8201: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 1.5560: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 2.3240: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) ;; communications error to 192.168.100.1#53: timed out 5.0431: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 5.0431: tap: protocol 17, 192.168.100.157:46013 -> 192.168.100.1:53 (1 packet) 5.0432: Flow 1 (NEW): FREE -> NEW 5.0432: Flow 1 (INI): NEW -> INI 5.0432: Flow 1 (INI): TAP [192.168.100.157]:46013 -> [192.168.100.1]:53 => ? 5.0432: Flow 1 (TGT): INI -> TGT 5.0432: Flow 1 (TGT): TAP [192.168.100.157]:46013 -> [192.168.100.1]:53 => HOST [0.0.0.0]:46013 -> [127.0.0.1]:53 5.0432: Flow 1 (UDP flow): TGT -> TYPED 5.0432: Flow 1 (UDP flow): TAP [192.168.100.157]:46013 -> [192.168.100.1]:53 => HOST [0.0.0.0]:46013 -> [127.0.0.1]:53 5.0433: Flow 1 (UDP flow): Side 0 hash table insert: bucket: 100062 5.0433: Flow 1 (UDP flow): TYPED -> ACTIVE 5.0433: Flow 1 (UDP flow): TAP [192.168.100.157]:46013 -> [192.168.100.1]:53 => HOST [0.0.0.0]:46013 -> [127.0.0.1]:53 5.0434: pasta: epoll event on UDP reply socket 160 (events: 0x00000008) 5.0434: ICMP error on UDP socket 160: Connection refused 5.4924: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) ;; communications error to 192.168.100.1#53: timed out 10.0478: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 10.0478: tap: protocol 17, 192.168.100.157:55861 -> 192.168.100.1:53 (1 packet) 10.0478: Flow 2 (NEW): FREE -> NEW 10.0478: Flow 2 (INI): NEW -> INI 10.0478: Flow 2 (INI): TAP [192.168.100.157]:55861 -> [192.168.100.1]:53 => ? 10.0478: Flow 2 (TGT): INI -> TGT 10.0479: Flow 2 (TGT): TAP [192.168.100.157]:55861 -> [192.168.100.1]:53 => HOST [0.0.0.0]:55861 -> [127.0.0.1]:53 10.0479: Flow 2 (UDP flow): TGT -> TYPED 10.0479: Flow 2 (UDP flow): TAP [192.168.100.157]:55861 -> [192.168.100.1]:53 => HOST [0.0.0.0]:55861 -> [127.0.0.1]:53 10.0480: Flow 2 (UDP flow): Side 0 hash table insert: bucket: 342763 10.0481: Flow 2 (UDP flow): TYPED -> ACTIVE 10.0481: Flow 2 (UDP flow): TAP [192.168.100.157]:55861 -> [192.168.100.1]:53 => HOST [0.0.0.0]:55861 -> [127.0.0.1]:53 10.0482: pasta: epoll event on UDP reply socket 161 (events: 0x00000008) 10.0483: ICMP error on UDP socket 161: Connection refused 13.4282: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) ;; communications error to 192.168.100.1#53: timed out ;; no servers could be reached$ passt -f -d # on Debian Testing/Trixie 0.0016: No interfaces with usable IPv6 routes 0.0017: Failed to detect external interface for IPv6 0.0028: UNIX domain socket bound at /tmp/passt_1.socket 0.0029: Template interface: enp1s0 (IPv4) 0.0029: MAC: 0.0029: host: 9a:55:9a:55:9a:55 0.0029: NAT to host 127.0.0.1: 192.168.100.1 0.0029: DHCP: 0.0029: assign: 192.168.100.157 0.0029: mask: 255.255.255.0 0.0029: router: 192.168.100.1 0.0029: DNS: 0.0029: 192.168.100.1So, judging from this configuration, it looks like we advertise to the guest (via DHCP) 192.168.100.1 as resolver (copied from the host), and when we receive packets from the guest for 192.168.100.1, we'll re-map them to the host. Nothing strange so far, systemd-resolved is running on the host, it should get our queries and reply to them.$ cat /etc/resolv.conf # On Debian Trixie # This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8). [...] nameserver 192.168.100.1 search . $ cat /etc/resolv.conf # On a Debian 11 OS # Generated by NetworkManager nameserver 192.168.100.1 Also the output of `resolvectl status` for good measure: # On Fedora 41 Global Protocols: LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported resolv.conf mode: stub Link 2 (wlp0s20f3) Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 Protocols: +DefaultRoute LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported Current DNS Server: 192.168.100.1 DNS Servers: 192.168.100.1 # On Debian Trixie Global Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported resolv.conf mode: uplink Link 2 (enp1s0) Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported DNS Servers: 192.168.100.1 Default Route: yesEverything as expected here, I don't see any obvious reason why systemd-resolved should discard our queries.The log from Debian Trixie host for VM1: passt 0.0~git20250121.4f2c8e7-1: /usr/bin/passt.avx2 (6428) 0.0017: info: No interfaces with usable IPv6 routes 0.0029: info: UNIX domain socket bound at /run/user/1000/libvirt/qemu/run/passt/2-vm1-net0.socket 0.0030: info: Template interface: enp1s0 (IPv4) 0.0030: info: MAC: 0.0030: info: host: 9a:55:9a:55:9a:55 0.0030: info: NAT to host 127.0.0.1: 192.168.100.1 0.0030: info: DHCP: 0.0031: info: assign: 192.168.100.157 0.0031: info: mask: 255.255.255.0 0.0031: info: router: 192.168.100.1 0.0031: info: DNS: 0.0031: info: 192.168.100.1 0.0031: info: DNS search list: 0.0031: info: . 0.0066: info: You can now start qemu (>= 7.2, with commit 13c6be96618c): 0.0066: info: kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/run/user/1000/libvirt/qemu/run/passt/2-vm1-net0.socket 0.0066: info: or qrap, for earlier qemu versions: 0.0066: info: ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio 0.0617: info: accepted connection from PID 0 38.6257: info: DHCP: offer to discover 38.6257: info: from 52:54:00:a0:e1:7c 38.6471: info: DHCP: ack to request 38.6471: info: from 52:54:00:a0:e1:7c 451.4989: info: Client connection closed, exitingUnfortunately libvirt doesn't let us enable more verbose logging. I hoped to see DNS queries there, but without --debug given to passt, that won't work. Another idea: pasta(1) does the same job as passt(1) (it's the same code and same binary) and it's intended for containers, but it has a stand-alone mode that can probably help us to debug this, because it's a network namespace that will look like your guest, and it can also take packet captures. What happens if you run: pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org ?If the query fails (that's what I would expect), can you please attach the output and the resulting packet capture? Note that the packet capture might have sensitive data, please have a look at it with e.g. Wireshark/tshark before sharing it. By the way, if you run this without specifying any command, for example: pasta --config-net --pcap /tmp/dns.pcap you will get a shell where you can play around in a separate network namespace and with a network stack that looks pretty much the same as passt for your guest.This is rather strange: from the shell I successfully managed to `ping fsf.org` and `ping gnu.org`. I went back and ran $ pasta --config-net --trace --pcap /tmp/ping.pcap -- ping -c 5 fsf.org # and the following output followed (ping.pcap is also attached) 0.0013: No interfaces with usable IPv6 routes 0.0013: Failed to detect external interface for IPv6 0.0091: Template interface: enp1s0 (IPv4) 0.0091: Namespace interface: enp1s0 0.0092: MAC: 0.0092: host: 9a:55:9a:55:9a:55 0.0092: NAT to host 127.0.0.1: 192.168.100.1 0.0092: DHCP: 0.0092: assign: 192.168.100.157 0.0093: mask: 255.255.255.0 0.0093: router: 192.168.100.1 0.0093: DNS: 0.0093: 192.168.100.1 0.0093: DNS search list: 0.0094: . 0.0161: SO_PEEK_OFF supported 0.0161: TCP_INFO tcpi_snd_wnd field supported 0.0161: TCP_INFO tcpi_bytes_acked field supported 0.0161: TCP_INFO tcpi_min_rtt field supported 0.0162: Saving packet capture to /tmp/ping.pcap PING fsf.org (209.51.188.174) 56(84) bytes of data. 0.0181: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0181: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0182: tap: protocol 1, 192.168.100.157 -> 209.51.188.174 (1 packet) 0.0182: Flow 0 (NEW): FREE -> NEW 0.0182: Flow 0 (INI): NEW -> INI 0.0182: Flow 0 (INI): TAP [192.168.100.157]:11 -> [209.51.188.174]:11 => ? 0.0182: Flow 0 (TGT): INI -> TGT 0.0182: Flow 0 (TGT): TAP [192.168.100.157]:11 -> [209.51.188.174]:11 => HOST [0.0.0.0]:0 -> [209.51.188.174]:11 0.0182: Flow 0 (ICMP ping sequence): TGT -> TYPED 0.0183: Flow 0 (ICMP ping sequence): TAP [192.168.100.157]:11 -> [209.51.188.174]:11 => HOST [0.0.0.0]:0 -> [209.51.188.174]:11 0.0183: Flow 0 (ICMP ping sequence): new socket 95 for echo ID 11 0.0183: Flow 0 (ICMP ping sequence): Side 0 hash table insert: bucket: 150766 0.0184: Flow 0 (ICMP ping sequence): TYPED -> ACTIVE 0.0184: Flow 0 (ICMP ping sequence): TAP [192.168.100.157]:11 -> [209.51.188.174]:11 => HOST [0.0.0.0]:0 -> [209.51.188.174]:11 0.0184: Flow 0 (ICMP ping sequence): echo request to socket, ID: 11, seq: 1 0.0214: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0538: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.4423: pasta: epoll event on ICMP/ICMPv6 ping socket 95 (events: 0x00000001) 0.4424: Flow 0 (ICMP ping sequence): echo reply to tap, ID: 11, seq: 1 64 bytes from www.fsf.org (209.51.188.174): icmp_seq=1 ttl=255 time=424 ms 0.7857: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 1.0188: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 1.0189: tap: protocol 1, 192.168.100.157 -> 209.51.188.174 (1 packet) 1.0189: Flow 0 (ICMP ping sequence): echo request to socket, ID: 11, seq: 2 1.0736: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 1.1777: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 1.4302: pasta: epoll event on ICMP/ICMPv6 ping socket 95 (events: 0x00000001) 1.4303: Flow 0 (ICMP ping sequence): echo reply to tap, ID: 11, seq: 2 64 bytes from www.fsf.org (209.51.188.174): icmp_seq=2 ttl=255 time=412 ms 2.0188: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 2.0189: tap: protocol 1, 192.168.100.157 -> 209.51.188.174 (1 packet) 2.0190: Flow 0 (ICMP ping sequence): echo request to socket, ID: 11, seq: 3 2.4837: pasta: epoll event on ICMP/ICMPv6 ping socket 95 (events: 0x00000001) 2.4837: Flow 0 (ICMP ping sequence): echo reply to tap, ID: 11, seq: 3 64 bytes from www.fsf.org (209.51.188.174): icmp_seq=3 ttl=255 time=465 ms 3.0191: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 3.0191: tap: protocol 1, 192.168.100.157 -> 209.51.188.174 (1 packet) 3.0192: Flow 0 (ICMP ping sequence): echo request to socket, ID: 11, seq: 4 3.6917: pasta: epoll event on ICMP/ICMPv6 ping socket 95 (events: 0x00000001) 3.6918: Flow 0 (ICMP ping sequence): echo reply to tap, ID: 11, seq: 4 64 bytes from www.fsf.org (209.51.188.174): icmp_seq=4 ttl=255 time=673 ms 4.0186: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 4.0187: tap: protocol 1, 192.168.100.157 -> 209.51.188.174 (1 packet) 4.0188: Flow 0 (ICMP ping sequence): echo request to socket, ID: 11, seq: 5 4.4281: pasta: epoll event on ICMP/ICMPv6 ping socket 95 (events: 0x00000001) 4.4282: Flow 0 (ICMP ping sequence): echo reply to tap, ID: 11, seq: 5 64 bytes from www.fsf.org (209.51.188.174): icmp_seq=5 ttl=255 time=410 ms --- fsf.org ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4001ms rtt min/avg/max/mdev = 409.797/476.856/673.012/100.088 ms There were no entries on the auditlog regarding pasta. I wonder if these 2 issues are mutually exclusive: If I disable apparmor and let passt run, it doesn't get DNS configs right; however, if I don't make any changes to apparmor configs, while passt won't be able to create the socket at /run/*, it will get DNS configs right (?) Curioser and curioser.-- Stefano
On Sunday, February 2nd, 2025 at 8:06 PM, Prafulla Giri <prafulla.giri(a)protonmail.com> wrote:I wonder if these 2 issues are mutually exclusive: If I disable apparmor and let passt run, it doesn't get DNS configs right; however, if I don't make any changes to apparmor configs, while passt won't be able to create the socket at /run/*, it will get DNS configs right (?)Nope. I just disabled app-armor and tested $ pasta --config-net and could ping fsf.org but could not nslookup fsf.org
On Sun, 02 Feb 2025 14:21:49 +0000 Prafulla Giri <prafulla.giri(a)protonmail.com> wrote:On Saturday, February 1st, 2025 at 2:05 AM, Stefano Brivio <sbrivio(a)redhat.com> wrote:System call number 59 (this seems to be x86_64) is "execve": $ ausyscall 59 execve and this seems to be libvirt failing to execute passt itself, but: https://gitlab.com/libvirt/libvirt/-/blob/0264a7704ada52f686cafe8f6402d5b60… Do you see the libvirtd profile loaded if you run 'aa-status'? Do you have this line: /usr/bin/passt Cx -> passt, in /etc/apparmor.d/abstractions/libvirt-qemu? I wonder if something bad happened during installation. Can you perhaps grep a bit before and after those messages (say, grep -A5 -B5) to see if we spot something else related to libvirt?On Thu, 30 Jan 2025 10:05:14 +0000 Prafulla Giri prafulla.giri(a)protonmail.com wrote:The following is the output of grep-ping 'passt' after re-enforcing the apparmor config and trying to start a VM: $ grep passt /var/log/audit/audit.log # Debian Trixie type=AVC msg=audit(1738501259.829:124): apparmor="STATUS" operation="profile_load" profile="unconfined" name="passt" pid=1935 comm="apparmor_parser" type=AVC msg=audit(1738501309.118:135): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2030 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738501309.118:135): arch=c000003e syscall=59 success=no exit=-13 a0=7faf24035fc0 a1=7faf24035210 a2=7ffc063280d0 a3=0 items=0 ppid=1964 pid=2030 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=ANOM_ABEND msg=audit(1738501309.118:136): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2030 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy"I didn't have auditd installed on Debian and installed it, and running everything with the default auditd config (with my Apparmor disabled for passt, as mentioned previously) does not result in anything. Do I have to configure auditd manually? Any pointers on that, please?No, the default configuration is just fine. But you should re-enable AppArmor for passt so that we can see meaningful messages in the logs.type=AVC msg=audit(1738501923.727:148): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2088 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738501923.727:148): arch=c000003e syscall=59 success=no exit=-13 a0=7ff564035d40 a1=7ff564039d00 a2=7fffe9aa1de0 a3=0 items=0 ppid=2060 pid=2088 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=ANOM_ABEND msg=audit(1738501923.727:149): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2088 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy" type=AVC msg=audit(1738502301.651:174): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2145 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738502301.651:174): arch=c000003e syscall=59 success=no exit=-13 a0=7fe208034ce0 a1=7fe208034350 a2=7fffd2e60120 a3=0 items=0 ppid=2117 pid=2145 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=ANOM_ABEND msg=audit(1738502301.651:175): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2145 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy"Ouch. I just sent a patch for this, you can test it by checking out passt locally: git clone git://passt.top/passt; cd passt applying it (you might need to install 'b4'): b4 shazam https://archives.passt.top/passt-dev/20250203082210.2114348-1-sbrivio@redha… then: make and ./pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org You can also install it to /usr/local with 'make install', it's just a couple of files and will uninstall cleanly with 'make uninstall' if needed. Note that AppArmor profiles don't apply to binaries under /usr/local/bin.This one errors out. dns.pcap is attached. $ pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org # Debian Trixie/Testing 0.0015: No interfaces with usable IPv6 routes 0.0015: Failed to detect external interface for IPv6 0.0073: Template interface: enp1s0 (IPv4) 0.0073: Namespace interface: enp1s0 0.0074: MAC: 0.0074: host: 9a:55:9a:55:9a:55 0.0074: NAT to host 127.0.0.1: 192.168.100.1 0.0074: DHCP: 0.0074: assign: 192.168.100.157 0.0074: mask: 255.255.255.0 0.0075: router: 192.168.100.1 0.0075: DNS: 0.0075: 192.168.100.1 0.0076: DNS search list: 0.0076: . 0.0146: SO_PEEK_OFF supported 0.0146: TCP_INFO tcpi_snd_wnd field supported 0.0146: TCP_INFO tcpi_bytes_acked field supported 0.0146: TCP_INFO tcpi_min_rtt field supported 0.0147: Saving packet capture to /tmp/dns.pcap 0.0197: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0371: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0372: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0372: tap: protocol 17, 192.168.100.157:41892 -> 192.168.100.1:53 (1 packet) 0.0372: Flow 0 (NEW): FREE -> NEW 0.0372: Flow 0 (INI): NEW -> INI 0.0372: Flow 0 (INI): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => ? 0.0372: Flow 0 (TGT): INI -> TGT 0.0373: Flow 0 (TGT): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => HOST [0.0.0.0]:41892 -> [127.0.0.1]:53 0.0373: Flow 0 (UDP flow): TGT -> TYPED 0.0373: Flow 0 (UDP flow): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => HOST [0.0.0.0]:41892 -> [127.0.0.1]:53 0.0373: Flow 0 (UDP flow): Side 0 hash table insert: bucket: 31049 0.0374: Flow 0 (UDP flow): TYPED -> ACTIVE 0.0374: Flow 0 (UDP flow): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => HOST [0.0.0.0]:41892 -> [127.0.0.1]:53 0.0374: pasta: epoll event on UDP reply socket 95 (events: 0x00000008) 0.0374: ICMP error on UDP socket 95: Connection refused$ passt -f -d # on Debian Testing/Trixie 0.0016: No interfaces with usable IPv6 routes 0.0017: Failed to detect external interface for IPv6 0.0028: UNIX domain socket bound at /tmp/passt_1.socket 0.0029: Template interface: enp1s0 (IPv4) 0.0029: MAC: 0.0029: host: 9a:55:9a:55:9a:55 0.0029: NAT to host 127.0.0.1: 192.168.100.1 0.0029: DHCP: 0.0029: assign: 192.168.100.157 0.0029: mask: 255.255.255.0 0.0029: router: 192.168.100.1 0.0029: DNS: 0.0029: 192.168.100.1So, judging from this configuration, it looks like we advertise to the guest (via DHCP) 192.168.100.1 as resolver (copied from the host), and when we receive packets from the guest for 192.168.100.1, we'll re-map them to the host. Nothing strange so far, systemd-resolved is running on the host, it should get our queries and reply to them.$ cat /etc/resolv.conf # On Debian Trixie # This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8). [...] nameserver 192.168.100.1 search . $ cat /etc/resolv.conf # On a Debian 11 OS # Generated by NetworkManager nameserver 192.168.100.1 Also the output of `resolvectl status` for good measure: # On Fedora 41 Global Protocols: LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported resolv.conf mode: stub Link 2 (wlp0s20f3) Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 Protocols: +DefaultRoute LLMNR=resolve -mDNS -DNSOverTLS DNSSEC=no/unsupported Current DNS Server: 192.168.100.1 DNS Servers: 192.168.100.1 # On Debian Trixie Global Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported resolv.conf mode: uplink Link 2 (enp1s0) Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported DNS Servers: 192.168.100.1 Default Route: yesEverything as expected here, I don't see any obvious reason why systemd-resolved should discard our queries.The log from Debian Trixie host for VM1: passt 0.0~git20250121.4f2c8e7-1: /usr/bin/passt.avx2 (6428) 0.0017: info: No interfaces with usable IPv6 routes 0.0029: info: UNIX domain socket bound at /run/user/1000/libvirt/qemu/run/passt/2-vm1-net0.socket 0.0030: info: Template interface: enp1s0 (IPv4) 0.0030: info: MAC: 0.0030: info: host: 9a:55:9a:55:9a:55 0.0030: info: NAT to host 127.0.0.1: 192.168.100.1 0.0030: info: DHCP: 0.0031: info: assign: 192.168.100.157 0.0031: info: mask: 255.255.255.0 0.0031: info: router: 192.168.100.1 0.0031: info: DNS: 0.0031: info: 192.168.100.1 0.0031: info: DNS search list: 0.0031: info: . 0.0066: info: You can now start qemu (>= 7.2, with commit 13c6be96618c): 0.0066: info: kvm ... -device virtio-net-pci,netdev=s -netdev stream,id=s,server=off,addr.type=unix,addr.path=/run/user/1000/libvirt/qemu/run/passt/2-vm1-net0.socket 0.0066: info: or qrap, for earlier qemu versions: 0.0066: info: ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio 0.0617: info: accepted connection from PID 0 38.6257: info: DHCP: offer to discover 38.6257: info: from 52:54:00:a0:e1:7c 38.6471: info: DHCP: ack to request 38.6471: info: from 52:54:00:a0:e1:7c 451.4989: info: Client connection closed, exitingUnfortunately libvirt doesn't let us enable more verbose logging. I hoped to see DNS queries there, but without --debug given to passt, that won't work. Another idea: pasta(1) does the same job as passt(1) (it's the same code and same binary) and it's intended for containers, but it has a stand-alone mode that can probably help us to debug this, because it's a network namespace that will look like your guest, and it can also take packet captures. What happens if you run: pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org ?[...] This is rather strange: from the shell I successfully managed to `ping fsf.org` and `ping gnu.org`.That's because they were already cached on your host at this point (I suppose by systemd-resolved) and ping didn't need to resolve anything, just call getaddrinfo() and get the addresses back. There's no UDP at all in the output below:I went back and ran $ pasta --config-net --trace --pcap /tmp/ping.pcap -- ping -c 5 fsf.org # and the following output followed (ping.pcap is also attached) 0.0013: No interfaces with usable IPv6 routes 0.0013: Failed to detect external interface for IPv6 0.0091: Template interface: enp1s0 (IPv4) 0.0091: Namespace interface: enp1s0 0.0092: MAC: 0.0092: host: 9a:55:9a:55:9a:55 0.0092: NAT to host 127.0.0.1: 192.168.100.1 0.0092: DHCP: 0.0092: assign: 192.168.100.157 0.0093: mask: 255.255.255.0 0.0093: router: 192.168.100.1 0.0093: DNS: 0.0093: 192.168.100.1 0.0093: DNS search list: 0.0094: . 0.0161: SO_PEEK_OFF supported 0.0161: TCP_INFO tcpi_snd_wnd field supported 0.0161: TCP_INFO tcpi_bytes_acked field supported 0.0161: TCP_INFO tcpi_min_rtt field supported 0.0162: Saving packet capture to /tmp/ping.pcap PING fsf.org (209.51.188.174) 56(84) bytes of data. 0.0181: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0181: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0182: tap: protocol 1, 192.168.100.157 -> 209.51.188.174 (1 packet)-- Stefano
On Monday, February 3rd, 2025 at 2:20 PM, Stefano Brivio <sbrivio(a)redhat.com> wrote:Yes, it is loaded.The following is the output of grep-ping 'passt' after re-enforcing the apparmor config and trying to start a VM: $ grep passt /var/log/audit/audit.log # Debian Trixie type=AVC msg=audit(1738501259.829:124): apparmor="STATUS" operation="profile_load" profile="unconfined" name="passt" pid=1935 comm="apparmor_parser" type=AVC msg=audit(1738501309.118:135): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2030 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738501309.118:135): arch=c000003e syscall=59 success=no exit=-13 a0=7faf24035fc0 a1=7faf24035210 a2=7ffc063280d0 a3=0 items=0 ppid=1964 pid=2030 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=ANOM_ABEND msg=audit(1738501309.118:136): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2030 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy"System call number 59 (this seems to be x86_64) is "execve": $ ausyscall 59 execve and this seems to be libvirt failing to execute passt itself, but: https://gitlab.com/libvirt/libvirt/-/blob/0264a7704ada52f686cafe8f6402d5b60… Do you see the libvirtd profile loaded if you run 'aa-status'?Do you have this line: /usr/bin/passt Cx -> passt,Yes, it is there.in /etc/apparmor.d/abstractions/libvirt-qemu? I wonder if something bad happened during installation. Can you perhaps grep a bit before and after those messages (say, grep -A5 -B5) to see if we spot something else related to libvirt?$ grep -A5 -B5 passt /var/log/audit/audit.log # Debian Trixie type=SERVICE_STOP msg=audit(1738501179.991:119): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='unit=libvirtd comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'UID="root" AUID="unset" type=USER_ACCT msg=audit(1738501259.697:120): pid=1931 uid=1000 auid=1000 ses=1 subj=unconfined msg='op=PAM:accounting grantors=pam_permit acct="larryboy" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=USER_CMD msg=audit(1738501259.697:121): pid=1931 uid=1000 auid=1000 ses=1 subj=unconfined msg='cwd="/home/larryboy" cmd=61612D656E666F726365202F6574632F61707061726D6F722E642F7573722E62696E2E7061737374 exe="/usr/bin/sudo" terminal=pts/0 res=success'UID="larryboy" AUID="larryboy" type=CRED_REFR msg=audit(1738501259.697:122): pid=1931 uid=1000 auid=1000 ses=1 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=USER_START msg=audit(1738501259.697:123): pid=1931 uid=1000 auid=1000 ses=1 subj=unconfined msg='op=PAM:session_open grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=AVC msg=audit(1738501259.829:124): apparmor="STATUS" operation="profile_load" profile="unconfined" name="passt" pid=1935 comm="apparmor_parser" type=SYSCALL msg=audit(1738501259.829:124): arch=c000003e syscall=1 success=yes exit=38258 a0=5 a1=564749519130 a2=9572 a3=0 items=0 ppid=1934 pid=1935 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=1 comm="apparmor_parser" exe="/usr/sbin/apparmor_parser" subj=unconfined key=(null)ARCH=x86_64 SYSCALL=write AUID="larryboy" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" type=PROCTITLE msg=audit(1738501259.829:124): proctitle=2F7362696E2F61707061726D6F725F706172736572002D492F6574632F61707061726D6F722E64002D2D62617365002F6574632F61707061726D6F722E64002D72002F6574632F61707061726D6F722E642F7573722E62696E2E7061737374 type=USER_END msg=audit(1738501259.837:125): pid=1931 uid=1000 auid=1000 ses=1 subj=unconfined msg='op=PAM:session_close grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=CRED_DISP msg=audit(1738501259.837:126): pid=1931 uid=1000 auid=1000 ses=1 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=USER_ACCT msg=audit(1738501267.430:127): pid=1937 uid=1000 auid=1000 ses=1 subj=unconfined msg='op=PAM:accounting grantors=pam_permit acct="larryboy" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" -- type=USER_START msg=audit(1738501267.430:130): pid=1937 uid=1000 auid=1000 ses=1 subj=unconfined msg='op=PAM:session_open grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=USER_END msg=audit(1738501267.430:131): pid=1937 uid=1000 auid=1000 ses=1 subj=unconfined msg='op=PAM:session_close grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=CRED_DISP msg=audit(1738501267.430:132): pid=1937 uid=1000 auid=1000 ses=1 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=BPF msg=audit(1738501309.002:133): prog-id=71 op=LOAD type=SERVICE_START msg=audit(1738501309.082:134): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='unit=polkit comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'UID="root" AUID="unset" type=AVC msg=audit(1738501309.118:135): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2030 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738501309.118:135): arch=c000003e syscall=59 success=no exit=-13 a0=7faf24035fc0 a1=7faf24035210 a2=7ffc063280d0 a3=0 items=0 ppid=1964 pid=2030 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=PROCTITLE msg=audit(1738501309.118:135): proctitle="(null)" type=ANOM_ABEND msg=audit(1738501309.118:136): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2030 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy" type=USER_ACCT msg=audit(1738501327.534:137): pid=2031 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='op=PAM:accounting grantors=pam_permit acct="larryboy" exe="/usr/lib/openssh/sshd-session" hostname=192.168.100.166 addr=192.168.100.166 terminal=ssh res=success'UID="root" AUID="unset" type=CRED_ACQ msg=audit(1738501327.538:138): pid=2031 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="larryboy" exe="/usr/lib/openssh/sshd-session" hostname=192.168.100.166 addr=192.168.100.166 terminal=ssh res=success'UID="root" AUID="unset" type=LOGIN msg=audit(1738501327.538:139): pid=2031 uid=0 subj=unconfined old-auid=4294967295 auid=1000 tty=(none) old-ses=4294967295 ses=3 res=1UID="root" OLD-AUID="unset" AUID="larryboy" type=SYSCALL msg=audit(1738501327.538:139): arch=c000003e syscall=1 success=yes exit=4 a0=5 a1=7ffdba6bed30 a2=4 a3=0 items=0 ppid=607 pid=2031 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=3 comm="sshd-session" exe="/usr/lib/openssh/sshd-session" subj=unconfined key=(null)ARCH=x86_64 SYSCALL=write AUID="larryboy" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" type=PROCTITLE msg=audit(1738501327.538:139): proctitle=737368642D73657373696F6E3A206C61727279626F79205B707269765D -- type=USER_AUTH msg=audit(1738501345.602:143): pid=2043 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:authentication grantors=pam_permit acct="larryboy" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=USER_ACCT msg=audit(1738501345.602:144): pid=2043 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:accounting grantors=pam_permit acct="larryboy" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=USER_CMD msg=audit(1738501345.602:145): pid=2043 uid=1000 auid=1000 ses=3 subj=unconfined msg='cwd="/home/larryboy" cmd=7461696C202D66202F7661722F6C6F672F61756469742F61756469742E6C6F67 exe="/usr/bin/sudo" terminal=pts/1 res=success'UID="larryboy" AUID="larryboy" type=CRED_REFR msg=audit(1738501345.602:146): pid=2043 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=USER_START msg=audit(1738501345.602:147): pid=2043 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:session_open grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=AVC msg=audit(1738501923.727:148): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2088 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738501923.727:148): arch=c000003e syscall=59 success=no exit=-13 a0=7ff564035d40 a1=7ff564039d00 a2=7fffe9aa1de0 a3=0 items=0 ppid=2060 pid=2088 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=PROCTITLE msg=audit(1738501923.727:148): proctitle="(null)" type=ANOM_ABEND msg=audit(1738501923.727:149): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2088 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy" type=SERVICE_START msg=audit(1738501960.339:150): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='unit=systemd-tmpfiles-clean comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'UID="root" AUID="unset" type=SERVICE_STOP msg=audit(1738501960.339:151): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='unit=systemd-tmpfiles-clean comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'UID="root" AUID="unset" type=USER_END msg=audit(1738502065.759:152): pid=2043 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:session_close grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=CRED_DISP msg=audit(1738502065.763:153): pid=2043 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=USER_ACCT msg=audit(1738502103.155:154): pid=2096 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:accounting grantors=pam_permit acct="larryboy" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" -- type=USER_CMD msg=audit(1738502295.487:169): pid=2106 uid=1000 auid=1000 ses=3 subj=unconfined msg='cwd="/home/larryboy" cmd=67726570207061737374202F7661722F6C6F672F61756469742F61756469742E6C6F67 exe="/usr/bin/sudo" terminal=pts/1 res=success'UID="larryboy" AUID="larryboy" type=CRED_REFR msg=audit(1738502295.487:170): pid=2106 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=USER_START msg=audit(1738502295.487:171): pid=2106 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:session_open grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=USER_END msg=audit(1738502295.491:172): pid=2106 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:session_close grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=CRED_DISP msg=audit(1738502295.491:173): pid=2106 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=AVC msg=audit(1738502301.651:174): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2145 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738502301.651:174): arch=c000003e syscall=59 success=no exit=-13 a0=7fe208034ce0 a1=7fe208034350 a2=7fffd2e60120 a3=0 items=0 ppid=2117 pid=2145 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=PROCTITLE msg=audit(1738502301.651:174): proctitle="(null)" type=ANOM_ABEND msg=audit(1738502301.651:175): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2145 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy" type=USER_ACCT msg=audit(1738502318.063:176): pid=2146 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:accounting grantors=pam_permit acct="larryboy" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=USER_CMD msg=audit(1738502318.063:177): pid=2146 uid=1000 auid=1000 ses=3 subj=unconfined msg='cwd="/home/larryboy" cmd=67726570207061737374202F7661722F6C6F672F61756469742F61756469742E6C6F67 exe="/usr/bin/sudo" terminal=pts/1 res=success'UID="larryboy" AUID="larryboy" type=CRED_REFR msg=audit(1738502318.063:178): pid=2146 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=USER_START msg=audit(1738502318.063:179): pid=2146 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:session_open grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" type=USER_END msg=audit(1738502318.063:180): pid=2146 uid=1000 auid=1000 ses=3 subj=unconfined msg='op=PAM:session_close grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="larryboy" AUID="larryboy" -- type=USER_AUTH msg=audit(1738507044.714:414): pid=3259 uid=1000 auid=1000 ses=30 subj=unconfined msg='op=PAM:authentication grantors=pam_permit acct="larryboy" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=USER_ACCT msg=audit(1738507044.714:415): pid=3259 uid=1000 auid=1000 ses=30 subj=unconfined msg='op=PAM:accounting grantors=pam_permit acct="larryboy" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=USER_CMD msg=audit(1738507044.714:416): pid=3259 uid=1000 auid=1000 ses=30 subj=unconfined msg='cwd="/home/larryboy" cmd=61612D64697361626C65202F6574632F61707061726D6F722E642F7573722E62696E2E7061737374 exe="/usr/bin/sudo" terminal=pts/0 res=success'UID="larryboy" AUID="larryboy" type=CRED_REFR msg=audit(1738507044.714:417): pid=3259 uid=1000 auid=1000 ses=30 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=USER_START msg=audit(1738507044.714:418): pid=3259 uid=1000 auid=1000 ses=30 subj=unconfined msg='op=PAM:session_open grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=AVC msg=audit(1738507044.818:419): apparmor="STATUS" operation="profile_remove" profile="unconfined" name="passt" pid=3263 comm="apparmor_parser" type=SYSCALL msg=audit(1738507044.818:419): arch=c000003e syscall=1 success=yes exit=6 a0=4 a1=7ffe35c30830 a2=6 a3=0 items=0 ppid=3262 pid=3263 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts2 ses=30 comm="apparmor_parser" exe="/usr/sbin/apparmor_parser" subj=unconfined key=(null)ARCH=x86_64 SYSCALL=write AUID="larryboy" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" type=PROCTITLE msg=audit(1738507044.818:419): proctitle=2F7362696E2F61707061726D6F725F706172736572002D492F6574632F61707061726D6F722E64002D2D62617365002F6574632F61707061726D6F722E64002D52002F6574632F61707061726D6F722E642F7573722E62696E2E7061737374 type=USER_END msg=audit(1738507044.830:420): pid=3259 uid=1000 auid=1000 ses=30 subj=unconfined msg='op=PAM:session_close grantors=pam_limits,pam_permit,pam_umask,pam_unix acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=CRED_DISP msg=audit(1738507044.830:421): pid=3259 uid=1000 auid=1000 ses=30 subj=unconfined msg='op=PAM:setcred grantors=pam_permit acct="root" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/0 res=success'UID="larryboy" AUID="larryboy" type=USER_END msg=audit(1738507343.621:422): pid=2482 uid=0 auid=1000 ses=12 subj=unconfined msg='op=PAM:session_close grantors=pam_selinux,pam_loginuid,pam_keyinit,pam_permit,pam_umask,pam_unix,pam_systemd,pam_mail,pam_limits,pam_env,pam_env,pam_selinux acct="larryboy" exe="/usr/lib/openssh/sshd-session" hostname=192.168.100.166 addr=192.168.100.166 terminal=ssh res=success'UID="root" AUID="larryboy"$ ./pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org # On Debian Trixie, dns.pcap attached 0.0002: No interfaces with usable IPv6 routes 0.0002: Failed to detect external interface for IPv6 0.0035: Template interface: enp1s0 (IPv4) 0.0035: Namespace interface: enp1s0 0.0035: MAC: 0.0035: host: 9a:55:9a:55:9a:55 0.0035: NAT to host 127.0.0.1: 192.168.100.1 0.0036: DHCP: 0.0036: assign: 192.168.100.157 0.0036: mask: 255.255.255.0 0.0036: router: 192.168.100.1 0.0036: DNS: 0.0036: 192.168.100.1 0.0036: DNS search list: 0.0036: . 0.0204: SO_PEEK_OFF supported 0.0204: TCP_INFO tcpi_snd_wnd field supported 0.0205: TCP_INFO tcpi_bytes_acked field supported 0.0205: TCP_INFO tcpi_min_rtt field supported 0.0205: Saving packet capture to /tmp/dns.pcap 0.0281: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0413: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0414: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0414: tap: protocol 17, 192.168.100.157:56205 -> 192.168.100.1:53 (1 packet) 0.0415: Flow 0 (NEW): FREE -> NEW 0.0415: Flow 0 (INI): NEW -> INI 0.0415: Flow 0 (INI): TAP [192.168.100.157]:56205 -> [192.168.100.1]:53 => ? 0.0416: Flow 0 (TGT): INI -> TGT 0.0416: Flow 0 (TGT): TAP [192.168.100.157]:56205 -> [192.168.100.1]:53 => HOST [0.0.0.0]:56205 -> [192.168.100.1]:53 0.0416: Flow 0 (UDP flow): TGT -> TYPED 0.0416: Flow 0 (UDP flow): TAP [192.168.100.157]:56205 -> [192.168.100.1]:53 => HOST [0.0.0.0]:56205 -> [192.168.100.1]:53 0.0417: Flow 0 (UDP flow): Side 0 hash table insert: bucket: 121236 0.0417: Flow 0 (UDP flow): TYPED -> ACTIVE 0.0417: Flow 0 (UDP flow): TAP [192.168.100.157]:56205 -> [192.168.100.1]:53 => HOST [0.0.0.0]:56205 -> [192.168.100.1]:53 0.3059: pasta: epoll event on UDP reply socket 96 (events: 0x00000001) 0.3059: Flow 0 (UDP flow): Received 1 datagrams on reply socket Server: 192.168.100.1 Address: 192.168.100.1#53 Non-authoritative answer: Name: fsf.org Address: 209.51.188.174 0.3173: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.3175: tap: protocol 17, 192.168.100.157:50006 -> 192.168.100.1:53 (1 packet) 0.3175: Flow 1 (NEW): FREE -> NEW 0.3176: Flow 1 (INI): NEW -> INI 0.3177: Flow 1 (INI): TAP [192.168.100.157]:50006 -> [192.168.100.1]:53 => ? 0.3177: Flow 1 (TGT): INI -> TGT 0.3178: Flow 1 (TGT): TAP [192.168.100.157]:50006 -> [192.168.100.1]:53 => HOST [0.0.0.0]:50006 -> [192.168.100.1]:53 0.3179: Flow 1 (UDP flow): TGT -> TYPED 0.3179: Flow 1 (UDP flow): TAP [192.168.100.157]:50006 -> [192.168.100.1]:53 => HOST [0.0.0.0]:50006 -> [192.168.100.1]:53 0.3181: Flow 1 (UDP flow): Side 0 hash table insert: bucket: 167789 0.3182: Flow 1 (UDP flow): TYPED -> ACTIVE 0.3183: Flow 1 (UDP flow): TAP [192.168.100.157]:50006 -> [192.168.100.1]:53 => HOST [0.0.0.0]:50006 -> [192.168.100.1]:53 0.3406: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 1.3645: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 1.7900: pasta: epoll event on UDP reply socket 97 (events: 0x00000001) 1.7903: Flow 1 (UDP flow): Received 1 datagrams on reply socket Name: fsf.org Address: 2001:470:142:4::a> > $ passt -f -d # on Debian Testing/Trixie > > 0.0016: No interfaces with usable IPv6 routes > > 0.0017: Failed to detect external interface for IPv6 > > 0.0028: UNIX domain socket bound at /tmp/passt_1.socket > > 0.0029: Template interface: enp1s0 (IPv4) > > 0.0029: MAC: > > 0.0029: host: 9a:55:9a:55:9a:55 > > 0.0029: NAT to host 127.0.0.1: 192.168.100.1 > > 0.0029: DHCP: > > 0.0029: assign: 192.168.100.157 > > 0.0029: mask: 255.255.255.0 > > 0.0029: router: 192.168.100.1 > > 0.0029: DNS: > > 0.0029: 192.168.100.1 > > So, judging from this configuration, it looks like we advertise to > the guest (via DHCP) 192.168.100.1 as resolver (copied from the host), > and when we receive packets from the guest for 192.168.100.1, we'll > re-map them to the host. > > Nothing strange so far, systemd-resolved is running on the host, it > should get our queries and reply to them. > > > $ cat /etc/resolv.conf # On Debian Trixie > > # This is /run/systemd/resolve/resolv.conf managed by > > man:systemd-resolved(8). [...] > > nameserver 192.168.100.1 > > search . > > $ cat /etc/resolv.conf # On a Debian 11 OS > > # Generated by NetworkManager > > nameserver 192.168.100.1 > > > > Also the output of `resolvectl status` for good measure: > > # On Fedora 41 > > Global > > Protocols: LLMNR=resolve -mDNS -DNSOverTLS > > DNSSEC=no/unsupported resolv.conf mode: stub > > > > Link 2 (wlp0s20f3) > > Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 > > Protocols: +DefaultRoute LLMNR=resolve -mDNS -DNSOverTLS > > DNSSEC=no/unsupported Current DNS Server: 192.168.100.1 > > DNS Servers: 192.168.100.1 > > > > # On Debian Trixie > > Global > > Protocols: +LLMNR +mDNS -DNSOverTLS DNSSEC=no/unsupported > > resolv.conf mode: uplink > > > > Link 2 (enp1s0) > > Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6 > > Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS > > DNSSEC=no/unsupported DNS Servers: 192.168.100.1 > > Default Route: yes > > Everything as expected here, I don't see any obvious reason why > systemd-resolved should discard our queries. > > > The log from Debian Trixie host for VM1: > > passt 0.0~git20250121.4f2c8e7-1: /usr/bin/passt.avx2 (6428) > > 0.0017: info: No interfaces with usable IPv6 routes > > 0.0029: info: UNIX domain socket bound at > > /run/user/1000/libvirt/qemu/run/passt/2-vm1-net0.socket 0.0030: info: > > Template interface: enp1s0 (IPv4) 0.0030: info: MAC: > > 0.0030: info: host: 9a:55:9a:55:9a:55 > > 0.0030: info: NAT to host 127.0.0.1: 192.168.100.1 > > 0.0030: info: DHCP: > > 0.0031: info: assign: 192.168.100.157 > > 0.0031: info: mask: 255.255.255.0 > > 0.0031: info: router: 192.168.100.1 > > 0.0031: info: DNS: > > 0.0031: info: 192.168.100.1 > > 0.0031: info: DNS search list: > > 0.0031: info: . > > 0.0066: info: > > You can now start qemu (>= 7.2, with commit 13c6be96618c): > > 0.0066: info: kvm ... -device virtio-net-pci,netdev=s -netdev > > stream,id=s,server=off,addr.type=unix,addr.path=/run/user/1000/libvirt/qemu/run/passt/2-vm1-net0.socket > > 0.0066: info: or qrap, for earlier qemu versions: 0.0066: info: > > ./qrap 5 kvm ... -net socket,fd=5 -net nic,model=virtio 0.0617: > > info: accepted connection from PID 0 38.6257: info: DHCP: offer > > to discover 38.6257: info: from 52:54:00:a0:e1:7c > > 38.6471: info: DHCP: ack to request > > 38.6471: info: from 52:54:00:a0:e1:7c > > 451.4989: info: Client connection closed, exiting > > Unfortunately libvirt doesn't let us enable more verbose logging. I > hoped to see DNS queries there, but without --debug given to passt, > that won't work. > > Another idea: pasta(1) does the same job as passt(1) (it's the same > code and same binary) and it's intended for containers, but it has a > stand-alone mode that can probably help us to debug this, because it's > a network namespace that will look like your guest, and it can also > take packet captures. > > What happens if you run: > > pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org > > ? > This one errors out. dns.pcap is attached. > $ pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org # Debian Trixie/Testing > 0.0015: No interfaces with usable IPv6 routes > 0.0015: Failed to detect external interface for IPv6 > 0.0073: Template interface: enp1s0 (IPv4) > 0.0073: Namespace interface: enp1s0 > 0.0074: MAC: > 0.0074: host: 9a:55:9a:55:9a:55 > 0.0074: NAT to host 127.0.0.1: 192.168.100.1 > 0.0074: DHCP: > 0.0074: assign: 192.168.100.157 > 0.0074: mask: 255.255.255.0 > 0.0075: router: 192.168.100.1 > 0.0075: DNS: > 0.0075: 192.168.100.1 > 0.0076: DNS search list: > 0.0076: . > 0.0146: SO_PEEK_OFF supported > 0.0146: TCP_INFO tcpi_snd_wnd field supported > 0.0146: TCP_INFO tcpi_bytes_acked field supported > 0.0146: TCP_INFO tcpi_min_rtt field supported > 0.0147: Saving packet capture to /tmp/dns.pcap > 0.0197: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) > 0.0371: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) > 0.0372: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) > 0.0372: tap: protocol 17, 192.168.100.157:41892 -> 192.168.100.1:53 (1 packet) > 0.0372: Flow 0 (NEW): FREE -> NEW > 0.0372: Flow 0 (INI): NEW -> INI > 0.0372: Flow 0 (INI): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => ? > 0.0372: Flow 0 (TGT): INI -> TGT > 0.0373: Flow 0 (TGT): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => HOST [0.0.0.0]:41892 -> [127.0.0.1]:53 > 0.0373: Flow 0 (UDP flow): TGT -> TYPED > 0.0373: Flow 0 (UDP flow): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => HOST [0.0.0.0]:41892 -> [127.0.0.1]:53 > 0.0373: Flow 0 (UDP flow): Side 0 hash table insert: bucket: 31049 > 0.0374: Flow 0 (UDP flow): TYPED -> ACTIVE > 0.0374: Flow 0 (UDP flow): TAP [192.168.100.157]:41892 -> [192.168.100.1]:53 => HOST [0.0.0.0]:41892 -> [127.0.0.1]:53 > 0.0374: pasta: epoll event on UDP reply socket 95 (events: 0x00000008) > 0.0374: ICMP error on UDP socket 95: Connection refusedOuch. I just sent a patch for this, you can test it by checking out passt locally: git clone git://passt.top/passt; cd passt applying it (you might need to install 'b4'): b4 shazam https://archives.passt.top/passt-dev/20250203082210.2114348-1-sbrivio@redha… then: make and ./pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.orgYou can also install it to /usr/local with 'make install', it's just a couple of files and will uninstall cleanly with 'make uninstall' if needed. Note that AppArmor profiles don't apply to binaries under /usr/local/bin.# Apparmor is enabled $ virsh start --domain vm1 # Debian-supplied `passt` error: Failed to start domain 'vm1' error: internal error: Child process (passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/3-vm1-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/3-vm1-net0-passt.pid --log-file /tmp/vm-1-passt.log) unexpected fatal signal 11 $ $ virsh start --domain vm1 # `make install`-ed `passt` error: Failed to start domain 'vm1' error: internal error: Child process (passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/4-vm1-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/4-vm1-net0-passt.pid --log-file /tmp/vm-1-passt.log) unexpected exit status 126: libvirt: error : cannot execute binary passt: Permission denied Just a side note, once these issues are resolved, please don't hesitate to ping me to test things out on Debian: this has been horizon-broadening. I never knew about b4 and stuff. Pretty awesome stuff!
On Tue, 04 Feb 2025 08:21:53 +0000 Prafulla Giri <prafulla.giri(a)protonmail.com> wrote:type=SERVICE_START msg=audit(1738501309.082:134): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='unit=polkit comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'UID="root" AUID="unset" type=AVC msg=audit(1738501309.118:135): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2030 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738501309.118:135): arch=c000003e syscall=59 success=no exit=-13 a0=7faf24035fc0 a1=7faf24035210 a2=7ffc063280d0 a3=0 items=0 ppid=1964 pid=2030 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=PROCTITLE msg=audit(1738501309.118:135): proctitle="(null)" type=ANOM_ABEND msg=audit(1738501309.118:136): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2030 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy"So, it looks like passt is running as its own profile. This shouldn't happen because the libvirt profile has an own subprofile and we should see that in "profile" on the type=AVC line but... I just reproduced this! Clean Debian sid install, fresh install of libvirtd: error: internal error: Child process (passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0-passt.pid --tcp-ports 40922:22) unexpected fatal signal 11 I'll keep you posted.Okay, at least the DNS issue is fixed. I'll apply the fix in a moment, it will be available in an updated package in a while. -- Stefanohttps://archives.passt.top/passt-dev/20250203082210.2114348-1-sbrivio@redha… then: make and ./pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org$ ./pasta --config-net --trace --pcap /tmp/dns.pcap -- nslookup fsf.org # On Debian Trixie, dns.pcap attached 0.0002: No interfaces with usable IPv6 routes 0.0002: Failed to detect external interface for IPv6 0.0035: Template interface: enp1s0 (IPv4) 0.0035: Namespace interface: enp1s0 0.0035: MAC: 0.0035: host: 9a:55:9a:55:9a:55 0.0035: NAT to host 127.0.0.1: 192.168.100.1 0.0036: DHCP: 0.0036: assign: 192.168.100.157 0.0036: mask: 255.255.255.0 0.0036: router: 192.168.100.1 0.0036: DNS: 0.0036: 192.168.100.1 0.0036: DNS search list: 0.0036: . 0.0204: SO_PEEK_OFF supported 0.0204: TCP_INFO tcpi_snd_wnd field supported 0.0205: TCP_INFO tcpi_bytes_acked field supported 0.0205: TCP_INFO tcpi_min_rtt field supported 0.0205: Saving packet capture to /tmp/dns.pcap 0.0281: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0413: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0414: pasta: epoll event on /dev/net/tun device 16 (events: 0x00000001) 0.0414: tap: protocol 17, 192.168.100.157:56205 -> 192.168.100.1:53 (1 packet) 0.0415: Flow 0 (NEW): FREE -> NEW 0.0415: Flow 0 (INI): NEW -> INI 0.0415: Flow 0 (INI): TAP [192.168.100.157]:56205 -> [192.168.100.1]:53 => ? 0.0416: Flow 0 (TGT): INI -> TGT 0.0416: Flow 0 (TGT): TAP [192.168.100.157]:56205 -> [192.168.100.1]:53 => HOST [0.0.0.0]:56205 -> [192.168.100.1]:53 0.0416: Flow 0 (UDP flow): TGT -> TYPED 0.0416: Flow 0 (UDP flow): TAP [192.168.100.157]:56205 -> [192.168.100.1]:53 => HOST [0.0.0.0]:56205 -> [192.168.100.1]:53 0.0417: Flow 0 (UDP flow): Side 0 hash table insert: bucket: 121236 0.0417: Flow 0 (UDP flow): TYPED -> ACTIVE 0.0417: Flow 0 (UDP flow): TAP [192.168.100.157]:56205 -> [192.168.100.1]:53 => HOST [0.0.0.0]:56205 -> [192.168.100.1]:53 0.3059: pasta: epoll event on UDP reply socket 96 (events: 0x00000001) 0.3059: Flow 0 (UDP flow): Received 1 datagrams on reply socket Server: 192.168.100.1 Address: 192.168.100.1#53 Non-authoritative answer: Name: fsf.org Address: 209.51.188.174
On Tue, Feb 04, 2025 at 09:50:00AM +0100, Stefano Brivio wrote:On Tue, 04 Feb 2025 08:21:53 +0000 Prafulla Giri <prafulla.giri(a)protonmail.com> wrote:I've skimmed the conversation trying to understand whether there's anything that I need do from the libvirt side, but AFAICT no explicit action has been called for so far. It looks like you're making good progress in figuring out what's going on. Being able to reproduce the issue yourself is certainly going to help. I'm happy to leave all the debugging to you, since as you know I'm not very good at the AppArmor stuff and I'm really, really bad at the networking stuff ;) Once a clearer picture emerges, if it turns out that changes are needed in either libvirt or its Debian packaging, I can definitely look into making that happen. -- Andrea Bolognani / Red Hat / Virtualizationtype=SERVICE_START msg=audit(1738501309.082:134): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='unit=polkit comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'UID="root" AUID="unset" type=AVC msg=audit(1738501309.118:135): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2030 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738501309.118:135): arch=c000003e syscall=59 success=no exit=-13 a0=7faf24035fc0 a1=7faf24035210 a2=7ffc063280d0 a3=0 items=0 ppid=1964 pid=2030 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=PROCTITLE msg=audit(1738501309.118:135): proctitle="(null)" type=ANOM_ABEND msg=audit(1738501309.118:136): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2030 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy"So, it looks like passt is running as its own profile. This shouldn't happen because the libvirt profile has an own subprofile and we should see that in "profile" on the type=AVC line but... I just reproduced this! Clean Debian sid install, fresh install of libvirtd: error: internal error: Child process (passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0-passt.pid --tcp-ports 40922:22) unexpected fatal signal 11 I'll keep you posted.
On Tue, 4 Feb 2025 09:50:40 +0000 Andrea Bolognani <abologna(a)redhat.com> wrote:On Tue, Feb 04, 2025 at 09:50:00AM +0100, Stefano Brivio wrote:Not yet, because I was hoping to figure out what's going on, but I'm actually (almost?) stuck now. I don't think this is the same as https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1094583 by the way, because: $ find /etc/apparmor.d/ -ls | grep -i virt 148926 4 drwxr-xr-x 2 root root 4096 Feb 4 08:44 /etc/apparmor.d/libvirt 148927 4 -rw-r--r-- 1 root root 192 Jan 15 08:06 /etc/apparmor.d/libvirt/TEMPLATE.qemu 149882 4 -rw-r--r-- 1 root root 342 Jan 15 08:06 /etc/apparmor.d/libvirt/TEMPLATE.lxc 6098 8 -rw-r--r-- 1 root root 4780 Jan 30 22:47 /etc/apparmor.d/usr.sbin.libvirtd 20741 0 -rw-r--r-- 1 root root 0 Feb 4 08:44 /etc/apparmor.d/local/usr.sbin.libvirtd 20572 0 -rw-r--r-- 1 root root 0 Feb 4 08:44 /etc/apparmor.d/local/usr.lib.libvirt.virt-aa-helper 6826 12 -rw-r--r-- 1 root root 9258 Jan 30 22:47 /etc/apparmor.d/abstractions/libvirt-qemu 20662 8 -rw-r--r-- 1 root root 4610 Jan 30 22:47 /etc/apparmor.d/abstractions/libvirt-lxc 6099 4 -rw-r--r-- 1 root root 1898 Jan 30 22:47 /etc/apparmor.d/usr.lib.libvirt.virt-aa-helper $ find /etc/libvirt/ -ls | grep -i conf find: '/etc/libvirt/secrets': Permission denied 268888 20 -rw-r--r-- 1 root root 17826 Jan 30 22:47 /etc/libvirt/libvirtd.conf 269240 4 -rw-r--r-- 1 root root 2169 Jan 30 22:47 /etc/libvirt/libxl-lockd.conf 324760 4 -rw-r--r-- 1 root root 547 Nov 1 09:13 /etc/libvirt/libvirt.conf 269243 4 -rw-r--r-- 1 root root 3058 Jan 15 08:06 /etc/libvirt/virtlockd.conf 263460 4 -rw-r--r-- 1 root root 2465 Jan 30 22:47 /etc/libvirt/qemu-sanlock.conf 263459 4 -rw-r--r-- 1 root root 2169 Jan 30 22:47 /etc/libvirt/qemu-lockd.conf 269238 4 -rw-r--r-- 1 root root 1175 Jan 15 08:06 /etc/libvirt/lxc.conf 324759 4 -rw-r--r-- 1 root root 450 Nov 1 09:13 /etc/libvirt/libvirt-admin.conf 269241 4 -rw-r--r-- 1 root root 2465 Jan 30 22:47 /etc/libvirt/libxl-sanlock.conf 269242 4 -rw-r--r-- 1 root root 2268 Jan 15 08:06 /etc/libvirt/libxl.conf 263461 40 -rw------- 1 root root 39106 Jan 30 22:47 /etc/libvirt/qemu.conf 262245 4 -rw-r--r-- 1 root root 4095 Jan 15 08:06 /etc/libvirt/virtlogd.conf 268889 4 -rw-r--r-- 1 root root 1041 Jan 30 22:47 /etc/libvirt/network.confOn Tue, 04 Feb 2025 08:21:53 +0000 Prafulla Giri <prafulla.giri(a)protonmail.com> wrote:I've skimmed the conversation trying to understand whether there's anything that I need do from the libvirt side, but AFAICT no explicit action has been called for so far.type=SERVICE_START msg=audit(1738501309.082:134): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=unconfined msg='unit=polkit comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'UID="root" AUID="unset" type=AVC msg=audit(1738501309.118:135): apparmor="DENIED" operation="file_mmap" class="file" profile="passt" name="/usr/bin/passt" pid=2030 comm="passt" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0FSUID="larryboy" OUID="root" type=SYSCALL msg=audit(1738501309.118:135): arch=c000003e syscall=59 success=no exit=-13 a0=7faf24035fc0 a1=7faf24035210 a2=7ffc063280d0 a3=0 items=0 ppid=1964 pid=2030 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=(none) ses=1 comm="passt" exe="/usr/bin/passt" subj=passt key=(null)ARCH=x86_64 SYSCALL=execve AUID="larryboy" UID="larryboy" GID="larryboy" EUID="larryboy" SUID="larryboy" FSUID="larryboy" EGID="larryboy" SGID="larryboy" FSGID="larryboy" type=PROCTITLE msg=audit(1738501309.118:135): proctitle="(null)" type=ANOM_ABEND msg=audit(1738501309.118:136): auid=1000 uid=1000 gid=1000 ses=1 subj=passt pid=2030 comm="passt" exe="/usr/bin/passt" sig=11 res=1AUID="larryboy" UID="larryboy" GID="larryboy"So, it looks like passt is running as its own profile. This shouldn't happen because the libvirt profile has an own subprofile and we should see that in "profile" on the type=AVC line but... I just reproduced this! Clean Debian sid install, fresh install of libvirtd: error: internal error: Child process (passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0-passt.pid --tcp-ports 40922:22) unexpected fatal signal 11 I'll keep you posted.It looks like you're making good progress in figuring out what's going on. Being able to reproduce the issue yourself is certainly going to help. I'm happy to leave all the debugging to you, since as you know I'm not very good at the AppArmor stuff and I'm really, really bad at the networking stuff ;)...no, wait, I'm still failing to understand the bigger picture of what happens AppArmor-wise when I do 'virsh start something'. :) This is really pretty simple: fresh Debian sid image, all packages updated to today. Then: virt-install -d --name alpine --memory 1024 --noreboot --osinfo alpinelinux3.20 --network backend.type=passt,portForward0.proto=tcp,portForward0.range0.start=40922,portForward0.range0.to=22 --import --disk nocloud_alpine-3.21.2-x86_64-bios-tiny-r0.qcow2 this works. But: $ virsh start alpine error: Failed to start domain 'alpine' error: internal error: Child process (passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0-passt.pid --tcp-ports 40922:2) unexpected fatal signal 11 execve() of passt is denied by AppArmor. Starting passt on its own (passt -f) works, instead. At this point, which libvirtd (?) process should associate with which libvirtd profile? Once that's clear to me, I can probably debug further. I can also give you access to the machine if needed.Once a clearer picture emerges, if it turns out that changes are needed in either libvirt or its Debian packaging, I can definitely look into making that happen.I'm fairly sure it's libvirt, because I didn't change anything substantial in passt, and it's anyway the AppArmor profile for libvirtd that seems to be... missing? And yet it's there. -- Stefano
On Tue, Feb 04, 2025 at 11:17:24AM +0100, Stefano Brivio wrote:On Tue, 4 Feb 2025 09:50:40 +0000 Andrea Bolognani <abologna(a)redhat.com> wrote:That issue can only manifest itself when upgrading from bookworm, so if you have performed a fresh install of sid you don't need to worry about it.I've skimmed the conversation trying to understand whether there's anything that I need do from the libvirt side, but AFAICT no explicit action has been called for so far.Not yet, because I was hoping to figure out what's going on, but I'm actually (almost?) stuck now. I don't think this is the same as https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1094583 by the way,This is really pretty simple: fresh Debian sid image, all packages updated to today. Then: virt-install -d --name alpine --memory 1024 --noreboot --osinfo alpinelinux3.20 --network backend.type=passt,portForward0.proto=tcp,portForward0.range0.start=40922,portForward0.range0.to=22 --import --disk nocloud_alpine-3.21.2-x86_64-bios-tiny-r0.qcow2 this works. But: $ virsh start alpine error: Failed to start domain 'alpine' error: internal error: Child process (passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0-passt.pid --tcp-ports 40922:2) unexpected fatal signal 11 execve() of passt is denied by AppArmor. Starting passt on its own (passt -f) works, instead.I was initially very surprised to read this, but it makes sense after spending some more time looking into it. Normally, virt-install will perform guest creation in two phases. The first one is the installation itself, which needs the install media to be connected; once that's done, the OS installer will usually initiate a reboot, and when the VM comes up again the installl media will no longer be connected. Other changes to the configuration might happen as well, I'm not 100% sure. Anyway, since you've passed --noreboot above, virt-install will only go through the first phase of installing the guest; additionally, since you've passed --import, the VM will only be defined and the installation will be considered done without having to start it once. As a counter-example, see how the behavior changes when performing a "regular" install from CDROM instead: $ virt-install --name alpine --memory 1024 --osinfo alpinelinux3.20 \ --network backend.type=passt --graphics none --disk none \ --cdrom ./alpine-virt-3.21.2-x86_64.iso Starting install... ERROR internal error: Child process (passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/3-alpine-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/3-alpine-net0-passt.pid) unexpected fatal signal 11 So there's no magic to that first VM start that apparently worked even when subsequent ones wouldn't. The VM start simply didn't happen in the first place.At this point, which libvirtd (?) process should associate with which libvirtd profile? Once that's clear to me, I can probably debug further.[...]I'm fairly sure it's libvirt, because I didn't change anything substantial in passt, and it's anyway the AppArmor profile for libvirtd that seems to be... missing? And yet it's there.We're going back to the question of how AppArmor works for unprivileged VMs... The short answer is that I'm not convinced it does. In order to make a direct comparison, I've create the very same Alpine VM, with no network interface, both on qemu:///system and qemu:///user. When I start the former, the (filtered) output for aa-status goes from 22 profiles are in enforce mode. libvirtd libvirtd//qemu_bridge_helper virt-aa-helper 25 profiles are in complain mode. dnsmasq//libvirt_leaseshelper 2 processes are in enforce mode. /usr/sbin/libvirtd (862) libvirtd to 24 profiles are in enforce mode. libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4//passt libvirtd libvirtd//qemu_bridge_helper virt-aa-helper 25 profiles are in complain mode. dnsmasq//libvirt_leaseshelper 3 processes are in enforce mode. /usr/bin/qemu-system-x86_64 (1310) libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 /usr/sbin/libvirtd (862) libvirtd The additional profiles (libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 and its passt subprofile) are generated dynamically when the VM is started and the QEMU process gets the correct one assigned to it. So far so good. After launching the qemu:///session VM, however, the situation is a lot different: 22 profiles are in enforce mode. libvirtd libvirtd//qemu_bridge_helper virt-aa-helper 25 profiles are in complain mode. dnsmasq//libvirt_leaseshelper 4 processes are in enforce mode. /usr/sbin/libvirtd (1589) libvirtd /usr/sbin/virtlogd (1632) libvirtd As you can see, the per-VM profile hasn't been created, and so obviously it couldn't be applied to the QEMU process either. This is probably undesirable, but at the same time I'm not really sure how it could be fixed. Creating a new profile requires dropping a file in /etc/apparmor.d/libvirt, and the unprivileged libvirtd intentionally doesn't have the necessary permissions to do that... Do you have any ideas? -- Andrea Bolognani / Red Hat / Virtualization
On Tue, 4 Feb 2025 15:50:43 +0000 Andrea Bolognani <abologna(a)redhat.com> wrote:On Tue, Feb 04, 2025 at 11:17:24AM +0100, Stefano Brivio wrote:Ah, sure, sorry! I didn't mean to waste your time with that, it was clear to me that passt doesn't start there... I just wanted to show the setup.On Tue, 4 Feb 2025 09:50:40 +0000 Andrea Bolognani <abologna(a)redhat.com> wrote:That issue can only manifest itself when upgrading from bookworm, so if you have performed a fresh install of sid you don't need to worry about it.I've skimmed the conversation trying to understand whether there's anything that I need do from the libvirt side, but AFAICT no explicit action has been called for so far.Not yet, because I was hoping to figure out what's going on, but I'm actually (almost?) stuck now. I don't think this is the same as https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1094583 by the way,This is really pretty simple: fresh Debian sid image, all packages updated to today. Then: virt-install -d --name alpine --memory 1024 --noreboot --osinfo alpinelinux3.20 --network backend.type=passt,portForward0.proto=tcp,portForward0.range0.start=40922,portForward0.range0.to=22 --import --disk nocloud_alpine-3.21.2-x86_64-bios-tiny-r0.qcow2 this works. But: $ virsh start alpine error: Failed to start domain 'alpine' error: internal error: Child process (passt --one-off --socket /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0.socket --pid /run/user/1000/libvirt/qemu/run/passt/1-alpine-net0-passt.pid --tcp-ports 40922:2) unexpected fatal signal 11 execve() of passt is denied by AppArmor. Starting passt on its own (passt -f) works, instead.I was initially very surprised to read this, but it makes sense after spending some more time looking into it.[...] So there's no magic to that first VM start that apparently worked even when subsequent ones wouldn't. The VM start simply didn't happen in the first place.Why do we need additional profiles, I wonder? Are we trying to replicate the MCS (Multi-Category Security) stuff from SELinux?At this point, which libvirtd (?) process should associate with which libvirtd profile? Once that's clear to me, I can probably debug further.[...]I'm fairly sure it's libvirt, because I didn't change anything substantial in passt, and it's anyway the AppArmor profile for libvirtd that seems to be... missing? And yet it's there.We're going back to the question of how AppArmor works for unprivileged VMs... The short answer is that I'm not convinced it does. In order to make a direct comparison, I've create the very same Alpine VM, with no network interface, both on qemu:///system and qemu:///user. When I start the former, the (filtered) output for aa-status goes from 22 profiles are in enforce mode. libvirtd libvirtd//qemu_bridge_helper virt-aa-helper 25 profiles are in complain mode. dnsmasq//libvirt_leaseshelper 2 processes are in enforce mode. /usr/sbin/libvirtd (862) libvirtd to 24 profiles are in enforce mode. libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4//passt libvirtd libvirtd//qemu_bridge_helper virt-aa-helper 25 profiles are in complain mode. dnsmasq//libvirt_leaseshelper 3 processes are in enforce mode. /usr/bin/qemu-system-x86_64 (1310) libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 /usr/sbin/libvirtd (862) libvirtd The additional profiles (libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 and its passt subprofile) are generated dynamically when the VM is started and the QEMU process gets the correct one assigned to it. So far so good.After launching the qemu:///session VM, however, the situation is a lot different: 22 profiles are in enforce mode. libvirtd libvirtd//qemu_bridge_helper virt-aa-helper 25 profiles are in complain mode. dnsmasq//libvirt_leaseshelper 4 processes are in enforce mode. /usr/sbin/libvirtd (1589) libvirtd /usr/sbin/virtlogd (1632) libvirtd As you can see, the per-VM profile hasn't been created, and so obviously it couldn't be applied to the QEMU process either.Oh, now I understand the whole "template" thing finally! And now that you mention virt-aa-helper (I wasn't aware of that) I also found: https://gitlab.com/apparmor/apparmor/-/wikis/Libvirt Yes, of course, that won't work unless you're root.This is probably undesirable, but at the same time I'm not really sure how it could be fixed.If I understood the purpose correctly: implementing equivalent MCS functionality in AppArmor would probably be the only "complete" fix. But for the moment (or more realistically):Creating a new profile requires dropping a file in /etc/apparmor.d/libvirt, and the unprivileged libvirtd intentionally doesn't have the necessary permissions to do that...Profiles could reside in other places too, but they won't be associated "just like that". A privileged helper could... help. But if users can edit their own profiles in their homes, that defies a bit the point of AppArmor profiles altogether.Do you have any ideas?Probably you should ask somebody more familiar (openSUSE/Ubuntu maintainers of libvirt, or the authors of the virt-aa-helper thing?), but a couple of quick ideas: 1. user-specific subprofiles could be added at adduser time (is there a hook?) and libvirtd could use aa_change_hat(2) to select the appropriate one based on UID 2. (most reasonable I think) don't use per-VM profiles for the rootless case. Define a single "libvirt-user" (or "libvirt-session") profile and use that. We could copy it from the existing ones I suppose. I think that MCS-equivalent functionality is anyway much less critical if guests are started as unprivileged users because you have a strong separation given by the fact that guests are started as different users. If all the guests are started as root, and multiple users have access to that facility, user separation is much more seriously endangered, hence a stronger need for per-VM profiles. And, stating the obvious, it's counterproductive to force users to run guests as root because we can't have that kind of functionality. By the way, I recently happened to introduce an AppArmor profile for guestfs-tools: https://salsa.debian.org/libvirt-team/guestfs-tools/-/merge_requests/1 there are no separate profiles, there. I can try to work on this but I'm really a bit too busy right now. If you can, great, otherwise, let me know. On the other hand this feels pretty urgent. :( -- Stefano
On Tue, Feb 04, 2025 at 05:22:42PM +0100, Stefano Brivio wrote:On Tue, 4 Feb 2025 15:50:43 +0000 Andrea Bolognani <abologna(a)redhat.com> wrote:I'm not well-versed enough in SELinux to be able to answer the latter question, but I can answer the former. The per-VM profile is needed to ensure that each VM is only granted access to its own resources. $ sudo tail -4 /etc/apparmor.d/libvirt/libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 profile libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 flags=(attach_disconnected) { #include <abstractions/libvirt-qemu> #include if exists <libvirt/libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4.files> } $ sudo cat /etc/apparmor.d/libvirt/libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4.files "/var/log/libvirt/**/alpine.log" w, "/var/lib/libvirt/qemu/domain-alpine/monitor.sock" rw, "/var/lib/libvirt/qemu/domain-1-alpine/*" rw, "/run/libvirt/**/alpine.pid" rwk, "/run/libvirt/**/*.tunnelmigrate.dest.alpine" rw, "/var/lib/libvirt/images/alpine.qcow2" rwk, "/var/lib/libvirt/qemu/domain-1-alpine/{,**}" rwk, "/run/libvirt/qemu/channel/1-alpine/{,**}" rwk, "/var/lib/libvirt/qemu/domain-1-alpine/master-key.aes" rwk, "/dev/userfaultfd" rwk, The stuff in the libvirt-qemu abstraction is generic, all VMs get access to it. The stuff in .files is all specific to the VM.The additional profiles (libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 and its passt subprofile) are generated dynamically when the VM is started and the QEMU process gets the correct one assigned to it. So far so good.Why do we need additional profiles, I wonder? Are we trying to replicate the MCS (Multi-Category Security) stuff from SELinux?Sounds to me like this would require granting the QEMU process access to roughly the entire filesystem? The disk image could live anywhere after all, and if we can't dynamically add a rule for the exact path the only way out is a free-for-all approach.Do you have any ideas?Probably you should ask somebody more familiar (openSUSE/Ubuntu maintainers of libvirt, or the authors of the virt-aa-helper thing?), but a couple of quick ideas: 1. user-specific subprofiles could be added at adduser time (is there a hook?) and libvirtd could use aa_change_hat(2) to select the appropriate one based on UID 2. (most reasonable I think) don't use per-VM profiles for the rootless case. Define a single "libvirt-user" (or "libvirt-session") profile and use that. We could copy it from the existing ones I suppose.I think that MCS-equivalent functionality is anyway much less critical if guests are started as unprivileged users because you have a strong separation given by the fact that guests are started as different users. If all the guests are started as root, and multiple users have access to that facility, user separation is much more seriously endangered, hence a stronger need for per-VM profiles.Ideally you'd still want to isolate unprivileged VMs from each other. If you don't, what's the point of using AppArmor in the first place?I can try to work on this but I'm really a bit too busy right now. If you can, great, otherwise, let me know. On the other hand this feels pretty urgent. :(I'm afraid I have neither the time nor the expertise to work on this myself. -- Andrea Bolognani / Red Hat / Virtualization
On Tue, 4 Feb 2025 18:46:37 +0000 Andrea Bolognani <abologna(a)redhat.com> wrote:On Tue, Feb 04, 2025 at 05:22:42PM +0100, Stefano Brivio wrote:Ah, thanks, it never occurred to me to look into that. So, yes, essentially the same thing as it's done with MCS and SELinux.On Tue, 4 Feb 2025 15:50:43 +0000 Andrea Bolognani <abologna(a)redhat.com> wrote:I'm not well-versed enough in SELinux to be able to answer the latter question, but I can answer the former. The per-VM profile is needed to ensure that each VM is only granted access to its own resources. $ sudo tail -4 /etc/apparmor.d/libvirt/libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 profile libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 flags=(attach_disconnected) { #include <abstractions/libvirt-qemu> #include if exists <libvirt/libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4.files> } $ sudo cat /etc/apparmor.d/libvirt/libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4.files "/var/log/libvirt/**/alpine.log" w, "/var/lib/libvirt/qemu/domain-alpine/monitor.sock" rw, "/var/lib/libvirt/qemu/domain-1-alpine/*" rw, "/run/libvirt/**/alpine.pid" rwk, "/run/libvirt/**/*.tunnelmigrate.dest.alpine" rw, "/var/lib/libvirt/images/alpine.qcow2" rwk, "/var/lib/libvirt/qemu/domain-1-alpine/{,**}" rwk, "/run/libvirt/qemu/channel/1-alpine/{,**}" rwk, "/var/lib/libvirt/qemu/domain-1-alpine/master-key.aes" rwk, "/dev/userfaultfd" rwk, The stuff in the libvirt-qemu abstraction is generic, all VMs get access to it. The stuff in .files is all specific to the VM.The additional profiles (libvirt-1cdfdfd3-a020-45d9-8f88-8e0ce31745c4 and its passt subprofile) are generated dynamically when the VM is started and the QEMU process gets the correct one assigned to it. So far so good.Why do we need additional profiles, I wonder? Are we trying to replicate the MCS (Multi-Category Security) stuff from SELinux?Right. That's what we did for libguestfs as well, the image can be *almost* anywhere. But it's not free-for-all: you're just granting *limited* filesystem access (not to sysfs, not to /etc, and so on). And I had to build a *very* loose profile for libguestfs because that applies to root as well, but for rootless libvirtd, it might even make sense to restrict access to just @{HOME}/** and /tmp/** (that's what I did for stand-alone passt, for example).Sounds to me like this would require granting the QEMU process access to roughly the entire filesystem? The disk image could live anywhere after all, and if we can't dynamically add a rule for the exact path the only way out is a free-for-all approach.Do you have any ideas?Probably you should ask somebody more familiar (openSUSE/Ubuntu maintainers of libvirt, or the authors of the virt-aa-helper thing?), but a couple of quick ideas: 1. user-specific subprofiles could be added at adduser time (is there a hook?) and libvirtd could use aa_change_hat(2) to select the appropriate one based on UID 2. (most reasonable I think) don't use per-VM profiles for the rootless case. Define a single "libvirt-user" (or "libvirt-session") profile and use that. We could copy it from the existing ones I suppose.Well, you are still restricting them significantly, for example they can't run random binaries, send arbitrary signals to other processes or to each other, and access a ton of places on the filesystem. Perhaps that's even more important than curbing filesystem access, because that should already be significantly restricted.I think that MCS-equivalent functionality is anyway much less critical if guests are started as unprivileged users because you have a strong separation given by the fact that guests are started as different users. If all the guests are started as root, and multiple users have access to that facility, user separation is much more seriously endangered, hence a stronger need for per-VM profiles.Ideally you'd still want to isolate unprivileged VMs from each other. If you don't, what's the point of using AppArmor in the first place?I'll try to submit a pull request at least for Debian in a couple of days. I guess it would be nice if you could ask other maintainers meanwhile. -- StefanoI can try to work on this but I'm really a bit too busy right now. If you can, great, otherwise, let me know. On the other hand this feels pretty urgent. :(I'm afraid I have neither the time nor the expertise to work on this myself.
On Tue, Feb 04, 2025 at 08:14:48PM +0100, Stefano Brivio wrote:On Tue, 4 Feb 2025 18:46:37 +0000 Andrea Bolognani <abologna(a)redhat.com> wrote:That could work, I suppose. Needs to be discussed upstream, making sure to involve those who are more experienced with AppArmor than I am, especially since it's not just a matter of updating the policy but fundamentally changing how the driver works when operating in unprivileged mode.Right. That's what we did for libguestfs as well, the image can be *almost* anywhere. But it's not free-for-all: you're just granting *limited* filesystem access (not to sysfs, not to /etc, and so on). And I had to build a *very* loose profile for libguestfs because that applies to root as well, but for rootless libvirtd, it might even make sense to restrict access to just @{HOME}/** and /tmp/** (that's what I did for stand-alone passt, for example).2. (most reasonable I think) don't use per-VM profiles for the rootless case. Define a single "libvirt-user" (or "libvirt-session") profile and use that. We could copy it from the existing ones I suppose.Sounds to me like this would require granting the QEMU process access to roughly the entire filesystem? The disk image could live anywhere after all, and if we can't dynamically add a rule for the exact path the only way out is a free-for-all approach.I'll try to submit a pull request at least for Debian in a couple of days.Be aware that I will emphatically refuse to introduce changes to the Debian package unless they have been merged upstream first. AppArmor support lives in the upstream repository, and all fixes and improvements have to go through it. -- Andrea Bolognani / Red Hat / Virtualization
On Tue, 4 Feb 2025 14:19:34 -0800 Andrea Bolognani <abologna(a)redhat.com> wrote:On Tue, Feb 04, 2025 at 08:14:48PM +0100, Stefano Brivio wrote:Sure, that makes sense of course.On Tue, 4 Feb 2025 18:46:37 +0000 Andrea Bolognani <abologna(a)redhat.com> wrote:That could work, I suppose. Needs to be discussed upstream, making sure to involve those who are more experienced with AppArmor than I amRight. That's what we did for libguestfs as well, the image can be *almost* anywhere. But it's not free-for-all: you're just granting *limited* filesystem access (not to sysfs, not to /etc, and so on). And I had to build a *very* loose profile for libguestfs because that applies to root as well, but for rootless libvirtd, it might even make sense to restrict access to just @{HOME}/** and /tmp/** (that's what I did for stand-alone passt, for example).2. (most reasonable I think) don't use per-VM profiles for the rootless case. Define a single "libvirt-user" (or "libvirt-session") profile and use that. We could copy it from the existing ones I suppose.Sounds to me like this would require granting the QEMU process access to roughly the entire filesystem? The disk image could live anywhere after all, and if we can't dynamically add a rule for the exact path the only way out is a free-for-all approach.especially since it's not just a matter of updating the policy but fundamentally changing how the driver works when operating in unprivileged mode.Well, right now it runs unconfined, and (at least with passt) networking doesn't work. Pretty much any change would be good. :) I've been disabling AppArmor when I start guests for quite a while now, thinking that I just broke something on my setup while developing stuff (I reported that to you but I wasn't sure how the whole thing worked...). Oops.Then never mind. I can help filing a Debian issue if needed, let me know. Or let me know how I can help otherwise. I would consider a workaround for passt for the moment, say, the whole block: /usr/bin/passt r, signal (receive) set=("term") peer=/usr/sbin/libvirtd, signal (receive) set=("term") peer=libvirtd, signal (receive) set=("term") peer=virtqemud, owner @{run}/user/[0-9]*/libvirt/qemu/run/passt/* rw, owner @{run}/libvirt/qemu/passt/* rw, as part of the profile for usr.bin.passt. If you don't see issues with it, I'll go ahead with that. I still need to check openSUSE though (I haven't tried for a while there). -- StefanoI'll try to submit a pull request at least for Debian in a couple of days.Be aware that I will emphatically refuse to introduce changes to the Debian package unless they have been merged upstream first. AppArmor support lives in the upstream repository, and all fixes and improvements have to go through it.