Skip to content

Commit 64816aa

Browse files
committed
Merge branch 'ipv6-more-drop-reason'
Eric Dumazet says: ==================== ipv6: more drop reason Add more drop reasons to IPv6: - IPV6_BAD_EXTHDR - IPV6_NDISC_FRAG - IPV6_NDISC_HOP_LIMIT - IPV6_NDISC_BAD_CODE ==================== Link: https://lore.kernel.org/r/20230210184708.2172562-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 1a940b0 + 545dbcd commit 64816aa

File tree

6 files changed

+55
-21
lines changed

6 files changed

+55
-21
lines changed

include/linux/skbuff.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,13 +2631,24 @@ void *skb_pull_data(struct sk_buff *skb, size_t len);
26312631

26322632
void *__pskb_pull_tail(struct sk_buff *skb, int delta);
26332633

2634-
static inline bool pskb_may_pull(struct sk_buff *skb, unsigned int len)
2634+
static inline enum skb_drop_reason
2635+
pskb_may_pull_reason(struct sk_buff *skb, unsigned int len)
26352636
{
26362637
if (likely(len <= skb_headlen(skb)))
2637-
return true;
2638+
return SKB_NOT_DROPPED_YET;
2639+
26382640
if (unlikely(len > skb->len))
2639-
return false;
2640-
return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL;
2641+
return SKB_DROP_REASON_PKT_TOO_SMALL;
2642+
2643+
if (unlikely(!__pskb_pull_tail(skb, len - skb_headlen(skb))))
2644+
return SKB_DROP_REASON_NOMEM;
2645+
2646+
return SKB_NOT_DROPPED_YET;
2647+
}
2648+
2649+
static inline bool pskb_may_pull(struct sk_buff *skb, unsigned int len)
2650+
{
2651+
return pskb_may_pull_reason(skb, len) == SKB_NOT_DROPPED_YET;
26412652
}
26422653

26432654
static inline void *pskb_pull(struct sk_buff *skb, unsigned int len)

include/net/dropreason.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@
7272
FN(FRAG_REASM_TIMEOUT) \
7373
FN(FRAG_TOO_FAR) \
7474
FN(TCP_MINTTL) \
75+
FN(IPV6_BAD_EXTHDR) \
76+
FN(IPV6_NDISC_FRAG) \
77+
FN(IPV6_NDISC_HOP_LIMIT) \
78+
FN(IPV6_NDISC_BAD_CODE) \
7579
FNe(MAX)
7680

7781
/**
@@ -318,6 +322,14 @@ enum skb_drop_reason {
318322
* the threshold (IP_MINTTL or IPV6_MINHOPCOUNT).
319323
*/
320324
SKB_DROP_REASON_TCP_MINTTL,
325+
/** @SKB_DROP_REASON_IPV6_BAD_EXTHDR: Bad IPv6 extension header. */
326+
SKB_DROP_REASON_IPV6_BAD_EXTHDR,
327+
/** @SKB_DROP_REASON_IPV6_NDISC_FRAG: invalid frag (suppress_frag_ndisc). */
328+
SKB_DROP_REASON_IPV6_NDISC_FRAG,
329+
/** @SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT: invalid hop limit. */
330+
SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT,
331+
/** @SKB_DROP_REASON_IPV6_NDISC_BAD_CODE: invalid NDISC icmp6 code. */
332+
SKB_DROP_REASON_IPV6_NDISC_BAD_CODE,
321333
/**
322334
* @SKB_DROP_REASON_MAX: the maximum of drop reason, which shouldn't be
323335
* used as a real 'reason'

include/net/ipv6.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,8 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl)
436436
atomic_dec(&fl->users);
437437
}
438438

439-
void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info);
439+
enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type,
440+
u8 code, __be32 info);
440441

441442
void icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
442443
struct icmp6hdr *thdr, int len);

include/net/ndisc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ int ndisc_late_init(void);
445445
void ndisc_late_cleanup(void);
446446
void ndisc_cleanup(void);
447447

448-
int ndisc_rcv(struct sk_buff *skb);
448+
enum skb_drop_reason ndisc_rcv(struct sk_buff *skb);
449449

450450
struct sk_buff *ndisc_ns_create(struct net_device *dev, const struct in6_addr *solicit,
451451
const struct in6_addr *saddr, u64 nonce);

net/ipv6/icmp.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -813,16 +813,19 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
813813
local_bh_enable();
814814
}
815815

816-
void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
816+
enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type,
817+
u8 code, __be32 info)
817818
{
818819
struct inet6_skb_parm *opt = IP6CB(skb);
820+
struct net *net = dev_net(skb->dev);
819821
const struct inet6_protocol *ipprot;
822+
enum skb_drop_reason reason;
820823
int inner_offset;
821824
__be16 frag_off;
822825
u8 nexthdr;
823-
struct net *net = dev_net(skb->dev);
824826

825-
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
827+
reason = pskb_may_pull_reason(skb, sizeof(struct ipv6hdr));
828+
if (reason != SKB_NOT_DROPPED_YET)
826829
goto out;
827830

828831
seg6_icmp_srh(skb, opt);
@@ -832,14 +835,17 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
832835
/* now skip over extension headers */
833836
inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
834837
&nexthdr, &frag_off);
835-
if (inner_offset < 0)
838+
if (inner_offset < 0) {
839+
SKB_DR_SET(reason, IPV6_BAD_EXTHDR);
836840
goto out;
841+
}
837842
} else {
838843
inner_offset = sizeof(struct ipv6hdr);
839844
}
840845

