https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=212873
Bug ID: 212873
Summary: pf kernel abort at boot in pf_purge_expired_fragments
Product: Base System
Version: CURRENT
Hardware: arm
OS: Any
Status: New
Severity: Affects Only Me
Priority: ---
Component: kern
Assignee: freebsd-bugs@FreeBSD.org
Reporter: p-fbsd-b...@ziemba.us
My analysis: it looks as if there is a null pointer dereference inside
TAILQ_LAST on line 225 of pf_norm.c.
Version:
I obtained sources 15 Sep 2016 14:38 PDT via svn from
https://svn0.us-west.freebsd.org/base/head and built with crochet, resulting in
FreeBSD-armv6-12.0-RPI2-305849.img.
Hardware:
Raspberry PI 2
Conditions:
1. There is no pf.conf file
2. pf_enable="YES" in rc.conf
3. pflog_enable="YES" in rc.conf
4. ue1 not attached to USB (i.e., presence/absence made no difference)
5. ue0 is the onboard usb ethernet
Here is /etc/rc.conf:
start /etc/rc.conf
hostname="bogart.ziemba.us"
defaultrouter="10.0.0.1"
ifconfig_ue0="inet 10.0.0.84/16"
ifconfig_ue1="inet 192.168.0.2/24 fib 1"
ifconfig_DEFAULT="DHCP"
vlans_ue0="101"
create_args_ue0_101="fib 1"
ifconfig_ue0_101="inet 10.126.0.3/16 fib 1"
static_routes="fib1default"
route_fib1default="default 10.126.0.2 -fib 1"
dhcpd_enable="YES"
dhcpd_conf="/usr/local/etc/dhcpd.conf"
dhcpd_ifaces=""
dhcpd_withumask="022"
sshd_enable="YES"
inetd_enable="YES"
sendmail_enable="NONE"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
growfs_enable="YES"
fsck_y_enable="YES"
saver="blank"
ntpd_enable="YES"
ntpd_sync_on_start="YES"
# NO /etc/pf.conf is present for this test
pf_enable="YES"
pf_rules="/etc/pf.conf"
pf_flags=""
# uncommenting the following two lines results in failure at boot
#pflog_enable="YES"
#pflog_logfile="/tmp/pflog"
end /etc/rc.conf
At boot, the console displays the following (hand-transcribed, it should be
character-for-character correct):
begin console transcription
Kernel page fault with the following non-sleepable locks held:
exclusive sleep mutex pf fragments (pf fragments) r = 0 (0xc4e03808) locked 0
/v2/Source/public/freebsd/pi/crochet/src/sys/modules/pf/../../netpfil/pf/pf_norm.c:224
stack backtrace:
Fatal kernel mode data abort: 'Translation Fault (L1)' on read
trapframe: 0xeb4c2d40
FSR=0005, FAR=0004, spsr=8013
r0 =, r1 =0001, r2 =, r3 =c087b774
r4 =000f, r5 =c4df839a, r6 =c4e03800, r7 =
r8 =c4e0343c, r9 =c4e03458, r10=, r11=eb4c2df0
r12=c4e03808, ssp=eb4c2dd0, slr=c02a6514, pc =c4deb88c
[ thread pid 358 tid 100084 ]
Stopped at pf_purge_expired_fragments+0x44: ldrr0, [r0, #0x004]
db>
end console transcription
Note that r0 is NULL.
Typing on my USB keyboard does not produce anything at the db> prompt, and I
don't have a serial console yet (awaiting special rpi cable in the mail), so I
haven't been able to interact with the debugger.
Here is the output of objdump:
from objdump output start
00024848 :
pf_purge_expired_fragments():
/v2/Source/public/freebsd/pi/crochet/src/sys/modules/pf/../../netpfil/pf/pf_norm
.c:219
return (0);
}
void
pf_purge_expired_fragments(void)
{
struct pf_fragment *frag;
u_int32_texpire = time_uptime -
24864: e5904000ldr r4, [r0]
24868: e594ldr r0, [r0, #4]
/v2/Source/public/freebsd/pi/crochet/src/sys/modules/pf/../../netpfil/pf/pf_norm.c:222
V_pf_default_rule.timeout[PFTM_FRAG];
2486c: e59f00acldr r0, [pc, #172] ; 24920
24870: e59072a4ldr r7, [r0, #676]
/v2/Source/public/freebsd/pi/crochet/src/sys/modules/pf/../../netpfil/pf/pf_norm.c:224
PF_FRAG_LOCK();
24874: e59f00a8ldr r0, [pc, #168] ; 24924
24878: e2800010add r0, r0, #16 ; 0x10
2487c: e58dstr r0, [sp]
24880: ebff810dbl 4cbc
/v2/Source/public/freebsd/pi/crochet/src/sys/modules/pf/../../netpfil/pf/pf_norm.c:225
while ((frag = TAILQ_LAST(&V_pf_fragqueue, pf_fragqueue)) != NULL) {
24884: e59f60a0ldr r6, [pc, #160] ; 2492c
24888: e5960004ldr r0, [r6, #4]
2488c: e594ldr r0, [r0, #4]
24890: e5905000ldr r5, [r0]
24894: e355cmp r5, #0 ; 0x0
24898: 0a18beq 24900
/v2/Source/public/freebsd/pi/crochet/src/sys/modules/pf/../../netpfil/pf/pf_norm.c:221
from objdump output end
Here is the relevant bit of sys/queue.h:
from sys/queue.h start
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
from sys/queue.h end
1. The con