unable to get WPA supplicant status via wpa-cli utility from a snap

Bug #2074070 reported by Bugra Aydogar
10
This bug affects 2 people
Affects Status Importance Assigned to Milestone
wpa (Ubuntu)
Invalid
Undecided
Unassigned

Bug Description

Hi

As a developer, while trying to get the wpa_supplicant status by using wpa_cli, it always returns a timeout from the snap context on Ubuntu Core 20.

The problem is not reproducible with Ubuntu Classic.

I did some further analysis to get strace output of `wpa_cli` as well as `wpa_supplicant` for the good (running wpa_cli from host terminal) and bad (running from snap context) cases.

Here is the strace output of the wpa_cli;
Good case:

```
bind(3, {sa_family=AF_UNIX, sun_path="/tmp/wpa_ctrl_29279-1"}, 110) = 0
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/wpa_supplicant/wlp0s20f3"}, 110) = 0
fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
sendto(3, "STATUS", 6, 0, NULL, 0) = 6
pselect6(4, [3], NULL, NULL, {tv_sec=10, tv_nsec=0}, NULL) = 1 (in [3], left {tv_sec=9, tv_nsec=999998877})
recvfrom(3, "bssid=68:a0:3e:93:47:2f\nfreq=526"..., 4095, 0, NULL, NULL) = 316
newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x4), ...}, AT_EMPTY_PATH) = 0
write(1, "bssid=68:a0:3e:93:47:2f\n", 24bssid=68:a0:3e:93:47:2f
) = 24
write(1, "freq=5260\n", 10freq=5260
) = 10
write(1, "ssid=SUPERBOX_Wi-Fi_472B\n", 25ssid=SUPERBOX_Wi-Fi_472B
) = 25
write(1, "id=0\n", 5id=0
) = 5
write(1, "mode=station\n", 13mode=station
) = 13
write(1, "wifi_generation=5\n", 18wifi_generation=5
) = 18
write(1, "pairwise_cipher=CCMP\n", 21pairwise_cipher=CCMP
) = 21
write(1, "group_cipher=CCMP\n", 18group_cipher=CCMP
) = 18
write(1, "key_mgmt=WPA2-PSK\n", 18key_mgmt=WPA2-PSK
) = 18
write(1, "wpa_state=COMPLETED\n", 20wpa_state=COMPLETED
) = 20
write(1, "ip_address=192.168.1.101\n", 25ip_address=192.168.1.101
) = 25
write(1, "p2p_device_address=b0:a4:60:e0:0"..., 37p2p_device_address=b0:a4:60:e0:0c:91
) = 37
write(1, "address=b0:a4:60:e0:0c:90\n", 26address=b0:a4:60:e0:0c:90
) = 26
write(1, "uuid=962ca758-c0a7-54c0-ae01-689"..., 42uuid=962ca758-c0a7-54c0-ae01-68990801f7a0
) = 42
write(1, "ieee80211ac=1\n", 14ieee80211ac=1
) = 14
unlink("/tmp/wpa_ctrl_29279-1") = 0
close(3) = 0
exit_group(0) = ?

```

Bad case (running from the snap context)

```
getpid() = 58024
bind(3, {sa_family=AF_UNIX, sun_path="/tmp/wpa_ctrl_58024-1"}, 110) = 0
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/wpa_supplicant/wlp0s20f3"}, 110) = 0
fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
sendto(3, "STATUS", 6, 0, NULL, 0) = 6
fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
unlink("/tmp/wpa_ctrl_58024-1") = 0
close(3) = 0
write(1, "'STATUS' command timed out.\n", 28'STATUS' command timed out.
) = 28
exit_group(-2) = ?
+++ exited with 254 +++
```

Here is the wpa_supplicant strace output;

For the good case, wpa_supplicant was able to send the message back to the wpa_cli;

```
pselect6(19, [4 5 7 9 10 11 13 14 15 16 17 18], [], [4], {tv_sec=9, tv_nsec=999997000}, NULL) = 1 (in [14], left {tv_sec=9, tv_nsec=281454971})
recvfrom(14, "STATUS", 8193, 0, {sa_family=AF_UNIX, sun_path="/tmp/wpa_ctrl_172293-1"}, [128 => 25]) = 6
getsockopt(14, SOL_SOCKET, SO_SNDBUF, [212992], [4]) = 0
ioctl(14, TIOCOUTQ, [0]) = 0
socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 19
ioctl(19, SIOCGIFADDR, {ifr_name="wlp0s20f3", ifr_addr={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.1.101")}}) = 0
close(19) = 0
getsockopt(14, SOL_SOCKET, SO_SNDBUF, [212992], [4]) = 0
ioctl(14, TIOCOUTQ, [0]) = 0
sendto(14, "bssid=68:a0:3e:93:47:2f\nfreq=526"..., 316, 0, {sa_family=AF_UNIX, sun_path="/tmp/wpa_ctrl_172293-1"}, 25) = 316
pselect6(19, [4 5 7 9 10 11 13 14 15 16 17 18], [], [4], {tv_sec=9, tv_nsec=278742000}, NULL
```

