public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
* Re: Apparmor (and other) Issues
       [not found] <gfnJ5_aKhxXif2AlacEZIAO3UgiyKhgfDhlg7-FWBbkXttL891Y9k0zClSeYZiLN8JkMF9Z_pprz9f3w88cjZTkHL42cjar9boCCIuS6B08=@protonmail.com>
@ 2025-01-29  9:41 ` Stefano Brivio
  2025-01-29 18:10   ` Prafulla Giri
  0 siblings, 1 reply; 20+ messages in thread
From: Stefano Brivio @ 2025-01-29  9:41 UTC (permalink / raw)
  To: Prafulla Giri; +Cc: passt-dev, Andrea Bolognani

Hi,

On Wed, 29 Jan 2025 09:14:12 +0000
Prafulla Giri <prafulla.giri@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/0264a7704ada52f686cafe8f6402d5b60f9f0fc4/src/security/apparmor/libvirt-qemu.in#L204

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.2

Oops. 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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-01-29  9:41 ` Apparmor (and other) Issues Stefano Brivio
@ 2025-01-29 18:10   ` Prafulla Giri
  2025-01-29 18:48     ` Stefano Brivio
  0 siblings, 1 reply; 20+ messages in thread
From: Prafulla Giri @ 2025-01-29 18:10 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: passt-dev, Andrea Bolognani

Hello,

On Wednesday, January 29th, 2025 at 3:26 PM, Stefano Brivio <sbrivio@redhat.com> wrote:

> Hi,
> 
> On Wed, 29 Jan 2025 09:14:12 +0000
> Prafulla Giri prafulla.giri@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.
> 

I'm glad to have bumped into you. Because of the email domain, I thought you weren't the Debian maintainer. Silly me.

> 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/0264a7704ada52f686cafe8f6402d5b60f9f0fc4/src/security/apparmor/libvirt-qemu.in#L204
> 
> 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.

> 
> > - 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
> 
> 
> Oops. 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.
> 

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

> > 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 think I no longer have to, since I have the Debian maintainer right here. (:

> > Thank you once again for this awesome tool.
> 
> 
> And thanks again for trying it out and reporting issues!
> 
I'm happy to be of some assistance (:
> --
> Stefano

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-01-29 18:10   ` Prafulla Giri
@ 2025-01-29 18:48     ` Stefano Brivio
  2025-01-30 10:05       ` Prafulla Giri
  0 siblings, 1 reply; 20+ messages in thread
From: Stefano Brivio @ 2025-01-29 18:48 UTC (permalink / raw)
  To: Prafulla Giri; +Cc: passt-dev, Andrea Bolognani

On Wed, 29 Jan 2025 18:10:36 +0000
Prafulla Giri <prafulla.giri@protonmail.com> wrote:

> Hello,
> 
> On Wednesday, January 29th, 2025 at 3:26 PM, Stefano Brivio <sbrivio@redhat.com> wrote:
> 
> > Hi,
> > 
> > On Wed, 29 Jan 2025 09:14:12 +0000
> > Prafulla Giri prafulla.giri@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.
> 
> I'm glad to have bumped into you. Because of the email domain, I thought you weren't the Debian maintainer. Silly me.

:)

> > 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/0264a7704ada52f686cafe8f6402d5b60f9f0fc4/src/security/apparmor/libvirt-qemu.in#L204
> > 
> > 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.

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?

> > > - 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  
> > 
> > 
> > Oops. 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.
> >   
> 
> 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

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.

