Skip to content

Commit cc74edd

Browse files
Alexander Aringdavem330
authored andcommitted
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 <[email protected]> Reviewed-by: Yotam Gigi <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f6cd145 commit cc74edd

File tree

3 files changed

+41
-4
lines changed

3 files changed

+41
-4
lines changed

include/net/ife.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
void *ife_encode(struct sk_buff *skb, u16 metalen);
1313
void *ife_decode(struct sk_buff *skb, u16 *metalen);
1414

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);
1617
int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,
1718
const void *dval);
1819

net/ife/ife.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,43 @@ struct meta_tlvhdr {
9292
__be16 len;
9393
};
9494

95+
static bool __ife_tlv_meta_valid(const unsigned char *skbdata,
96+
const unsigned char *ifehdr_end)
97+
{
98+
const struct meta_tlvhdr *tlv;
99+
u16 tlvlen;
100+
101+
if (unlikely(skbdata + sizeof(*tlv) > ifehdr_end))
102+
return false;
103+
104+
tlv = (const struct meta_tlvhdr *)skbdata;
105+
tlvlen = ntohs(tlv->len);
106+
107+
/* tlv length field is inc header, check on minimum */
108+
if (tlvlen < NLA_HDRLEN)
109+
return false;
110+
111+
/* overflow by NLA_ALIGN check */
112+
if (NLA_ALIGN(tlvlen) < tlvlen)
113+
return false;
114+
115+
if (unlikely(skbdata + NLA_ALIGN(tlvlen) > ifehdr_end))
116+
return false;
117+
118+
return true;
119+
}
120+
95121
/* Caller takes care of presenting data in network order
96122
*/
97-
void *ife_tlv_meta_decode(void *skbdata, u16 *attrtype, u16 *dlen, u16 *totlen)
123+
void *ife_tlv_meta_decode(void *skbdata, const void *ifehdr_end, u16 *attrtype,
124+
u16 *dlen, u16 *totlen)
98125
{
99-
struct meta_tlvhdr *tlv = (struct meta_tlvhdr *) skbdata;
126+
struct meta_tlvhdr *tlv;
127+
128+
if (!__ife_tlv_meta_valid(skbdata, ifehdr_end))
129+
return NULL;
100130

131+
tlv = (struct meta_tlvhdr *)skbdata;
101132
*dlen = ntohs(tlv->len) - NLA_HDRLEN;
102133
*attrtype = ntohs(tlv->type);
103134

net/sched/act_ife.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,12 @@ static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
682682
u16 mtype;
683683
u16 dlen;
684684

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+
}
686691

687692
if (find_decode_metaid(skb, ife, mtype, dlen, curr_data)) {
688693
/* abuse overlimits to count when we receive metadata

0 commit comments

Comments
 (0)