Skip to content

Commit 98c8f12

Browse files
keesdavem330
authored andcommitted
net: sched: Fix memory exposure from short TCA_U32_SEL
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: Al Viro <viro@zeniv.linux.org.uk> Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: Cong Wang <xiyou.wangcong@gmail.com> Cc: Jiri Pirko <jiri@resnulli.us> Cc: "David S. Miller" <davem@davemloft.net> Cc: netdev@vger.kernel.org Signed-off-by: Kees Cook <keescook@chromium.org> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent e75d039 commit 98c8f12

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

net/sched/cls_u32.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
914914
struct nlattr *opt = tca[TCA_OPTIONS];
915915
struct nlattr *tb[TCA_U32_MAX + 1];
916916
u32 htid, flags = 0;
917+
size_t sel_size;
917918
int err;
918919
#ifdef CONFIG_CLS_U32_PERF
919920
size_t size;
@@ -1076,8 +1077,13 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
10761077
}
10771078

10781079
s = nla_data(tb[TCA_U32_SEL]);
1080+
sel_size = struct_size(s, keys, s->nkeys);
1081+
if (nla_len(tb[TCA_U32_SEL]) < sel_size) {
1082+
err = -EINVAL;
1083+
goto erridr;
1084+
}
10791085

1080-
n = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL);
1086+
n = kzalloc(offsetof(typeof(*n), sel) + sel_size, GFP_KERNEL);
10811087
if (n == NULL) {
10821088
err = -ENOBUFS;
10831089
goto erridr;
@@ -1092,7 +1098,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
10921098
}
10931099
#endif
10941100

1095-
memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
1101+
memcpy(&n->sel, s, sel_size);
10961102
RCU_INIT_POINTER(n->ht_up, ht);
10971103
n->handle = handle;
10981104
n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;

0 commit comments

Comments
 (0)