However, for the bad case (where wpa_cli is called from the snap context), the data is available but while wpa_supplicant tries to send it, the socket is probably not visible since we got a no such a file error;

```
recvfrom(14, "STATUS", 8193, 0, {sa_family=AF_UNIX, sun_path="/tmp/wpa_ctrl_172203-1"}, [128 => 25]) = 6
getsockopt(14, SOL_SOCKET, SO_SNDBUF, [212992], [4]) = 0
ioctl(14, TIOCOUTQ, [0]) = 0
socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 19
ioctl(19, SIOCGIFADDR, {ifr_name="wlp0s20f3", ifr_addr={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.1.101")}}) = 0
close(19) = 0
getsockopt(14, SOL_SOCKET, SO_SNDBUF, [212992], [4]) = 0
ioctl(14, TIOCOUTQ, [0]) = 0
sendto(14, "bssid=68:a0:3e:93:47:2f\nfreq=526"..., 316, 0, {sa_family=AF_UNIX, sun_path="/tmp/wpa_ctrl_172203-1"}, 25) = -1 ENOENT (No such file or directory)
getsockopt(14, SOL_SOCKET, SO_SNDBUF, [212992], [4]) = 0
ioctl(14, TIOCOUTQ, [0]) = 0
```

I dont see any denial for accessing to the unix socket and the same problem also occurs within devmode.
I'm assuming that since all of the snaps have their own `/tmp` directory, they may not be able to reach out to the `/tmp` of the host. Moreover, it seems like the wpa_cli also opens a unix socket that exist within the `/tmp` directory. Thus, we might be observing this behavior.

Could you please suggest a potential fixes?

Thanks,
Bugra

Revision history for this message
Launchpad Janitor (janitor) wrote :

Status changed to 'Confirmed' because the bug affects multiple users.

Changed in wpa (Ubuntu):
status: New → Confirmed
Revision history for this message
John Johansen (jjohansen) wrote :

So I have some questions about the snap run under the wpa_client case.

Is this trace repeatable? This one is odd to me in a couple of ways like we are getting a timeout without every doing a select/poll/... so either it is somehow missing from the trace or its being done by interrupt.

The trace starts to differ with the
  fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0

instead of
  pselect6(4, ... <- Why is this one missing
  recvfrom(3, ... <- missing can be explained by time out
  newfstatat(1, ...

the missing pselect/poll.. of any kind is weird and needs to be investigated. The missing recvfrom can be explained by the timeout.

the change from newfstatat to fstat in the snap might give a clue. I think we might be looking at a seccomp issue where newfstatat or at least something used to detect if newfstatat is present is being blocked. My guess is the code to select this is in glibc.

This might also explain pselect6 missing. If glibc is setting some local vars that it is using to conditionally determine which syscall to use. It may just be straight up returning an error (eg timeout) without making a syscall of any kind. Again this is conjecture and needs to be investigated.

Revision history for this message
Philip Meulengracht (the-meulengracht) wrote (last edit ):

So I looked into this and the observations made in this post is correct. It's because the default path of the wpa_cli client socket made is in /tmp (they use AF_UNIX sockets, and UDP protocol - this means the client socket must bind a visible place for the server)

/tmp is obviously not visible outside the snap, so the wpasupplicant server will never be able to respond.

The good news is that wpa_cli has a -s switch where you can change the location of the socket that the client is using. For example:

"wpa_cli -s /path/to/shared/location" should hopefully fix the issue

Revision history for this message
Philip Meulengracht (the-meulengracht) wrote :

Just as an added information, providing the switch `-s /run/wpa_supplicant` with the network-control interface connected should work.

Revision history for this message
Bugra Aydogar (bugraaydogar) wrote :

Thanks for the input. The suggested workaround works fine and therefore, I'm closing the bug report.

Changed in wpa (Ubuntu):
status: Confirmed → Invalid
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.