-- 
Stefano


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-01-29 18:48     ` Stefano Brivio
@ 2025-01-30 10:05       ` Prafulla Giri
  2025-01-31 20:20         ` Stefano Brivio
  0 siblings, 1 reply; 20+ messages in thread
From: Prafulla Giri @ 2025-01-30 10:05 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: passt-dev, Andrea Bolognani


On Thursday, January 30th, 2025 at 12:33 AM, Stefano Brivio <sbrivio@redhat.com> wrote:

> On Wed, 29 Jan 2025 18:10:36 +0000
> Prafulla Giri prafulla.giri@protonmail.com wrote:
> 
> > Hello,
> > 
> > On Wednesday, January 29th, 2025 at 3:26 PM, Stefano Brivio sbrivio@redhat.com wrote:
> > 
> > > Hi,
> > > 
> > > On Wed, 29 Jan 2025 09:14:12 +0000
> > > Prafulla Giri prafulla.giri@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.
> > 
> > I'm glad to have bumped into you. Because of the email domain, I thought you weren't the Debian maintainer. Silly me.
> 
> 
> :)
> 
> > > 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/0264a7704ada52f686cafe8f6402d5b60f9f0fc4/src/security/apparmor/libvirt-qemu.in#L204
> > > 
> > > 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.
> 
> 
> 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?
> 
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.

> > > > - 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
> > > 
> > > Oops. 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.
> > 
> > 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
> 
> 
> 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.
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  supported

> 
> 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: yes

> 
> 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.
> 
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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-01-30 10:05       ` Prafulla Giri
@ 2025-01-31 20:20         ` Stefano Brivio
       [not found]           ` <NNMPy6qrSrpU0VFxOsd8tUnJFDsz_Ychl7WAxOB1aYfyRCjzTG4uzNEGZLkHUa_NnxCEAL_X1lhnySdZ_1i2ZMxuVK0zDHa-YLex3O5fhRw=@protonmail.com>
  0 siblings, 1 reply; 20+ messages in thread
From: Stefano Brivio @ 2025-01-31 20:20 UTC (permalink / raw)
  To: Prafulla Giri; +Cc: passt-dev, Andrea Bolognani

On Thu, 30 Jan 2025 10:05:14 +0000
Prafulla Giri <prafulla.giri@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.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

?

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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
       [not found]           ` <NNMPy6qrSrpU0VFxOsd8tUnJFDsz_Ychl7WAxOB1aYfyRCjzTG4uzNEGZLkHUa_NnxCEAL_X1lhnySdZ_1i2ZMxuVK0zDHa-YLex3O5fhRw=@protonmail.com>
@ 2025-02-02 14:40             ` Prafulla Giri
  2025-02-03  8:35             ` Stefano Brivio
  1 sibling, 0 replies; 20+ messages in thread
From: Prafulla Giri @ 2025-02-02 14:40 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: passt-dev, Andrea Bolognani


On Sunday, February 2nd, 2025 at 8:06 PM, Prafulla Giri <prafulla.giri@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

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
       [not found]           ` <NNMPy6qrSrpU0VFxOsd8tUnJFDsz_Ychl7WAxOB1aYfyRCjzTG4uzNEGZLkHUa_NnxCEAL_X1lhnySdZ_1i2ZMxuVK0zDHa-YLex3O5fhRw=@protonmail.com>
  2025-02-02 14:40             ` Prafulla Giri
@ 2025-02-03  8:35             ` Stefano Brivio
       [not found]               ` <0gHPSAbajW7n2zyIE-8k2vez7nkpAHQOnP4p6yfc6i5v948AExss0zBAYKF-92Yqf90DhAg3Xx9u19aw4TtSQLnpNgvCEa--wkPTL0PDdnM=@protonmail.com>
  1 sibling, 1 reply; 20+ messages in thread
From: Stefano Brivio @ 2025-02-03  8:35 UTC (permalink / raw)
  To: Prafulla Giri; +Cc: passt-dev, Andrea Bolognani

On Sun, 02 Feb 2025 14:21:49 +0000
Prafulla Giri <prafulla.giri@protonmail.com> wrote:

> On Saturday, February 1st, 2025 at 2:05 AM, Stefano Brivio <sbrivio@redhat.com> wrote:
> 
> > On Thu, 30 Jan 2025 10:05:14 +0000
> > Prafulla Giri prafulla.giri@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.
> >   
> 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=0\x1dFSUID="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)\x1dARCH=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=1\x1dAUID="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/0264a7704ada52f686cafe8f6402d5b60f9f0fc4/src/security/apparmor/libvirt-qemu.in#L195

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?

> 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=0\x1dFSUID="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)\x1dARCH=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=1\x1dAUID="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=0\x1dFSUID="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)\x1dARCH=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=1\x1dAUID="larryboy" UID="larryboy" GID="larryboy"
> 
> > > $ 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 refused

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@redhat.com/

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 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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
       [not found]               ` <0gHPSAbajW7n2zyIE-8k2vez7nkpAHQOnP4p6yfc6i5v948AExss0zBAYKF-92Yqf90DhAg3Xx9u19aw4TtSQLnpNgvCEa--wkPTL0PDdnM=@protonmail.com>
