Virtual network devices (eg. via mac80211_hwsim) created in container are inaccessible

Version Info

  • App: Docker for Desktop for Windows v4.25.2, WSL2-based engine (Engine v24.0.6, Compose v23.0-desktop.1)
  • Host OS: Windows 11 Enterprise 23H2, 22631
  • Container: Ubuntu 23.10 (ubuntu:mantic latest), Linux c2303735a8a6 5.15.90.1-microsoft-standard-WSL2 #2 SMP Fri Nov 3 10:43:43 MDT 2023 x86_64 x86_64 x86_64 GNU/Linux
  • mac80211_hwsim.c (kernel driver source)

The container is run with the following command from an elevated Powershell window:

docker run -it --privileged --cap-add=ALL --security-opt systempaths=unconfined --security-opt apparmor=unconfined f26a63bc45c3

Reproduction Steps

  1. In container, compile mac80211_hwsim as a kernel module using this script.
  2. Load mac80211_hwsim kernel module:
    modprobe mac80211_hwsim radios=2
  3. Validate that 3 new devices show up: 1 for the hwsim control device, hwsim0, and 2 wlan devices, wlan0, wlan1, for each virtual device/radio created by the driver.

Expected Result
hwsim0, wlan0, and wlan1 show up as network devices. Example output below when following repro steps on WSL2 distro (Ubuntu mantic) directly, where this works:

root@foxmulder:/sys/class/net# ls /sys/class/net
bonding_masters  eth0  hwsim0  lo  wlan0  wlan1
root@foxmulder:/sys/class/ieee80211# ip l show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1280 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:15:5d:3f:48:91 brd ff:ff:ff:ff:ff:ff
15: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 02:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
16: wlan1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 02:00:00:00:01:00 brd ff:ff:ff:ff:ff:ff
17: hwsim0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ieee802.11/radiotap 12:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff

Actual Result
No new network devices show up in /sys/class/net, no new devices in ip link show output, and debugfs entry for driver not present. lsmod output:

root@f26a63bc45c3:/# lsmod
Module                   Size  Used by
mac80211_hwsim          77824  0
mac80211              1052672  1 mac80211_hwsim
cfg80211               868352  2 mac80211_hwsim,mac80211
rfkill                  24576  1 cfg80211

Note that after the modprobe in step 2 above, no errors are observed in the kernel logs, confirmed via dmesg. I also recompiled the mac80211_hwsim driver with DDEBUG and did not observe any pr_debug() messages indicating warnings or failures. I further added additional printks in the source to validate that network device registration was succeeding. This leads me to believe that loading the module and creating the device driver instances are working, but docker’s network isolation is somehow hiding the devices.

Leaving the mac80211_hwsim module instance in place, I then compiled and attempted to load the virt_wifi driver as a module as well per below, which worked:

root@f26a63bc45c3:/# modprobe -v virt_wifi
insmod /lib/modules/5.15.90.1-microsoft-standard-WSL2/kernel/drivers/net/wireless/virt_wifi.ko
root@f26a63bc45c3:/# ip link add link eth0 name wlan0 type virt_wifi
root@f26a63bc45c3:/# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3: wlan0@eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
28: eth0@if29: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0

virt_wifi technically doesn’t add a new device, instead, it inserts itself in the existing net device’s stack, so this working on its own may not add much value to diagnosing what’s wrong here, but I thought it was worth mentioning.

I’m guessing this is by design, but wondering if there are some ways to work around it. I can patch the driver, if necessary.

1 Like

I’m so interested
Any git repo for that

I’m tring to test captive portals from inside docker
connecting wifi should be the first step
however connecting on pare metal is just giving errors
so I think the driver is now the issue

I would love to see what you did already