Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 906cce04 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 7c5aba21 d57493d6
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -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);


+36 −2
Original line number Original line Diff line number Diff line
@@ -69,6 +69,9 @@ void *ife_decode(struct sk_buff *skb, u16 *metalen)
	int total_pull;
	int total_pull;
	u16 ifehdrln;
	u16 ifehdrln;


	if (!pskb_may_pull(skb, skb->dev->hard_header_len + IFE_METAHDRLEN))
		return NULL;

	ifehdr = (struct ifeheadr *) (skb->data + skb->dev->hard_header_len);
	ifehdr = (struct ifeheadr *) (skb->data + skb->dev->hard_header_len);
	ifehdrln = ntohs(ifehdr->metalen);
	ifehdrln = ntohs(ifehdr->metalen);
	total_pull = skb->dev->hard_header_len + ifehdrln;
	total_pull = skb->dev->hard_header_len + ifehdrln;
@@ -92,12 +95,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);


+7 −2
Original line number Original line Diff line number Diff line
@@ -652,7 +652,7 @@ static int find_decode_metaid(struct sk_buff *skb, struct tcf_ife_info *ife,
		}
		}
	}
	}


	return 0;
	return -ENOENT;
}
}


static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
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