DF-0751 / fix.diff
diff --git a/sys/netproto/mpls/mpls_input.c b/sys/netproto/mpls/mpls_input.c --- a/sys/netproto/mpls/mpls_input.c +++ b/sys/netproto/mpls/mpls_input.c @@ -45,6 +45,14 @@ #include <netproto/mpls/mpls.h> #include <netproto/mpls/mpls_var.h> +/* + * Maximum number of MPLS labels we will process in one mpls_input() + * call. RFC 3032 does not bound the label stack, but a legitimate + * stack is never deeper than a handful of entries; cap it to prevent a + * malicious or malformed frame from spinning the netisr thread forever. + */ +#define MPLS_LABEL_TTL_MAX 32 + struct mpls_stats mplsstats_percpu[MAXCPU]; struct route mplsforward_rt[MAXCPU]; @@ -89,6 +97,7 @@ { struct mpls *mpls = NULL; mpls_label_t label; + int depth = 0; M_ASSERTPKTHDR(m); @@ -99,6 +108,11 @@ ("mpls_input: mpls header too small")); again: + if (++depth > MPLS_LABEL_TTL_MAX) { + mplsstat.mplss_invalid++; + m_freem(m); + return; + } if (m->m_len < sizeof(struct mpls)) { m = m_pullup(m, sizeof(struct mpls)); if (m == NULL) { @@ -120,6 +134,7 @@ netisr_queue(NETISR_IP, m); return; } + m_adj(m, sizeof(struct mpls)); goto again; /* If not the bottom label, per RFC4182. */ case 1: @@ -139,6 +154,7 @@ netisr_queue(NETISR_IPV6, m); return; } + m_adj(m, sizeof(struct mpls)); goto again; /* If not the bottom label, per RFC4182. */ case 3: |