In IPv6 Destination options processing function check if net->ipv6.sysctl.max_dst_opts_cnt is zero up front. If it is zero then drop the packet since Destination Options processing is disabled. Similarly, in IPv6 hop-by-hop options processing function check if net->ipv6.sysctl.max_hbh_opts_cnt is zero up front. If it is zero then drop the packet since Hop-by-Hop Options processing is disabled. Signed-off-by: Tom Herbert --- net/ipv6/exthdrs.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 54088fa0c09d..b9d186784b96 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -301,9 +301,11 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) #endif struct dst_entry *dst = skb_dst(skb); struct net *net = dev_net(skb->dev); - int extlen; + int extlen, max_opts_cnt; - if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || + max_opts_cnt = READ_ONCE(net->ipv6.sysctl.max_dst_opts_cnt); + if (!max_opts_cnt || + !pskb_may_pull(skb, skb_transport_offset(skb) + 8) || !pskb_may_pull(skb, (skb_transport_offset(skb) + ((skb_transport_header(skb)[1] + 1) << 3)))) { __IP6_INC_STATS(dev_net(dst_dev(dst)), idev, @@ -322,8 +324,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) dstbuf = opt->dst1; #endif - if (ip6_parse_tlv(false, skb, - READ_ONCE(net->ipv6.sysctl.max_dst_opts_cnt))) { + if (ip6_parse_tlv(false, skb, max_opts_cnt)) { skb->transport_header += extlen; opt = IP6CB(skb); #if IS_ENABLED(CONFIG_IPV6_MIP6) @@ -1033,7 +1034,7 @@ int ipv6_parse_hopopts(struct sk_buff *skb) { struct inet6_skb_parm *opt = IP6CB(skb); struct net *net = dev_net(skb->dev); - int extlen; + int extlen, max_opts_cnt; /* * skb_network_header(skb) is equal to skb->data, and @@ -1041,7 +1042,9 @@ int ipv6_parse_hopopts(struct sk_buff *skb) * sizeof(struct ipv6hdr) by definition of * hop-by-hop options. */ - if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) || + max_opts_cnt = READ_ONCE(net->ipv6.sysctl.max_hbh_opts_cnt); + if (!max_opts_cnt || + !pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) || !pskb_may_pull(skb, (sizeof(struct ipv6hdr) + ((skb_transport_header(skb)[1] + 1) << 3)))) { fail_and_free: @@ -1054,8 +1057,7 @@ int ipv6_parse_hopopts(struct sk_buff *skb) goto fail_and_free; opt->flags |= IP6SKB_HOPBYHOP; - if (ip6_parse_tlv(true, skb, - READ_ONCE(net->ipv6.sysctl.max_hbh_opts_cnt))) { + if (ip6_parse_tlv(true, skb, max_opts_cnt)) { skb->transport_header += extlen; opt = IP6CB(skb); opt->nhoff = sizeof(struct ipv6hdr); -- 2.43.0