Commit cc74eddd authored by Alexander Aring's avatar Alexander Aring Committed by David S. Miller

net: sched: ife: handle malformed tlv length

There is currently no handling to check on a invalid tlv length. This
patch adds such handling to avoid killing the kernel with a malformed
ife packet.
Signed-off-by: default avatarAlexander Aring <aring@mojatatu.com>
Reviewed-by: default avatarYotam Gigi <yotam.gi@gmail.com>
Acked-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f6cd1453
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
void *ife_encode(struct sk_buff *skb, u16 metalen); void *ife_encode(struct sk_buff *skb, u16 metalen);
void *ife_decode(struct sk_buff *skb, u16 *metalen); void *ife_decode(struct sk_buff *skb, u16 *metalen);
void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 *totlen); void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
u16 *dlen, u16 *totlen);
int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen, int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,
const void *dval); const void *dval);
......
...@@ -92,12 +92,43 @@ struct meta_tlvhdr { ...@@ -92,12 +92,43 @@ struct meta_tlvhdr {
__be16 len; __be16 len;
}; };
static bool __ife_tlv_meta_valid(const unsigned char *skbdata,
const unsigned char *ifehdr_end)
{
const struct meta_tlvhdr *tlv;
u16 tlvlen;
if (unlikely(skbdata + sizeof(*tlv) > ifehdr_end))
return false;
tlv = (const struct meta_tlvhdr *)skbdata;
tlvlen = ntohs(tlv->len);
/* tlv length field is inc header, check on minimum */
if (tlvlen < NLA_HDRLEN)
return false;
/* overflow by NLA_ALIGN check */
if (NLA_ALIGN(tlvlen) < tlvlen)
return false;
if (unlikely(skbdata + NLA_ALIGN(tlvlen) > ifehdr_end))
return false;
return true;
}
/* Caller takes care of presenting data in network order /* Caller takes care of presenting data in network order
*/ */
void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 *totlen) void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
u16 *dlen, u16 *totlen)
{ {
struct meta_tlvhdr *tlv = (struct meta_tlvhdr *) skbdata; struct meta_tlvhdr *tlv;
if (!__ife_tlv_meta_valid(skbdata, ifehdr_end))
return NULL;
tlv = (struct meta_tlvhdr *)skbdata;
*dlen = ntohs(tlv->len) - NLA_HDRLEN; *dlen = ntohs(tlv->len) - NLA_HDRLEN;
*attrtype = ntohs(tlv->type); *attrtype = ntohs(tlv->type);
......
...@@ -682,7 +682,12 @@ 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,
u16 mtype; u16 mtype;
u16 dlen; u16 dlen;
curr_data = ife_tlv_meta_decode(tlv_data, &mtype, &dlen, NULL); curr_data = ife_tlv_meta_decode(tlv_data, ifehdr_end, &mtype,
&dlen, NULL);
if (!curr_data) {
qstats_drop_inc(this_cpu_ptr(ife->common.cpu_qstats));
return TC_ACT_SHOT;
}
if (find_decode_metaid(skb, ife, mtype, dlen, curr_data)) { if (find_decode_metaid(skb, ife, mtype, dlen, curr_data)) {
/* abuse overlimits to count when we receive metadata /* abuse overlimits to count when we receive metadata
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment