firewall_edit_nat.php - memory exhaustion on 32 bit with VIP range
After upgrade to 2.2, experience memory limit errors even after increasing php memory_limit :
_Crash report begins. Anonymous machine information:
FreeBSD 10.1-RELEASE-p4 #0 36d7dec(releng/10.1)-dirty: Thu Jan 22 15:12:38 CST 2015 root@pfsense-22-i386-builder:/usr/obj.i386/usr/pfSensesrc/src/sys/pfSense_SMP.10
Crash report details:
[27-Jan-2015 21:17:45 Africa/Harare] PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 534773760 bytes) in /usr/local/www/firewall_nat_edit.php on line 692
If i comment out line 681 to 697, the foreach dealing with Virtual Ip's, I can now at least get into the NAT editing screen. I have no virtual ip's defined on the system.
#1 Updated by Chris Buechler over 6 years ago
- Status changed from New to Feedback
not a replicable circumstance.
In order for the situation as described to occur, you have to have some kind of configuration under <virtualip> in your config, otherwise it'd completely skip the code whose removal you're saying fixes the issue. Open a backup of your config in a text editor and search for <virtualip>, what do you have from <virtualip> to </virtualip>?
#2 Updated by Mogamat Abrahams over 6 years ago
You are right, must have missed it due to fatigue, although I do remember removing this before upgrading to 2.2.
#3 Updated by Alejandro Olivan over 6 years ago
I got exactly the same situation, so may I at least help consistently confirming the issue existence:
I have stopped upgrading deployed pfsense appliances after outbound NAT php error happens as described.
The issue has appeared on every upgraded router which had several virtual, public , IPs, assigned to the WAN interface and manual outbound rules where set to deal with outbound traffic.
I'm not sure whether this also occurs on appliances with ARP proxy alias on LAN interfaces, but at least I'm aware of the issue present on one appliance whit this setup.
The issue seems to exist on 100% upgraded appliances...but I have to investigate.
In every case the virtual IPs were part of the configuration, so no surprises with the xmls, they show <virtualip> fields as expected.
#4 Updated by Phillip Davis over 6 years ago
Numbers like that work fine for me - e.g. subnet 188.8.131.52 subnet_bits 29
It build a correct list of 8 addresses.
I guess you did not really have "197.xx.xx.131" in the config, but have just obfuscated with "xx" some actual numbers of the public IP address block.
So I do not see how it was sent into a huge or infinite loop there.
#5 Updated by Alejandro Olivan over 6 years ago
Here i paste relevant part of one upgraded router setup.
This particular one has a mixture of virtualIPs, may this help reproduce it.
<descr><![CDATA[proxy ARP requests to SubnetXXX]]></descr>
<descr><![CDATA[catch local packets for somehost]]></descr>
<descr><![CDATA[Catch IP traffic to example.net in WAN iface]]></descr>
...Where obviously aaa.bbb.ccc.ddd appears as a real public IP address.
#10 Updated by Phillip Davis over 6 years ago
Yes - I had been checking the code on a 64-bit system accidentally. Now I am at home with my Alix it all goes wrong:
$x1 = gen_subnet("184.108.40.206","29");
$x2 = ip2long32($x1);
$y1 = gen_subnet_max("220.127.116.11","29");
$y2 = ip2long32($y1);
$z2 = $y2 - $x1;
So even converting and IP address like 18.104.22.168 to an int using ip2long32 will end up with a negative number. Any address in the 2nd half, from 22.214.171.124 onward is going to have this problem.
I will try with the fix now...
#11 Updated by Phillip Davis over 6 years ago
Sorry - the last subtraction in my code above should have been "$z2 = $y2 - $x2" - so ignore the rubbish "float(-198.1)" that was there.
With fix from #4318 the output is:
which is correct - the difference between the bottom and top address is 7, for a total of 8 addresses in the subnet. It works even though the (int) turn out to be negative here.
#12 Updated by Phillip Davis over 6 years ago
$x2 = ip2long32("127.255.255.255");
$y2 = ip2long32("126.96.36.199");
$z2 = $y2 - $x2;
If we convert 2 addresses either side of the 188.8.131.52 boundary into int32 and then try to subtract to find the difference, we get the wrong answer. With subnets, the bottom and top address of a subnet are always in the same half of the address space, except for the "/0" case of the whole internet. As long (pardon the pun) as comparison/subtraction is always done with addresses that are both in the same half of the address space, then ip2long32 is OK.