summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillem de Bruijn <willemb@google.com>2020-07-24 09:03:08 -0400
committerDavid S. Miller <davem@davemloft.net>2020-07-24 17:12:41 -0700
commitc4e9e09f5589f9afe6b8f8c4fb078e0559bca667 (patch)
treeb5631b1e8eb0dcd420c3facb6dfe44476d09972d
parent623b57bec7c8daf89623c95cd9cc919e4090c9da (diff)
icmp: revise rfc4884 tests
1) Only accept packets with original datagram len field >= header len. The extension header must start after the original datagram headers. The embedded datagram len field is compared against the 128B minimum stipulated by RFC 4884. It is unlikely that headers extend beyond this. But as we know the exact header length, check explicitly. 2) Remove the check that datagram length must be <= 576B. This is a send constraint. There is no value in testing this on rx. Within private networks it may be known safe to send larger packets. Process these packets. This test was also too lax. It compared original datagram length rather than entire icmp packet length. The stand-alone fix would be: - if (hlen + skb->len > 576) + if (-skb_network_offset(skb) + skb->len > 576) Fixes: eba75c587e81 ("icmp: support rfc 4884") Signed-off-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/icmp.c8
1 files changed, 2 insertions, 6 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 793aebf07c2a..8d2654cdbd77 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -1164,16 +1164,12 @@ void ip_icmp_error_rfc4884(const struct sk_buff *skb,
return;
}
- /* outer headers up to inner iph. skb->data is at inner payload */
+ /* original datagram headers: end of icmph to payload (skb->data) */
hlen = -skb_transport_offset(skb) - sizeof(struct icmphdr);
- /* per rfc 791: maximum packet length of 576 bytes */
- if (hlen + skb->len > 576)
- return;
-
/* per rfc 4884: minimal datagram length of 128 bytes */
off = icmp_hdr(skb)->un.reserved[1] * sizeof(u32);
- if (off < 128)
+ if (off < 128 || off < hlen)
return;
/* kernel has stripped headers: return payload offset in bytes */