XXX: this is not a final commit message, but a discussion starter for
phabricator!
The 1dda8ba77a20 did not change the storage logic of inpcbs, but added a
few assertions that were not there before. The assertion in human language
would be: if an inpcb was not found in the exact hash and it doesn't have
INP_UNCONNECTED flag set, then it must be present in the wildcard hash.
However, this assertion can not be checked with existing lookup functions
for certain edge case:
Here is the failing scenario:
struct in_addr addrs[] = { { FIRST }, { SECOND }, };
struct jail jconf = {
.version = JAIL_API_VERSION,
.path = __DECONST(char *, "/"),
.hostname = __DECONST(char *,"test"),
.ip4s = nitems(addrs),
.ip4 = addrs,
};
struct sockaddr_in sin = { .sin_family = AF_INET };
socklen_t slen = sizeof(sin);
int s;
ATF_REQUIRE(jail(&jconf) > 0);
ATF_REQUIRE((s = socket(PF_INET, SOCK_DGRAM, 0)) > 0);
ATF_REQUIRE(bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0);
ATF_REQUIRE(getsockname(s, (struct sockaddr *)&sin, &slen) == 0);/*
- Note that jailed address reports self as INADDR_ANY! However on
- input it won't catch any destinations, only FIRST and SECOND.
*/
ATF_REQUIRE_MSG(sin.sin_addr.s_addr == INADDR_ANY && sin.sin_port != 0,
"jailed unconnected socket name %s:%u", inet_ntoa(sin.sin_addr),
ntohs(sin.sin_port));/*
- This connect(2) will panic in MPASS(i).
*/
sin.sin_addr.s_addr = REMOTE;
sin.sin_port = htons(6666);
ATF_REQUIRE(connect(s, (struct sockaddr *)&sin, sizeof(sin)) == 0);Other options that I see:
- Remove assertions completely.
- Add a more relaxed wildcard lookup function for INVARIANTS use.
- Use different laddr for lookup:
if (inp->inp_laddr == htonl(INADDR_ANY) &&
prison_flag(inp->inp_cred, PR_IP4)) prison_get_ip4(inp->inp_cred, &laddr);
else
laddr = inp->inp_laddr;
i = in_pcblookup_wild_locked(ipictx.pcbinfo,
laddr, inp->inp_lport, RT_ALL_FIBS, &ipictx.wbucket);
MPASS(i);
- Your idea?