summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbluhm <bluhm@openbsd.org>2021-02-22 13:04:56 +0000
committerbluhm <bluhm@openbsd.org>2021-02-22 13:04:56 +0000
commitbe7274bff2cdfc1e4013aa1cc73f6ee5bcc3b103 (patch)
treeff4a85cd4407f488e24fd0b7ec6dd7c561ab42d7
parentadd 7.0 syspatch pubkey (diff)
downloadwireguard-openbsd-be7274bff2cdfc1e4013aa1cc73f6ee5bcc3b103.tar.xz
wireguard-openbsd-be7274bff2cdfc1e4013aa1cc73f6ee5bcc3b103.zip
When cutting of the head of an overlapping fragment during pf
reassembly, reinsert the fragment into the lookup table with correct index. Reported-by: syzbot+d043455a5346f726f1c4@syzkaller.appspotmail.com OK claudio@
-rw-r--r--sys/net/pf_norm.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/sys/net/pf_norm.c b/sys/net/pf_norm.c
index 2b6789a7949..9bd1514167c 100644
--- a/sys/net/pf_norm.c
+++ b/sys/net/pf_norm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_norm.c,v 1.220 2021/02/09 14:06:19 patrick Exp $ */
+/* $OpenBSD: pf_norm.c,v 1.221 2021/02/22 13:04:56 bluhm Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
@@ -665,10 +665,35 @@ pf_fillup_fragment(struct pf_frnode *key, u_int32_t id,
aftercut = frent->fe_off + frent->fe_len - after->fe_off;
if (aftercut < after->fe_len) {
+ int old_index, new_index;
+
DPFPRINTF(LOG_NOTICE, "frag tail overlap %d", aftercut);
m_adj(after->fe_m, aftercut);
+ old_index = pf_frent_index(after);
after->fe_off += aftercut;
after->fe_len -= aftercut;
+ new_index = pf_frent_index(after);
+ if (old_index != new_index) {
+ DPFPRINTF(LOG_DEBUG, "frag index %d, new %d",
+ old_index, new_index);
+ /* Fragment switched queue as fe_off changed */
+ after->fe_off -= aftercut;
+ after->fe_len += aftercut;
+ /* Remove restored fragment from old queue */
+ pf_frent_remove(frag, after);
+ after->fe_off += aftercut;
+ after->fe_len -= aftercut;
+ /* Insert into correct queue */
+ if (pf_frent_insert(frag, after, prev)) {
+ DPFPRINTF(LOG_WARNING,
+ "fragment requeue limit exceeded");
+ m_freem(after->fe_m);
+ pool_put(&pf_frent_pl, after);
+ pf_nfrents--;
+ /* There is not way to recover */
+ goto free_fragment;
+ }
+ }
break;
}