@ 2025-02-04  8:50                 ` Stefano Brivio
  2025-02-04  9:50                   ` Andrea Bolognani
  0 siblings, 1 reply; 20+ messages in thread
From: Stefano Brivio @ 2025-02-04  8:50 UTC (permalink / raw)
  To: Prafulla Giri; +Cc: passt-dev, Andrea Bolognani

On Tue, 04 Feb 2025 08:21:53 +0000
Prafulla Giri <prafulla.giri@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.

> > https://archives.passt.top/passt-dev/20250203082210.2114348-1-sbrivio@redhat.com/
> > 
> > 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

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.

-- 
Stefano


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-04  8:50                 ` Stefano Brivio
@ 2025-02-04  9:50                   ` Andrea Bolognani
  2025-02-04 10:17                     ` Stefano Brivio
  0 siblings, 1 reply; 20+ messages in thread
From: Andrea Bolognani @ 2025-02-04  9:50 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: Prafulla Giri, passt-dev

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@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.

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 / Virtualization


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-04  9:50                   ` Andrea Bolognani
@ 2025-02-04 10:17                     ` Stefano Brivio
  2025-02-04 15:50                       ` Andrea Bolognani
  0 siblings, 1 reply; 20+ messages in thread
From: Stefano Brivio @ 2025-02-04 10:17 UTC (permalink / raw)
  To: Andrea Bolognani; +Cc: Prafulla Giri, passt-dev

On Tue, 4 Feb 2025 09:50:40 +0000
Andrea Bolognani <abologna@redhat.com> wrote:

> 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@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.  
> 
> 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,
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.conf

> 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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-04 10:17                     ` Stefano Brivio
@ 2025-02-04 15:50                       ` Andrea Bolognani
  2025-02-04 16:22                         ` Stefano Brivio
  0 siblings, 1 reply; 20+ messages in thread
From: Andrea Bolognani @ 2025-02-04 15:50 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: Prafulla Giri, passt-dev

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@redhat.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.
>
> 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,

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.

> 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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-04 15:50                       ` Andrea Bolognani
@ 2025-02-04 16:22                         ` Stefano Brivio
  2025-02-04 18:46                           ` Andrea Bolognani
  0 siblings, 1 reply; 20+ messages in thread
From: Stefano Brivio @ 2025-02-04 16:22 UTC (permalink / raw)
  To: Andrea Bolognani; +Cc: Prafulla Giri, passt-dev

On Tue, 4 Feb 2025 15:50:43 +0000
Andrea Bolognani <abologna@redhat.com> wrote:

> 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@redhat.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.  
> >
> > 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,  
> 
> 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.
> 
> > 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.

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.

> [...]
>
> 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.

Why do we need additional profiles, I wonder? Are we trying to
replicate the MCS (Multi-Category Security) stuff from SELinux?

> 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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-04 16:22                         ` Stefano Brivio
@ 2025-02-04 18:46                           ` Andrea Bolognani
  2025-02-04 19:14                             ` Stefano Brivio
  0 siblings, 1 reply; 20+ messages in thread
From: Andrea Bolognani @ 2025-02-04 18:46 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: Prafulla Giri, passt-dev

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@redhat.com> wrote:
> > 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?

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.

> > 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.

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 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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-04 18:46                           ` Andrea Bolognani
@ 2025-02-04 19:14                             ` Stefano Brivio
  2025-02-04 22:19                               ` Andrea Bolognani
  0 siblings, 1 reply; 20+ messages in thread
From: Stefano Brivio @ 2025-02-04 19:14 UTC (permalink / raw)
  To: Andrea Bolognani; +Cc: Prafulla Giri, passt-dev

