From be7274bff2cdfc1e4013aa1cc73f6ee5bcc3b103 Mon Sep 17 00:00:00 2001 From: bluhm Date: Mon, 22 Feb 2021 13:04:56 +0000 Subject: [PATCH] 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@ --- sys/net/pf_norm.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) 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 @@ -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; } -- 2.20.1