summaryrefslogtreecommitdiff
path: root/sys/external
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>2023-02-03 19:01:08 +0000
committerchristos <christos@NetBSD.org>2023-02-03 19:01:08 +0000
commit153ea8bc86320ee9b69211b287f56e12f952dd0d (patch)
tree9f24c7eb2b6bdc5bd7df16634a1ac9be85dee80e /sys/external
parentd5f6c3f9826a742eba49f9a3f2689feb346ad21c (diff)
Fix use after free on packet with broken lengths
Under the scenario with a packet with length of 67 bytes, a header length using the default of 20 bytes and a TCP data offset (th_off) of 48 will cause m_pullup() to fail to make sure bytes are arranged contiguously. m_pullup() will free the mbuf chain and return a null. ipfilter stores the resultant mbuf address (or the resulting NULL) in its fr_info_t structure. Unfortunately the erroneous packet is not flagged for drop. From FreeBSD via CY Schubert; originally reported by: Robert Morris <rtm at lcs.mit.edu>
Diffstat (limited to 'sys/external')
-rw-r--r--sys/external/bsd/ipf/netinet/fil.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/sys/external/bsd/ipf/netinet/fil.c b/sys/external/bsd/ipf/netinet/fil.c
index 19154e2f617..10046acabde 100644
--- a/sys/external/bsd/ipf/netinet/fil.c
+++ b/sys/external/bsd/ipf/netinet/fil.c
@@ -1,4 +1,4 @@
-/* $NetBSD: fil.c,v 1.35 2021/12/05 07:28:20 msaitoh Exp $ */
+/* $NetBSD: fil.c,v 1.36 2023/02/03 19:01:08 christos Exp $ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -141,7 +141,7 @@ extern struct timeout ipf_slowtimer_ch;
#if !defined(lint)
#if defined(__NetBSD__)
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.35 2021/12/05 07:28:20 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.36 2023/02/03 19:01:08 christos Exp $");
#else
static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)Id: fil.c,v 1.1.1.2 2012/07/22 13:45:07 darrenr Exp $";
@@ -1142,8 +1142,10 @@ ipf_pr_pullup(fr_info_t *fin, int plen)
if (M_LEN(fin->fin_m) < plen + fin->fin_ipoff) {
#if defined(_KERNEL)
if (ipf_pullup(fin->fin_m, fin, plen) == NULL) {
- DT(ipf_pullup_fail);
+ DT1(ipf_pullup_fail, fr_info_t *, fin);
LBUMP(ipf_stats[fin->fin_out].fr_pull[1]);
+ fin->fin_reason = FRB_PULLUP;
+ fin->fin_flx |= FI_BAD;
return -1;
}
LBUMP(ipf_stats[fin->fin_out].fr_pull[0]);
@@ -1156,6 +1158,7 @@ ipf_pr_pullup(fr_info_t *fin, int plen)
*fin->fin_mp = NULL;
fin->fin_m = NULL;
fin->fin_ip = NULL;
+ fin->fin_flx |= FI_BAD;
return -1;
#endif
}
@@ -3214,6 +3217,13 @@ finished:
SPL_X(s);
+ if (fin->fin_m == NULL && fin->fin_flx & FI_BAD &&
+ fin->fin_reason == FRB_PULLUP) {
+ /* m_pullup() has freed the mbuf */
+ LBUMP(ipf_stats[out].fr_blocked[fin->fin_reason]);
+ return (-1);
+ }
+
#ifdef _KERNEL
if (FR_ISPASS(pass))
return 0;