Commit 7f1e6ec4 authored by Kees Cook's avatar Kees Cook Committed by Greg Kroah-Hartman

net: sched: Fix memory exposure from short TCA_U32_SEL

[ Upstream commit 98c8f125 ]

Via u32_change(), TCA_U32_SEL has an unspecified type in the netlink
policy, so max length isn't enforced, only minimum. This means nkeys
(from userspace) was being trusted without checking the actual size of
nla_len(), which could lead to a memory over-read, and ultimately an
exposure via a call to u32_dump(). Reachability is CAP_NET_ADMIN within
a namespace.
Reported-by: default avatarAl Viro <>
Cc: Jamal Hadi Salim <>
Cc: Cong Wang <>
Cc: Jiri Pirko <>
Cc: "David S. Miller" <>
Signed-off-by: default avatarKees Cook <>
Acked-by: default avatarJamal Hadi Salim <>
Signed-off-by: default avatarDavid S. Miller <>
Signed-off-by: default avatarGreg Kroah-Hartman <>
parent cb765f5c
......@@ -903,6 +903,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;
size_t size;
......@@ -1024,8 +1025,11 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
return -EINVAL;
s = nla_data(tb[TCA_U32_SEL]);
sel_size = sizeof(*s) + sizeof(*s->keys) * s->nkeys;
if (nla_len(tb[TCA_U32_SEL]) < sel_size)
return -EINVAL;
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)
return -ENOBUFS;
......@@ -1038,7 +1042,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
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;
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment