Skip to content

Commit

Permalink
ipv6: Remove dependency of ipv6_frag_thdr_truncated on ipv6 module
Browse files Browse the repository at this point in the history
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 70b095c ("ipv6: remove dependency of nf_defrag_ipv6 on ipv6
module")

Fixes: 9d9e937 ("ipv6/netfilter: Discard first fragment not including all headers")
Reported-by: Randy Dunlap <[email protected]>
Reported-by: kernel test robot <[email protected]>
Signed-off-by: Georg Kohmann <[email protected]>
Acked-by: Pablo Neira Ayuso <[email protected]>
Acked-by: Randy Dunlap <[email protected]> # build-tested
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
  • Loading branch information
Georg Kohmann authored and kuba-moo committed Nov 19, 2020
1 parent f0b0a2d commit 2d8f648
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 33 deletions.
2 changes: 0 additions & 2 deletions include/net/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
30 changes: 30 additions & 0 deletions include/net/ipv6_frag.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,35 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
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
2 changes: 1 addition & 1 deletion net/ipv6/netfilter/nf_conntrack_reasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
31 changes: 1 addition & 30 deletions net/ipv6/reassembly.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,35 +318,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *skb,
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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 2d8f648

Please sign in to comment.