Bug 238781 - sys.netinet.socket_afinet.socket_afinet_bind_zero does not work when mac_portacl(4) loaded
Summary: sys.netinet.socket_afinet.socket_afinet_bind_zero does not work when mac_port...
Status: Open
Alias: None
Product: Base System
Classification: Unclassified
Component: tests (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-testing (Nobody)
Depends on:
Reported: 2019-06-23 19:26 UTC by Li-Wen Hsu
Modified: 2019-12-02 15:43 UTC (History)
3 users (show)

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description Li-Wen Hsu freebsd_committer 2019-06-23 19:26:15 UTC
sys.netinet.socket_afinet.socket_afinet_bind_zero does not work when mac_portacl(4) loaded, while mac_portacl is needed for tests under /usr/tests/sys/mac/portacl.

For this simplified program:

#include <sys/errno.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, const char *argv[])
        int sd, rc;
        struct sockaddr_in sin;

        sd = socket(PF_INET, SOCK_DGRAM, 0);
        bzero(&sin, sizeof(sin));
        //sin.sin_family = AF_INET;
        rc = bind(sd, (struct sockaddr *)&sin, sizeof(sin));
        if (rc < 0) {
                perror("bind failed");
        } else {
                printf("bind ok.\n");
        return 0;

When mac_portacl(4) is loaded, it outputs:

bind failed: Invalid argument

And we found that uncomment line 16, sin.sin_family = AF_INET, will make bind(2) work. 

From bz:

it could be that portacl enforces the error because of the missing sin_family which we by policy do not enforce for AF_INET (per comment in in_pcb.c [1]).

[1] https://svnweb.freebsd.org/base/head/sys/netinet/in_pcb.c?annotate=346677#l816
Comment 1 commit-hook freebsd_committer 2019-06-23 19:37:38 UTC
A commit references this bug:

Author: lwhsu
Date: Sun Jun 23 19:37:12 UTC 2019
New revision: 349322
URL: https://svnweb.freebsd.org/changeset/base/349322

  Skip sys.netinet.socket_afinet.socket_afinet_bind_zero temporarily because it
  doesn't work when mac_portacl(4) loaded

  PR:		238781
  Sponsored by:	The FreeBSD Foundation

Comment 2 Robert Watson freebsd_committer 2019-08-12 19:31:08 UTC
The (sin_family == 0) thing is unfortunate, but presumably baked in for decades. Does Linux also allow that behavior? If so, I suspect we're pretty stuck with it, and should teach mac_portacl(4) that '0' means AF_INET. If not .. maybe it is still possible to change.
Comment 3 Ed Maste freebsd_committer 2019-08-14 19:32:06 UTC
(In reply to Robert Watson from comment #2)
It looks like Linux does have many cases allowing AF_UNSPEC instead of AF_INET.
Comment 4 Ed Maste freebsd_committer 2019-08-14 20:55:57 UTC
Perhaps we should add a security.mac.portacl.family_0_inet sysctl?
Comment 5 Robert Watson freebsd_committer 2019-08-15 08:21:11 UTC
Am I right in assuming that even when sin_family is set to 0, the sockaddr is always interpreted as a sockaddr_in for PF_INET sockets? If so, then, given that we check for PF_INET earlier in mac_portacl's socket_check_bind() function, we can probably safely allow 0 as well as AF_INET and AF_INET6.
Comment 6 Ed Maste freebsd_committer 2019-08-15 21:29:37 UTC
(In reply to Robert Watson from comment #5)
I believe that is indeed the case, although I did not do a comprehensive survey.

Anyhow, I wonder how common it is for software (excluding the failing test under discussion here) to fail to set sin_family?
Comment 7 Robert Watson freebsd_committer 2019-08-21 09:07:05 UTC
Given that it appears to be a portable behavior, I'm not against adding AF_UNSPEC support to mac_portacl, as long as PF_INET sockets are in use. This causes me to wonder: is there AF_UNSPEC behavior for PF_INET6 on FreeBSD or Linux, however?