In the loop(s) that scan for available ports in tcp_ipv4.c, grsec generates an entirely new random port number on each iteration of the loop. If it doesn't find an unused port number after (sysctl_local_port_range[1] - sysctl_local_port_range[0]) iterations, it assumes the local port range is exhausted.
The problem is that in a sceneraio where almost all ports are in use, it is possible that it won't find the available ports while it's constantly generating random numbers. With rand_tcp_src_ports disabled, this won't happen because it uses a simple incrementing algorithm which will never miss an available port.
To fix the problem, I propose moving the random port generation outside the loop, and using the incrementing algorithm inside the loop. Here are diffs against the stock 2.4.19 kernel sources which implement this:
- Code: Select all
@@ -213,7 +214,11 @@
int rover;
spin_lock(&tcp_portalloc_lock);
- rover = tcp_port_rover;
+ if(grsec_enable_randsrc && (high > low)) {
+ rover = low + (ip_randomid() % (high - low));
+ } else {
+ rover = tcp_port_rover;
+ }
do { rover++;
if ((rover < low) || (rover > high))
rover = low;
@@ -666,7 +671,11 @@
* memory pingpong. Any ideas how to do this in a nice way?
*/
spin_lock(&tcp_portalloc_lock);
- rover = tcp_port_rover;
+ if(grsec_enable_randsrc && (high > low)) {
+ rover = low + (ip_randomid() % (high - low));
+ } else {
+ rover = tcp_port_rover;
+ }
do {
rover++;
(Sorry if the formatting is screwed up; I'd prefer to post an attachment but I don't see how.)