|
||||||||||
On 23.12.2007, at 12:03, Chris Boot wrote: > I've just upgraded to 1.3b6 and my IPsec VPN appears to crash > m0n0wall: > ... > Fatal trap 12: page fault while in kernel mode > fault virtual address = 0x4 > fault code = supervisor write, page not present Thanks for the report - I've been able to reproduce this issue. It's a bug in FreeBSD 6.2 (i.e. not m0n0wall-specific), as I've also been able to provoke this kind of crash on a stock FreeBSD 6.2 machine. It is encountered in m0n0wall 1.3b6 if all of the following conditions are true: - at least one IPsec tunnel is configured - the traffic shaper is enabled - there is a traffic shaper rule on the WAN interface (or on whichever interface the tunnel is terminated) that matches *incoming* decapsulated packets Then, as soon as one such packet is received, the kernel tries to write to an invalid memory location and panics. This bug has only surfaced now that m0n0wall supports filtering of decapsulated IPsec packets via the enc0 interface. I've found the problem in the kernel (technical details: see below) and created a fixed version, 1.3b7-pre, which you can download here: http://m0n0.ch/wall/downloads-local/cdrom-1.3b7-pre.iso http://m0n0.ch/wall/downloads-local/generic-pc-1.3b7-pre.img http://m0n0.ch/wall/downloads-local/net45xx-1.3b7-pre.img http://m0n0.ch/wall/downloads-local/net48xx-1.3b7-pre.img http://m0n0.ch/wall/downloads-local/wrap-1.3b7-pre.img Please let me know if this fixes the problem for you. Regards, Manuel Technical details: I've done some kernel debugging, and it appears that the problem is related to calling ipsec_filter() in sys/net/if_enc.c, which passes packets through the pfil hooks. When a packet is passed to dummynet, it gets "consumed" by ipfw and the pointer to the mbuf that was passed in gets set to NULL. ipsec_filter() detects this and simply returns the error code that it got from pfil_run_hooks(), which is 0 even if the packet has been consumed. However, in the three functions where ipsec_filter() is called (in sys/netipsec/ {ipsec_input.c,ipsec_output.c,xform_ipip.c}), only a non-zero return value from ipsec_filter() causes processing to stop. Therefore, when a packet was consumed by dummynet, the ipsec_filter() callers in the three mentioned files continue processing with the now NULL mbuf, which of course then leads to a kernel panic. I've also noticed that ipfw doesn't match inbound packets on enc0, but on the interface where the encapsulated ESP packet came in instead, which is hardly surprising, as ipfw_check_in() in netinet/ ip_fw_pfil.c ignores its "ifp" argument and if_enc doesn't replace the ifp in the mbuf with the one for enc0. It works for outbound packets on enc0 as ipfw_check_out() honors the ifp argument. However, this is irrelevant for m0n0wall at present, since there's no GUI support for adding traffic shaper rules on enc0 (only filter rules, and ipfilter works fine both inbound and outbound on enc0). The fact needs to be considered though that incoming decapsulated IPsec packets can also match shaper rules on the interface where the corresponding ESP packet came in. Outbound to-be-encapsulated packets won't match though. I guess I'll file a FreeBSD PR about this soon. |