forked from luck/tmp_suning_uos_patched
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: Alexander Aring <aring@mojatatu.com> Reviewed-by: Yotam Gigi <yotam.gi@gmail.com> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f6cd14537f
commit
cc74eddd0f
|
@ -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 {
|
||||||
__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,
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user