OSDN Git Service

Merge tag 'net-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[tomoyo/tomoyo-test1.git] / net / netfilter / nft_exthdr.c
index 7f856ce..3fbaa7b 100644 (file)
@@ -35,6 +35,14 @@ static unsigned int optlen(const u8 *opt, unsigned int offset)
                return opt[offset + 1];
 }
 
+static int nft_skb_copy_to_reg(const struct sk_buff *skb, int offset, u32 *dest, unsigned int len)
+{
+       if (len % NFT_REG32_SIZE)
+               dest[len / NFT_REG32_SIZE] = 0;
+
+       return skb_copy_bits(skb, offset, dest, len);
+}
+
 static void nft_exthdr_ipv6_eval(const struct nft_expr *expr,
                                 struct nft_regs *regs,
                                 const struct nft_pktinfo *pkt)
@@ -56,8 +64,7 @@ static void nft_exthdr_ipv6_eval(const struct nft_expr *expr,
        }
        offset += priv->offset;
 
-       dest[priv->len / NFT_REG32_SIZE] = 0;
-       if (skb_copy_bits(pkt->skb, offset, dest, priv->len) < 0)
+       if (nft_skb_copy_to_reg(pkt->skb, offset, dest, priv->len) < 0)
                goto err;
        return;
 err:
@@ -153,8 +160,7 @@ static void nft_exthdr_ipv4_eval(const struct nft_expr *expr,
        }
        offset += priv->offset;
 
-       dest[priv->len / NFT_REG32_SIZE] = 0;
-       if (skb_copy_bits(pkt->skb, offset, dest, priv->len) < 0)
+       if (nft_skb_copy_to_reg(pkt->skb, offset, dest, priv->len) < 0)
                goto err;
        return;
 err:
@@ -210,7 +216,8 @@ static void nft_exthdr_tcp_eval(const struct nft_expr *expr,
                if (priv->flags & NFT_EXTHDR_F_PRESENT) {
                        *dest = 1;
                } else {
-                       dest[priv->len / NFT_REG32_SIZE] = 0;
+                       if (priv->len % NFT_REG32_SIZE)
+                               dest[priv->len / NFT_REG32_SIZE] = 0;
                        memcpy(dest, opt + offset, priv->len);
                }
 
@@ -238,7 +245,12 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr,
        if (!tcph)
                goto err;
 
+       if (skb_ensure_writable(pkt->skb, nft_thoff(pkt) + tcphdr_len))
+               goto err;
+
+       tcph = (struct tcphdr *)(pkt->skb->data + nft_thoff(pkt));
        opt = (u8 *)tcph;
+
        for (i = sizeof(*tcph); i < tcphdr_len - 1; i += optl) {
                union {
                        __be16 v16;
@@ -253,15 +265,6 @@ static void nft_exthdr_tcp_set_eval(const struct nft_expr *expr,
                if (i + optl > tcphdr_len || priv->len + priv->offset > optl)
                        goto err;
 
-               if (skb_ensure_writable(pkt->skb,
-                                       nft_thoff(pkt) + i + priv->len))
-                       goto err;
-
-               tcph = nft_tcp_header_pointer(pkt, sizeof(buff), buff,
-                                             &tcphdr_len);
-               if (!tcph)
-                       goto err;
-
                offset = i + priv->offset;
 
                switch (priv->len) {
@@ -325,9 +328,9 @@ static void nft_exthdr_tcp_strip_eval(const struct nft_expr *expr,
        if (skb_ensure_writable(pkt->skb, nft_thoff(pkt) + tcphdr_len))
                goto drop;
 
-       opt = (u8 *)nft_tcp_header_pointer(pkt, sizeof(buff), buff, &tcphdr_len);
-       if (!opt)
-               goto err;
+       tcph = (struct tcphdr *)(pkt->skb->data + nft_thoff(pkt));
+       opt = (u8 *)tcph;
+
        for (i = sizeof(*tcph); i < tcphdr_len - 1; i += optl) {
                unsigned int j;
 
@@ -392,9 +395,8 @@ static void nft_exthdr_sctp_eval(const struct nft_expr *expr,
                            offset + ntohs(sch->length) > pkt->skb->len)
                                break;
 
-                       dest[priv->len / NFT_REG32_SIZE] = 0;
-                       if (skb_copy_bits(pkt->skb, offset + priv->offset,
-                                         dest, priv->len) < 0)
+                       if (nft_skb_copy_to_reg(pkt->skb, offset + priv->offset,
+                                               dest, priv->len) < 0)
                                break;
                        return;
                }