Fix kernel diagnostic assertion "(sk->inp == NULL) || (sk->inp->inp_pf_sk
authorbluhm <bluhm@openbsd.org>
Wed, 21 Jun 2017 15:29:23 +0000 (15:29 +0000)
committerbluhm <bluhm@openbsd.org>
Wed, 21 Jun 2017 15:29:23 +0000 (15:29 +0000)
== NULL)".  The problem was that setting the inp pointer in the
statekey to NULL was delayed until the statekey refcounter reached
0.  So the inp could get linked to another statekey while an mbuf
in the socket buffer was keeping the refcounter at 1.  Set the
statekey inp pointer to NULL in pf_state_key_detach() immediately,
then the kassert can be even stricter.
OK sashan@

sys/net/pf.c

index b123858..70c6489 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf.c,v 1.1034 2017/06/05 22:18:28 sashan Exp $ */
+/*     $OpenBSD: pf.c,v 1.1035 2017/06/21 15:29:23 bluhm Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -779,6 +779,7 @@ pf_state_key_detach(struct pf_state *s, int idx)
                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 *sk)
                /* 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);
        }
 }