Introduce a helper for icmp type checking - icmp_is_valid_type. There is a number of code paths handling ICMP packets. To check icmp type validity, some of those code paths perform the check `type <= NR_ICMP_TYPES`. Since the introduction of ICMP_EXT_ECHO and ICMP_EXT_ECHOREPLY (RFC 8335), this check is no longer correct. To fix this inconsistency and avoid further problems with future ICMP types, the patch inserts the icmp_is_valid_type helper wherever it is required. Signed-off-by: Mathias Lark <mathias.lark@xxxxxxxxx> --- include/uapi/linux/icmp.h | 5 +++++ net/ipv4/icmp.c | 8 +++----- net/netfilter/nf_conntrack_proto_icmp.c | 4 +--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/uapi/linux/icmp.h b/include/uapi/linux/icmp.h index 163c0998aec9..ad736a24f0c8 100644 --- a/include/uapi/linux/icmp.h +++ b/include/uapi/linux/icmp.h @@ -159,4 +159,9 @@ struct icmp_ext_echo_iio { } addr; } ident; }; + +static inline bool icmp_is_valid_type(__u8 type) +{ + return type <= NR_ICMP_TYPES || type == ICMP_EXT_ECHO || type == ICMP_EXT_ECHOREPLY; +} #endif /* _UAPI_LINUX_ICMP_H */ diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 236debd9fded..686f3133370f 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -273,7 +273,7 @@ EXPORT_SYMBOL(icmp_global_allow); static bool icmpv4_mask_allow(struct net *net, int type, int code) { - if (type > NR_ICMP_TYPES) + if (!icmp_is_valid_type(type)) return true; /* Don't limit PMTU discovery. */ @@ -661,7 +661,7 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, * Assume any unknown ICMP type is an error. This * isn't specified by the RFC, but think about it.. */ - if (*itp > NR_ICMP_TYPES || + if (!icmp_is_valid_type(*itp) || icmp_pointers[*itp].error) goto out; } @@ -1225,12 +1225,10 @@ int icmp_rcv(struct sk_buff *skb) } /* - * 18 is the highest 'known' ICMP type. Anything else is a mystery - * * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently * discarded. */ - if (icmph->type > NR_ICMP_TYPES) { + if (!icmp_is_valid_type(icmph->type)) { reason = SKB_DROP_REASON_UNHANDLED_PROTO; goto error; } diff --git a/net/netfilter/nf_conntrack_proto_icmp.c b/net/netfilter/nf_conntrack_proto_icmp.c index b38b7164acd5..ba4462c393be 100644 --- a/net/netfilter/nf_conntrack_proto_icmp.c +++ b/net/netfilter/nf_conntrack_proto_icmp.c @@ -225,12 +225,10 @@ int nf_conntrack_icmpv4_error(struct nf_conn *tmpl, } /* - * 18 is the highest 'known' ICMP type. Anything else is a mystery - * * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently * discarded. */ - if (icmph->type > NR_ICMP_TYPES) { + if (!icmp_is_valid_type(icmph->type)) { icmp_error_log(skb, state, "invalid icmp type"); return -NF_ACCEPT; } -- 2.36.1