On Tue, 4 Feb 2025 18:46:37 +0000
Andrea Bolognani <abologna@redhat.com> wrote:

> 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@redhat.com> wrote:  
> > > 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?  
> 
> 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.

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.

> > > 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.  
> 
> 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.

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).

> > 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?

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 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.

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.

-- 
Stefano


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-04 19:14                             ` Stefano Brivio
@ 2025-02-04 22:19                               ` Andrea Bolognani
  2025-02-04 22:34                                 ` Stefano Brivio
  0 siblings, 1 reply; 20+ messages in thread
From: Andrea Bolognani @ 2025-02-04 22:19 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: Prafulla Giri, passt-dev

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@redhat.com> wrote:
> > > 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.
>
> 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).

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.

> 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


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-04 22:19                               ` Andrea Bolognani
@ 2025-02-04 22:34                                 ` Stefano Brivio
  2025-02-05  7:40                                   ` Prafulla Giri
  0 siblings, 1 reply; 20+ messages in thread
From: Stefano Brivio @ 2025-02-04 22:34 UTC (permalink / raw)
  To: Andrea Bolognani; +Cc: Prafulla Giri, passt-dev

On Tue, 4 Feb 2025 14:19:34 -0800
Andrea Bolognani <abologna@redhat.com> wrote:

> 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@redhat.com> wrote:  
> > > > 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.  
> >
> > 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).  
> 
> That could work, I suppose. Needs to be discussed upstream, making
> sure to involve those who are more experienced with AppArmor than I
> am

Sure, that makes sense of course.

> 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.

> > 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.

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).

-- 
Stefano


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-04 22:34                                 ` Stefano Brivio
@ 2025-02-05  7:40                                   ` Prafulla Giri
  2025-02-05 10:16                                     ` Stefano Brivio
  0 siblings, 1 reply; 20+ messages in thread
From: Prafulla Giri @ 2025-02-05  7:40 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: Andrea Bolognani, passt-dev

I am glad such capable maintainers are handling this.

If I may ask, however: could this simply not be dealt with by allowing passt binary access to $XDG_RUNTIME_DIR of the user in the apparmor profile? Forgive me, I am just a novice. But from my lack-of-understanding this issue looks like an issue of passt process not being able to create a socket inside a libvirt-maintained directory inside /run/user/$UID and that is why disabling the apparmor profile for passt seems to work-around this (?) Are there security concerns with this? Only asking out of curiosity.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-05  7:40                                   ` Prafulla Giri
@ 2025-02-05 10:16                                     ` Stefano Brivio
  2025-02-07  6:49                                       ` Prafulla Giri
  0 siblings, 1 reply; 20+ messages in thread
From: Stefano Brivio @ 2025-02-05 10:16 UTC (permalink / raw)
  To: Prafulla Giri; +Cc: Andrea Bolognani, passt-dev

On Wed, 05 Feb 2025 07:40:34 +0000
Prafulla Giri <prafulla.giri@protonmail.com> wrote:

> If I may ask, however: could this simply not be dealt with by
> allowing passt binary access to $XDG_RUNTIME_DIR of the user in the
> apparmor profile? Forgive me, I am just a novice.

Yes, that's a workaround. But the rationale for the current mechanism
based on a passt 'abstraction' is that if libvirtd starts passt, then
those /var/run/... paths are needed for the socket, and otherwise not.

Only the libvirt profile "knows" about that. That's why it's in the
libvirt profile. But the libvirt profile is not associated to the
process, oops.

> But from my
> lack-of-understanding this issue looks like an issue of passt process
> not being able to create a socket inside a libvirt-maintained
> directory inside /run/user/$UID and that is why disabling the
> apparmor profile for passt seems to work-around this (?) Are there
> security concerns with this? Only asking out of curiosity.

Your understanding is correct. We're just trying to make things as
strict as possible, and depending on specific paths.

