Snap policy module fails to identify snaps if SCM_CREDENTIALS are missing from PA_COMMAND_AUTH request
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
pulseaudio (Ubuntu) |
Fix Released
|
Undecided
|
Avital Ostromich |
Bug Description
This bug was discovered while debugging the non-deterministic behaviour of the example program attached to bug 1886854.
The snap policy module currently uses the credentials passed in an SCM_CREDENTIALS control message attached to the PA_COMMAND_AUTH request sent by the client. Credentials will only be attached to the message if at least one end of the connection has set the SO_PASSCRED socket option.
In normal operation, both the client and server set SO_PASSCRED on their sockets, so this functions normally. The test program on the other bug used an alternative client library that didn't set SO_PASSCRED, which leads to a race between the client sending the PA_COMMAND_AUTH request and the server calling setsockopt().
If the client wins, the server will receive a message with an empty SCM_CREDENTIALS control message (pid=0, uid=65534, gid=65534). When the snap policy module gets these empty credentials, it would try to look up the confinement of pid 0. As there is no such process, the module decides that the client is not a snap.
As any lookup via process ID is inherently racy, a better solution would be to use aa_getpeercon() to retrieve the client's security label in pa_native_
CVE References
description: | updated |
Changed in pulseaudio (Ubuntu): | |
status: | New → In Progress |
assignee: | James Henstridge (jamesh) → Avital Ostromich (avital) |
information type: | Private Security → Public Security |
I should note that aa_getpeercon() is currently a wrapper around
rc = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &optlen);
it checks that apparmor is enabled before hitting the interface (other LSMs could be using it), and then splits the context that is returned into a label and mode.
Once the LSM stacking replacement interface is properly defined it will use that if available instead.
You can hit the interface directly, but if you do you should perform similar checks and processing.