Comment 0 for bug 1867216

Revision history for this message
Jamie Strandboge (jdstrand) wrote :

'man 2 unix' describes the 'Autobind feature' as such:

   Autobind feature
       If a bind(2) call specifies addrlen as sizeof(sa_family_t), or the SO_PASS‐
       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(sa_family_t)) < 0) {
            perror("bind");
            return -errno;
    }

    return 0;
}

$ gcc -o autobind ./autobind.c

$ cat ./profile
  /etc/ld.so.cache r,
  /{usr/,}lib/@{multiarch}/ld* m,
  /{usr/,}lib/@{multiarch}/** r,
  /{usr/,}lib/@{multiarch}/lib*.so* mr,
  /{usr/,}lib/@{multiarch}/**/lib*.so* mr,
  unix (create, getattr, getopt, setopt, shutdown),

  unix (bind) type=dgram addr=none,
  unix (bind) type=dgram addr="@[0-9][0-9][0-9][0-9][0-9]",
  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.profile && aa-exec -p test -- ./autobind
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_mask="bind" denied_mask="bind" addr=none

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="@[0-9][0-9][0-9][0-9][0-9]",
  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=AF_UNIX}, 2) = -1 EACCES (Permission denied)

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="/tmp/foo"}, 10) = 0

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_mask="receive" denied_mask="receive" addr=none peer_addr=none peer="test"

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,'