We'll probably need to make them a bit looser for the moment being and
perhaps just allow passt, no matter who starts it, to write to
/var/run/**.

-- 
Stefano


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-05 10:16                                     ` Stefano Brivio
@ 2025-02-07  6:49                                       ` Prafulla Giri
  2025-02-07  9:16                                         ` Stefano Brivio
  0 siblings, 1 reply; 20+ messages in thread
From: Prafulla Giri @ 2025-02-07  6:49 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: Andrea Bolognani, passt-dev


On Wednesday, February 5th, 2025 at 4:01 PM, Stefano Brivio <sbrivio@redhat.com> wrote:

> But the libvirt profile is not associated to the
> process, oops.

Oh, so this is what is being worked upon: that Apparmor is not making the association, whereas SELinux is doing it's thing as it's supposed to.

> We're just trying to make things as
> strict as possible, and depending on specific paths.

I see. I'm glad this approach of as-strict-as-possible is being taken.

> We'll probably need to make them a bit looser for the moment being and
> perhaps just allow passt, no matter who starts it, to write to
> /var/run/**.

I believe user-mode virtual machines only need access to /run/user/$USER and not /var/run. Not even /run/*, but only /run/user/$USER. So if that work-around is to be implemented, that would be the strictest version of it: each user-started passt process gets access to $XDG_RUNTIME_DIR of it's owner (and not outside of it).

It also seems that more and more of us use $XDG_RUNTIME_DIR in lieu of /tmp in our personal shell scripts, because it kinda' feels like a more private /tmp.

Also, the `passt` update fixing DNS issue hasn't yet made it to Debian Trixie, yet. I figure it's going to take some time (?) Perhaps I should venture to Debian Sid, myself.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: Apparmor (and other) Issues
  2025-02-07  6:49                                       ` Prafulla Giri
@ 2025-02-07  9:16                                         ` Stefano Brivio
  0 siblings, 0 replies; 20+ messages in thread
From: Stefano Brivio @ 2025-02-07  9:16 UTC (permalink / raw)
  To: Prafulla Giri; +Cc: Andrea Bolognani, passt-dev

On Fri, 07 Feb 2025 06:49:45 +0000
Prafulla Giri <prafulla.giri@protonmail.com> wrote:

> On Wednesday, February 5th, 2025 at 4:01 PM, Stefano Brivio
> <sbrivio@redhat.com> wrote:
> 
> > But the libvirt profile is not associated to the
> > process, oops.  
> 
> Oh, so this is what is being worked upon: that Apparmor is not making
> the association

That, I'm not sure, but at least Andrea asked openSUSE and Ubuntu
people for comments. I just prepared (and merged) a workaround for the
moment. You are Cc'ed on the patch. If you want to test it, you should
add this:

  # Workaround: libvirt's profile comes with a passt subprofile which includes,
  # in turn, <abstractions/passt>, and adds libvirt-specific rules on top, to
  # allow passt (when started by libvirtd) to write socket and PID files in the
  # location requested by libvirtd itself, and to execute passt itself.
  #
  # However, when libvirt runs as unprivileged user, the mechanism based on
  # virt-aa-helper, designed to build per-VM profiles as guests are started,
  # doesn't work. The helper needs to create and load profiles on the fly, which
  # can't be done by unprivileged users, of course.
  #
  # As a result, libvirtd runs unconfined if guests are started by unprivileged
  # users, starting passt unconfined as well, which means that passt runs under
  # its own stand-alone profile (this one), which implies in turn that execve()
  # of /usr/bin/passt is not allowed, and socket and PID files can't be written.
  #
  # Duplicate libvirt-specific rules here as long as this is not solved in
  # libvirt's profile itself.
  /usr/bin/passt r,
  owner @{run}/user/[0-9]*/libvirt/qemu/run/passt/* rw,
  owner @{run}/libvirt/qemu/passt/* rw,

to your /etc/apparmor.d/usr.bin.passt. Note that changes to AppArmor
policy files are retained as configuration, so, if you edit it, package
upgrades won't override things automatically. You will need to:

  apt-get -o Dpkg::Options::="--force-confmiss" install --reinstall passt

> whereas SELinux is doing it's thing as it's supposed to.

Right, that's because SELinux can do this:

  https://selinuxproject.org/page/MultiCategorySecurity

with AppArmor, it needs to be "emulated", somehow.

> > We're just trying to make things as
> > strict as possible, and depending on specific paths.  
> 
> I see. I'm glad this approach of as-strict-as-possible is being taken.
> 
> > We'll probably need to make them a bit looser for the moment being
> > and perhaps just allow passt, no matter who starts it, to write to
> > /var/run/**.  
> 
> I believe user-mode virtual machines only need access to
> /run/user/$USER and not /var/run. Not even /run/*, but only
> /run/user/$USER. So if that work-around is to be implemented, that
> would be the strictest version of it: each user-started passt process
> gets access to $XDG_RUNTIME_DIR of it's owner (and not outside of it).

It depends, because if you start passt as root, socket and PID go to
@{run}/libvirt/qemu/passt/*, and if you don't, the location becomes
@{run}/user/[0-9]*/libvirt/qemu/run/passt/*.

@{run} is an AppArmor handle for /var/run and /run, I think (aren't
they generally linked anyway?). Note that Ubuntu and openSUSE might
use slightly different paths.

> It also seems that more and more of us use $XDG_RUNTIME_DIR in lieu
> of /tmp in our personal shell scripts, because it kinda' feels like a
> more private /tmp.

Yeah, it is.

> Also, the `passt` update fixing DNS issue hasn't yet made it to
> Debian Trixie, yet.

I didn't release the fix yet. I merged it (upstream), but actually I
was expecting you would give it a quick try. If I'm more confident
about the change, I can do things faster.

> I figure it's going to take some time (?) Perhaps
> I should venture to Debian Sid, myself.

It's not in Debian Sid either because I didn't make a new release of
passt, yet.

It probably makes sense to make one next week (we release quite often,
especially if there's one or more fixes that might be important for
somebody, such as this one). As Debian maintainer I also update Debian
packages within a couple of hours.

Sid to testing is usually five days of difference, look:

  https://tracker.debian.org/pkg/passt/news/

-- 
Stefano


^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2025-02-07  9:16 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <gfnJ5_aKhxXif2AlacEZIAO3UgiyKhgfDhlg7-FWBbkXttL891Y9k0zClSeYZiLN8JkMF9Z_pprz9f3w88cjZTkHL42cjar9boCCIuS6B08=@protonmail.com>
2025-01-29  9:41 ` Apparmor (and other) Issues Stefano Brivio
2025-01-29 18:10   ` Prafulla Giri
2025-01-29 18:48     ` Stefano Brivio
2025-01-30 10:05       ` Prafulla Giri
2025-01-31 20:20         ` Stefano Brivio
     [not found]           ` <NNMPy6qrSrpU0VFxOsd8tUnJFDsz_Ychl7WAxOB1aYfyRCjzTG4uzNEGZLkHUa_NnxCEAL_X1lhnySdZ_1i2ZMxuVK0zDHa-YLex3O5fhRw=@protonmail.com>
2025-02-02 14:40             ` Prafulla Giri
2025-02-03  8:35             ` Stefano Brivio
     [not found]               ` <0gHPSAbajW7n2zyIE-8k2vez7nkpAHQOnP4p6yfc6i5v948AExss0zBAYKF-92Yqf90DhAg3Xx9u19aw4TtSQLnpNgvCEa--wkPTL0PDdnM=@protonmail.com>
2025-02-04  8:50                 ` Stefano Brivio
2025-02-04  9:50                   ` Andrea Bolognani
2025-02-04 10:17                     ` Stefano Brivio
2025-02-04 15:50                       ` Andrea Bolognani
2025-02-04 16:22                         ` Stefano Brivio
2025-02-04 18:46                           ` Andrea Bolognani
2025-02-04 19:14                             ` Stefano Brivio
2025-02-04 22:19                               ` Andrea Bolognani
2025-02-04 22:34                                 ` Stefano Brivio
2025-02-05  7:40                                   ` Prafulla Giri
2025-02-05 10:16                                     ` Stefano Brivio
2025-02-07  6:49                                       ` Prafulla Giri
2025-02-07  9:16                                         ` Stefano Brivio

Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).