Unable to update some network settings when AppArmor is enabled

I’m currently running an unprivileged OpenWrt 23.05 instance on Incus as my router and it works pretty well. The main reason I turned to Incus is because my internet is provided by a Qualcomm USB 5G modem, and USB pass-through performance in VM (Proxmox VE) is hard capped around 120 Mbps on my device, at which point 1 core is fully loaded and can’t get any faster. With Incus I can get 300+ Mbps.

Here is what I did to pass through the modem:

devices:
  wwan-cdc-wdm0:
    mode: '0600'
    path: /dev/cdc-wdm0
    required: 'false'
    type: unix-char
  wwan:
    nictype: physical
    parent: wwp0s20u3i5
    type: nic

Later on, I saw Incus supports AppArmor, and turned it on on my host machine. My network is broken immediately unless I either turned AppArmor off, or set raw.lxc: lxc.apparmor.profile=unconfined. This weekend I got time to check on this again, and solved most of issues reported by audit. However, my WWAN is still broken.

After checking within OpenWrt, the failure is caused by unable to configure the modem as raw-ip mode. On my device, /sys/class/net/eth1/qmi/raw_ip is the path it is trying to modify, while /sys/class/net/eth1 itself is a symlink to /sys/devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.5/net/eth1, which I believe is ultimately blocked by this default rule. Since deny takes precedence, I’m left of no choice but to disable AppArmor.

Is there something else I can try here? I’m using 6.0.2 right now, which is the default package for NixOS 24.05.

1 Like

That’s a tough one because of how awful AppArmor profiles are to work with…

As you mentioned, the deny rules take precedence, so putting something in raw.apparmor isn’t really going to help here.

And because of how both AppArmor and sysfs work, it’s pretty tough to come up with something that’d be safe to add to the stock rules. Basically AppArmor always works on the fully de-referenced path and sysfs is an insane symlink factory…

So there’s basically no good way for us to allow say /sys/class/net/** because that path will never match due to basically all of those being symlinks…

I think our best option, other than having you keep just disabling AppArmor entirely would be to add some security.apparmor.XYZ configuration keys which would allow tweaking the behavior of our generated profile. The profile itself is quite messy so doing that may take some work.

For now, I’d recommend doing this instead of just unconfined.

raw.lxc=lxc.apparmor.profile=unconfined//&:incus-NAME_<var-lib-incus>:unconfined

This will still give you an unconfined environment but within the AppArmor namespace so your container can still interact with AppArmor if needed (like loading more profiles) and the tasks will still be separated from other containers as far as AppArmor is concerned.

1 Like