Hi, I saw a crash on an OpenBSD 6.1 based system when a kassert in pf_state_key_unref() was triggert.
kernel diagnostic assertion "(sk->inp == NULL) || (sk->inp->inp_pf_sk == NULL)" failed: file "../../../../../net/pf.c", line 7155 panic() at panic+0xfe __assert() at __assert+0x25 pf_state_key_unref() at pf_state_key_unref+0xc6 pf_pkt_unlink_state_key() at pf_pkt_unlink_state_key+0x15 m_free() at m_free+0xc0 soreceive() at soreceive+0xb5d recvit() at recvit+0x13a sys_recvmsg() at sys_recvmsg+0x107 syscall() at syscall+0x2df The problem is that setting the inp pointer in the statekey to NULL is delayed until the statekey refcounter reaches 0. So the inp could get linked to another statekey while the mbuf in the socket buffer was keeping the refcounter at 1. The sk->inp should be set to NULL immediately, then the kassert can get even stricter. ok? bluhm Index: net/pf.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v retrieving revision 1.1034 diff -u -p -r1.1034 pf.c --- net/pf.c 5 Jun 2017 22:18:28 -0000 1.1034 +++ net/pf.c 20 Jun 2017 22:37:43 -0000 @@ -779,6 +779,7 @@ pf_state_key_detach(struct pf_state *s, sk->removed = 1; pf_state_key_unlink_reverse(sk); pf_inpcb_unlink_state_key(sk->inp); + sk->inp = NULL; pf_state_key_unref(sk); } } @@ -7147,8 +7148,7 @@ pf_state_key_unref(struct pf_state_key * /* state key must be unlinked from reverse key */ KASSERT(sk->reverse == NULL); /* state key must be unlinked from socket */ - KASSERT((sk->inp == NULL) || (sk->inp->inp_pf_sk == NULL)); - sk->inp = NULL; + KASSERT(sk->inp == NULL); pool_put(&pf_state_key_pl, sk); } }