unix syntax does not easily accommodate unix autobind sockets
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
AppArmor |
New
|
Undecided
|
Unassigned | ||
snapd |
Triaged
|
Wishlist
|
Unassigned |
Bug Description
'man 2 unix' describes the 'Autobind feature' as such:
Autobind feature
If a bind(2) call specifies addrlen as sizeof(
CRED socket option was specified for a socket that was not explicitly bound
to an address, then the socket is autobound to an abstract address. The
address consists of a null byte followed by 5 bytes in the character set
[0-9a-f]. Thus, there is a limit of 2^20 autobind addresses. (From Linux
2.1.15, when the autobind feature was added, 8 bytes were used, and the
limit was thus 2^32 autobind addresses. The change to 5 bytes came in
Linux 2.3.15.)
Eg:
$ cat ./autobind.c
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
int main() {
int fd;
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
return -errno;
}
struct sockaddr_un un;
un.sun_family = AF_UNIX;
if (bind(fd, (struct sockaddr *) &un, sizeof(
return -errno;
}
return 0;
}
$ gcc -o autobind ./autobind.c
$ cat ./profile
/etc/ld.so.cache r,
/{usr/
/{usr/
/{usr/
/{usr/
unix (create, getattr, getopt, setopt, shutdown),
unix (bind) type=dgram addr=none,
unix (bind) type=dgram addr="@
unix (bind) type=dgram addr="@*",
unix (bind) type=dgram addr="@\x00",
#unix (bind) type=dgram addr="\x00x00", // invalid
# most specific rule that can be used
#unix (bind) type=dgram,
}
$ sudo apparmor_parser -r /tmp/apparmor.
bind: Permission denied
[243]
So far so good; the bind was mediated with the following logged denial:
apparmor="DENIED" operation="bind" profile="test" pid=735115 comm="autobind" family="unix" sock_type="dgram" protocol=0 requested_
This looks like an anonymous socket, so I expected this to work:
unix (bind) type=dgram addr=none,
but it doesn't. Considering the unix man page, I tried various addr=@ rules:
unix (bind) type=dgram addr=none,
unix (bind) type=dgram addr="@
unix (bind) type=dgram addr="@*",
unix (bind) type=dgram addr="@\x00",
#unix (bind) type=dgram addr="\x00x00", // invalid
The best rule I can come up with is:
unix (bind) type=dgram,
Unfortunately, that will allow binds for any abstract socket rules that uses this type (though we would still need send and receive rules to allow the communication).
We can see with strace the following (with -s 1024):
socket(AF_UNIX, SOCK_DGRAM, 0) = 3
bind(3, {sa_family=
Notice how the bind doesn't show anything for sun_path, like with a named socket:
socket(AF_UNIX, SOCK_STREAM, 0) = 3
bind(3, {sa_family=AF_UNIX, sun_path=
or an abstract socket:
socket(AF_UNIX, SOCK_STREAM, 0) = 3
bind(3, {sa_family=AF_UNIX, sun_path=@"foo"}, 6) = 0
socketpair() works fine with our anonymous socket mediation when forking a child where when we have this denial:
apparmor="DENIED" operation="sendmsg" profile="test" pid=735525 comm="unnamed-fork" family="unix" sock_type="dgram" protocol=0 requested_
and we can use this rule:
unix type=dgram addr=none,
I'm not sure what the fix should be, but based on the log, it seems like 'unix (bind) type=dgram addr=none,' would be reasonable. If that isn't for some reason, perhaps new syntax would work: 'unix (autobind) type=dgram,'
This was discovered by tracking down the denial in the kubernetes snap. This is the code that triggers the denial:
https:/
A simple go program to reproduce this is:
package main
import (
"fmt"
"net"
"unsafe"
)
var unixConnPtr unsafe.Pointer
func main() {
autobind, err := net.ResolveUnix
if err != nil {
}
sock, err := net.ListenUnixg
if err != nil {
}
// see github.
// how to connect this up to the journal socket
}
description: | updated |
Changed in snapd: | |
importance: | Undecided → Wishlist |
status: | New → Triaged |
This is fixed in apparmor 2.12.4, 2.13.5, and apparmor 3 by the expression addr=auto
eg.
unix (bind) addr=auto,