841846
/* Checkin header including 8 bytes of inner protocol header. */
842-
if (!pskb_may_pull(skb, inner_offset+8))
847+
reason = pskb_may_pull_reason(skb, inner_offset + 8);
848+
if (reason != SKB_NOT_DROPPED_YET)
843849
goto out;
844850

845851
/* BUGGG_FUTURE: we should try to parse exthdrs in this packet.
@@ -854,10 +860,11 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
854860
ipprot->err_handler(skb, opt, type, code, inner_offset, info);
855861

856862
raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info);
857-
return;
863+
return SKB_CONSUMED;
858864

859865
out:
860866
__ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
867+
return reason;
861868
}
862869

863870
/*
@@ -953,15 +960,16 @@ static int icmpv6_rcv(struct sk_buff *skb)
953960
case ICMPV6_DEST_UNREACH:
954961
case ICMPV6_TIME_EXCEED:
955962
case ICMPV6_PARAMPROB:
956-
icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
963+
reason = icmpv6_notify(skb, type, hdr->icmp6_code,
964+
hdr->icmp6_mtu);
957965
break;
958966

959967
case NDISC_ROUTER_SOLICITATION:
960968
case NDISC_ROUTER_ADVERTISEMENT:
961969
case NDISC_NEIGHBOUR_SOLICITATION:
962970
case NDISC_NEIGHBOUR_ADVERTISEMENT:
963971
case NDISC_REDIRECT:
964-
ndisc_rcv(skb);
972+
reason = ndisc_rcv(skb);
965973
break;
966974

967975
case ICMPV6_MGM_QUERY:
@@ -995,7 +1003,8 @@ static int icmpv6_rcv(struct sk_buff *skb)
9951003
* must pass to upper level
9961004
*/
9971005

998-
icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
1006+
reason = icmpv6_notify(skb, type, hdr->icmp6_code,
1007+
hdr->icmp6_mtu);
9991008
}
10001009

10011010
/* until the v6 path can be better sorted assume failure and

net/ipv6/ndisc.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,15 +1804,16 @@ static bool ndisc_suppress_frag_ndisc(struct sk_buff *skb)
18041804
return false;
18051805
}
18061806

1807-
int ndisc_rcv(struct sk_buff *skb)
1807+
enum skb_drop_reason ndisc_rcv(struct sk_buff *skb)
18081808
{
18091809
struct nd_msg *msg;
1810+
SKB_DR(reason);
18101811

18111812
if (ndisc_suppress_frag_ndisc(skb))
1812-
return 0;
1813+
return SKB_DROP_REASON_IPV6_NDISC_FRAG;
18131814

18141815
if (skb_linearize(skb))
1815-
return 0;
1816+
return SKB_DROP_REASON_NOMEM;
18161817

18171818
msg = (struct nd_msg *)skb_transport_header(skb);
18181819

@@ -1821,13 +1822,13 @@ int ndisc_rcv(struct sk_buff *skb)
18211822
if (ipv6_hdr(skb)->hop_limit != 255) {
18221823
ND_PRINTK(2, warn, "NDISC: invalid hop-limit: %d\n",
18231824
ipv6_hdr(skb)->hop_limit);
1824-
return 0;
1825+
return SKB_DROP_REASON_IPV6_NDISC_HOP_LIMIT;
18251826
}
18261827

18271828
if (msg->icmph.icmp6_code != 0) {
18281829
ND_PRINTK(2, warn, "NDISC: invalid ICMPv6 code: %d\n",
18291830
msg->icmph.icmp6_code);
1830-
return 0;
1831+
return SKB_DROP_REASON_IPV6_NDISC_BAD_CODE;
18311832
}
18321833

18331834
switch (msg->icmph.icmp6_type) {
@@ -1853,7 +1854,7 @@ int ndisc_rcv(struct sk_buff *skb)
18531854
break;
18541855
}
18551856

1856-
return 0;
1857+
return reason;
18571858
}
18581859

18591860
static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)

0 commit comments

Comments
 (0)