|
@@ -914,6 +914,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
|
|
|
struct nlattr *opt = tca[TCA_OPTIONS];
|
|
|
struct nlattr *tb[TCA_U32_MAX + 1];
|
|
|
u32 htid, flags = 0;
|
|
|
+ size_t sel_size;
|
|
|
int err;
|
|
|
#ifdef CONFIG_CLS_U32_PERF
|
|
|
size_t size;
|
|
@@ -1076,8 +1077,13 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
|
|
|
}
|
|
|
|
|
|
s = nla_data(tb[TCA_U32_SEL]);
|
|
|
+ sel_size = struct_size(s, keys, s->nkeys);
|
|
|
+ if (nla_len(tb[TCA_U32_SEL]) < sel_size) {
|
|
|
+ err = -EINVAL;
|
|
|
+ goto erridr;
|
|
|
+ }
|
|
|
|
|
|
- n = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL);
|
|
|
+ n = kzalloc(offsetof(typeof(*n), sel) + sel_size, GFP_KERNEL);
|
|
|
if (n == NULL) {
|
|
|
err = -ENOBUFS;
|
|
|
goto erridr;
|
|
@@ -1092,7 +1098,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
|
|
|
+ memcpy(&n->sel, s, sel_size);
|
|
|
RCU_INIT_POINTER(n->ht_up, ht);
|
|
|
n->handle = handle;
|
|
|
n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;
|