diff options
author | David S. Miller <davem@davemloft.net> | 2018-04-22 21:12:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-04-22 21:12:00 -0400 |
commit | 906cce04e785b307a83e8cc1420cb38b496f5066 (patch) | |
tree | 5386270f315c29fb679d6247f53eae936656fbd4 | |
parent | 7c5aba211dd61f41d737a2c51729eb9fdcd3edf4 (diff) | |
parent | d57493d6d1be26c8ac8516a4463bfe24956978eb (diff) |
Merge branch 'net-sched-ife-malformed-ife-packet-fixes'
Alexander Aring says:
====================
net: sched: ife: malformed ife packet fixes
As promised at netdev 2.2 tc workshop I am working on adding scapy support for
tdc testing. It is still work in progress. I will submit the patches to tdc
later (they are not in good shape yet). The good news is I have been able to
find bugs which normal packet testing would not be able to find.
With fuzzy testing I was able to craft certain malformed packets that IFE
action was not able to deal with. This patch set fixes those bugs.
changes since v4:
- use pskb_may_pull before pointer assign
changes since v3:
- use pskb_may_pull
changes since v2:
- remove inline from __ife_tlv_meta_valid
- add const to cast to meta_tlvhdr
- add acked and reviewed tags
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/ife.h | 3 | ||||
-rw-r--r-- | net/ife/ife.c | 38 | ||||
-rw-r--r-- | net/sched/act_ife.c | 9 |
3 files changed, 45 insertions, 5 deletions
diff --git a/include/net/ife.h b/include/net/ife.h index 44b9c00f7223..e117617e3c34 100644 --- a/include/net/ife.h +++ b/include/net/ife.h | |||
@@ -12,7 +12,8 @@ | |||
12 | void *ife_encode(struct sk_buff *skb, u16 metalen); | 12 | void *ife_encode(struct sk_buff *skb, u16 metalen); |
13 | void *ife_decode(struct sk_buff *skb, u16 *metalen); | 13 | void *ife_decode(struct sk_buff *skb, u16 *metalen); |
14 | 14 | ||
15 | void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 *totlen); | 15 | void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype, |
16 | u16 *dlen, u16 *totlen); | ||
16 | int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen, | 17 | int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen, |
17 | const void *dval); | 18 | const void *dval); |
18 | 19 | ||
diff --git a/net/ife/ife.c b/net/ife/ife.c index 7d1ec76e7f43..13bbf8cb6a39 100644 --- a/net/ife/ife.c +++ b/net/ife/ife.c | |||
@@ -69,6 +69,9 @@ void *ife_decode(struct sk_buff *skb, u16 *metalen) | |||
69 | int total_pull; | 69 | int total_pull; |
70 | u16 ifehdrln; | 70 | u16 ifehdrln; |
71 | 71 | ||
72 | if (!pskb_may_pull(skb, skb->dev->hard_header_len + IFE_METAHDRLEN)) | ||
73 | return NULL; | ||
74 | |||
72 | ifehdr = (struct ifeheadr *) (skb->data + skb->dev->hard_header_len); | 75 | ifehdr = (struct ifeheadr *) (skb->data + skb->dev->hard_header_len); |
73 | ifehdrln = ntohs(ifehdr->metalen); | 76 | ifehdrln = ntohs(ifehdr->metalen); |
74 | total_pull = skb->dev->hard_header_len + ifehdrln; | 77 | total_pull = skb->dev->hard_header_len + ifehdrln; |
@@ -92,12 +95,43 @@ struct meta_tlvhdr { | |||
92 | __be16 len; | 95 | __be16 len; |
93 | }; | 96 | }; |
94 | 97 | ||
98 | static bool __ife_tlv_meta_valid(const unsigned char *skbdata, | ||
99 | const unsigned char *ifehdr_end) | ||
100 | { | ||
101 | const struct meta_tlvhdr *tlv; | ||
102 | u16 tlvlen; | ||
103 | |||
104 | if (unlikely(skbdata + sizeof(*tlv) > ifehdr_end)) | ||
105 | return false; | ||
106 | |||
107 | tlv = (const struct meta_tlvhdr *)skbdata; | ||
108 | tlvlen = ntohs(tlv->len); | ||
109 | |||
110 | /* tlv length field is inc header, check on minimum */ | ||
111 | if (tlvlen < NLA_HDRLEN) | ||
112 | return false; | ||
113 | |||
114 | /* overflow by NLA_ALIGN check */ | ||
115 | if (NLA_ALIGN(tlvlen) < tlvlen) | ||
116 | return false; | ||
117 | |||
118 | if (unlikely(skbdata + NLA_ALIGN(tlvlen) > ifehdr_end)) | ||
119 | return false; | ||
120 | |||
121 | return true; | ||
122 | } | ||
123 | |||
95 | /* Caller takes care of presenting data in network order | 124 | /* Caller takes care of presenting data in network order |
96 | */ | 125 | */ |
97 | void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 *totlen) | 126 | void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype, |
127 | u16 *dlen, u16 *totlen) | ||
98 | { | 128 | { |
99 | struct meta_tlvhdr *tlv = (struct meta_tlvhdr *) skbdata; | 129 | struct meta_tlvhdr *tlv; |
130 | |||
131 | if (!__ife_tlv_meta_valid(skbdata, ifehdr_end)) | ||
132 | return NULL; | ||
100 | 133 | ||
134 | tlv = (struct meta_tlvhdr *)skbdata; | ||
101 | *dlen = ntohs(tlv->len) - NLA_HDRLEN; | 135 | *dlen = ntohs(tlv->len) - NLA_HDRLEN; |
102 | *attrtype = ntohs(tlv->type); | 136 | *attrtype = ntohs(tlv->type); |
103 | 137 | ||
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index a5994cf0512b..8527cfdc446d 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c | |||
@@ -652,7 +652,7 @@ static int find_decode_metaid(struct sk_buff *skb, struct tcf_ife_info *ife, | |||
652 | } | 652 | } |
653 | } | 653 | } |
654 | 654 | ||
655 | return 0; | 655 | return -ENOENT; |
656 | } | 656 | } |
657 | 657 | ||
658 | static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, | 658 | static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, |
@@ -682,7 +682,12 @@ static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, | |||
682 | u16 mtype; | 682 | u16 mtype; |
683 | u16 dlen; | 683 | u16 dlen; |
684 | 684 | ||
685 | curr_data = ife_tlv_meta_decode(tlv_data, &mtype, &dlen, NULL); | 685 | curr_data = ife_tlv_meta_decode(tlv_data, ifehdr_end, &mtype, |
686 | &dlen, NULL); | ||
687 | if (!curr_data) { | ||
688 | qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats)); | ||
689 | return TC_ACT_SHOT; | ||
690 | } | ||
686 | 691 | ||
687 | if (find_decode_metaid(skb, ife, mtype, dlen, curr_data)) { | 692 | if (find_decode_metaid(skb, ife, mtype, dlen, curr_data)) { |
688 | /* abuse overlimits to count when we receive metadata | 693 | /* abuse overlimits to count when we receive metadata |