ipv6: Remove dependency of ipv6_frag_thdr_truncated on ipv6 module
authorGeorg Kohmann <geokohma@cisco.com>
Thu, 19 Nov 2020 09:58:33 +0000 (10:58 +0100)
committerJakub Kicinski <kuba@kernel.org>
Thu, 19 Nov 2020 18:49:50 +0000 (10:49 -0800)
IPV6=m
NF_DEFRAG_IPV6=y

ld: net/ipv6/netfilter/nf_conntrack_reasm.o: in function
`nf_ct_frag6_gather':
net/ipv6/netfilter/nf_conntrack_reasm.c:462: undefined reference to
`ipv6_frag_thdr_truncated'

Netfilter is depending on ipv6 symbol ipv6_frag_thdr_truncated. This
dependency is forcing IPV6=y.

Remove this dependency by moving ipv6_frag_thdr_truncated out of ipv6. This
is the same solution as used with a similar issues: Referring to
commit 70b095c843266 ("ipv6: remove dependency of nf_defrag_ipv6 on ipv6
module")

Fixes: 9d9e937b1c8b ("ipv6/netfilter: Discard first fragment not including all headers")
Reported-by: Randy Dunlap <rdunlap@infradead.org>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Georg Kohmann <geokohma@cisco.com>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
Acked-by: Randy Dunlap <rdunlap@infradead.org> # build-tested
Link: https://lore.kernel.org/r/20201119095833.8409-1-geokohma@cisco.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/ipv6.h
include/net/ipv6_frag.h
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/reassembly.c

index 637cc6d..bd1f396 100644 (file)
@@ -1064,8 +1064,6 @@ int ipv6_skip_exthdr(const struct sk_buff *, int start, u8 *nexthdrp,
 
 bool ipv6_ext_hdr(u8 nexthdr);
 
-bool ipv6_frag_thdr_truncated(struct sk_buff *skb, int start, u8 *nexthdrp);
-
 enum {
        IP6_FH_F_FRAG           = (1 << 0),
        IP6_FH_F_AUTH           = (1 << 1),
index a21e8b1..851029e 100644 (file)
@@ -108,5 +108,35 @@ out_rcu_unlock:
        rcu_read_unlock();
        inet_frag_put(&fq->q);
 }
+
+/* Check if the upper layer header is truncated in the first fragment. */
+static inline bool
+ipv6frag_thdr_truncated(struct sk_buff *skb, int start, u8 *nexthdrp)
+{
+       u8 nexthdr = *nexthdrp;
+       __be16 frag_off;
+       int offset;
+
+       offset = ipv6_skip_exthdr(skb, start, &nexthdr, &frag_off);
+       if (offset < 0 || (frag_off & htons(IP6_OFFSET)))
+               return false;
+       switch (nexthdr) {
+       case NEXTHDR_TCP:
+               offset += sizeof(struct tcphdr);
+               break;
+       case NEXTHDR_UDP:
+               offset += sizeof(struct udphdr);
+               break;
+       case NEXTHDR_ICMP:
+               offset += sizeof(struct icmp6hdr);
+               break;
+       default:
+               offset += 1;
+       }
+       if (offset > skb->len)
+               return true;
+       return false;
+}
+
 #endif
 #endif
index b9cc0b3..c129ad3 100644 (file)
@@ -459,7 +459,7 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
        /* Discard the first fragment if it does not include all headers
         * RFC 8200, Section 4.5
         */
-       if (ipv6_frag_thdr_truncated(skb, fhoff, &nexthdr)) {
+       if (ipv6frag_thdr_truncated(skb, fhoff, &nexthdr)) {
                pr_debug("Drop incomplete fragment\n");
                return 0;
        }
index e3869ba..47a0dc4 100644 (file)
@@ -318,35 +318,6 @@ out_fail:
        return -1;
 }
 
-/* Check if the upper layer header is truncated in the first fragment. */
-bool ipv6_frag_thdr_truncated(struct sk_buff *skb, int start, u8 *nexthdrp)
-{
-       u8 nexthdr = *nexthdrp;
-       __be16 frag_off;
-       int offset;
-
-       offset = ipv6_skip_exthdr(skb, start, &nexthdr, &frag_off);
-       if (offset < 0 || (frag_off & htons(IP6_OFFSET)))
-               return false;
-       switch (nexthdr) {
-       case NEXTHDR_TCP:
-               offset += sizeof(struct tcphdr);
-               break;
-       case NEXTHDR_UDP:
-               offset += sizeof(struct udphdr);
-               break;
-       case NEXTHDR_ICMP:
-               offset += sizeof(struct icmp6hdr);
-               break;
-       default:
-               offset += 1;
-       }
-       if (offset > skb->len)
-               return true;
-       return false;
-}
-EXPORT_SYMBOL(ipv6_frag_thdr_truncated);
-
 static int ipv6_frag_rcv(struct sk_buff *skb)
 {
        struct frag_hdr *fhdr;
@@ -390,7 +361,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
         * the source of the fragment, with the Pointer field set to zero.
         */
        nexthdr = hdr->nexthdr;
-       if (ipv6_frag_thdr_truncated(skb, skb_transport_offset(skb), &nexthdr)) {
+       if (ipv6frag_thdr_truncated(skb, skb_transport_offset(skb), &nexthdr)) {
                __IP6_INC_STATS(net, __in6_dev_get_safely(skb->dev),
                                IPSTATS_MIB_INHDRERRORS);
                icmpv6_param_prob(skb, ICMPV6_HDR_INCOMP, 0);