]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
netfilter: nft_exthdr: fix offset with ipv4_find_option()
authorAlexey Kashavkin <akashavkin@gmail.com>
Sat, 1 Mar 2025 21:14:36 +0000 (00:14 +0300)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 13 Mar 2025 09:02:39 +0000 (10:02 +0100)
There is an incorrect calculation in the offset variable which causes
the nft_skb_copy_to_reg() function to always return -EFAULT. Adding the
start variable is redundant. In the __ip_options_compile() function the
correct offset is specified when finding the function. There is no need
to add the size of the iphdr structure to the offset.

Fixes: dbb5281a1f84 ("netfilter: nf_tables: add support for matching IPv4 options")
Signed-off-by: Alexey Kashavkin <akashavkin@gmail.com>
Reviewed-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nft_exthdr.c

index b8d03364566c1f92367f89cbc2698f261130ed19..c74012c9912554e74900da6bae2441efa12ac457 100644 (file)
@@ -85,7 +85,6 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb,
        unsigned char optbuf[sizeof(struct ip_options) + 40];
        struct ip_options *opt = (struct ip_options *)optbuf;
        struct iphdr *iph, _iph;
-       unsigned int start;
        bool found = false;
        __be32 info;
        int optlen;
@@ -93,7 +92,6 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb,
        iph = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
        if (!iph)
                return -EBADMSG;
-       start = sizeof(struct iphdr);
 
        optlen = iph->ihl * 4 - (int)sizeof(struct iphdr);
        if (optlen <= 0)
@@ -103,7 +101,7 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb,
        /* Copy the options since __ip_options_compile() modifies
         * the options.
         */
-       if (skb_copy_bits(skb, start, opt->__data, optlen))
+       if (skb_copy_bits(skb, sizeof(struct iphdr), opt->__data, optlen))
                return -EBADMSG;
        opt->optlen = optlen;
 
@@ -118,18 +116,18 @@ static int ipv4_find_option(struct net *net, struct sk_buff *skb,
                found = target == IPOPT_SSRR ? opt->is_strictroute :
                                               !opt->is_strictroute;
                if (found)
-                       *offset = opt->srr + start;
+                       *offset = opt->srr;
                break;
        case IPOPT_RR:
                if (!opt->rr)
                        break;
-               *offset = opt->rr + start;
+               *offset = opt->rr;
                found = true;
                break;
        case IPOPT_RA:
                if (!opt->router_alert)
                        break;
-               *offset = opt->router_alert + start;
+               *offset = opt->router_alert;
                found = true;
                break;
        default: