in_pcb_lport_dest() sized [first, last] as last - first, so the random
start never picked last and the search tried one port too few. With
first == last the random start divided by zero: once root sets the
range, any user's connect() panics the host. The sysctls are per-VNET,
so root in a vnet jail can do it.
Details
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Skipped - Unit
Tests Skipped - Build Status
Buildable 78540 Build 75423: arc lint + arc unit
Event Timeline
IMHO, it would be better to cover invalid sysctl setting in sysctl_net_ipport_check().
AFAIU, the arc4random_uniform() could be more expensive than regular one. Given that we have very little space for a quality randomness here anyway, I don't think it is worth to spend extra CPU cycles on connect().
AFAIK, the random port allocation can't be really considered a security feature against connection forging these days. An attacker can just inject 50k packets in a millisecond. However, the random port allocation is still useful to avoid revealing information on how many connections a host makes. For the latter purpose a cheaper random is fine.
Yeah, you're right, I don't think the random change is doing much/any lifting here - we can drop it.
Sysctl validation would fix the % 0 but still leave the off-by-one error in our port allocation here.
It also looks like there would be some downstream benefit in ensuring that first <= last - some downstream consumers will divide by zero if first == last + 1 and will otherwise allocate ports outside of the range when first > last
I agree that of by one needs to be fixed. Suggesting both your fix and fix to sysctl handler, so that invalid range is refused.
Thanks! I would suggest to split into two commits, since two changes are related but actually different and they also live in different chunks. No reason to squash them.