Commit ab364a6f authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller

[IPv6] route: Convert GETROUTE to use new netlink api

Fixes various unvalidated netlink attributes causing memory
corruptions when left empty by userspace applications.
Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2d7202bf
...@@ -1833,6 +1833,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu) ...@@ -1833,6 +1833,7 @@ void rt6_mtu_change(struct net_device *dev, unsigned mtu)
static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = { static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = {
[RTA_GATEWAY] = { .minlen = sizeof(struct in6_addr) }, [RTA_GATEWAY] = { .minlen = sizeof(struct in6_addr) },
[RTA_OIF] = { .type = NLA_U32 }, [RTA_OIF] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 },
[RTA_PRIORITY] = { .type = NLA_U32 }, [RTA_PRIORITY] = { .type = NLA_U32 },
[RTA_METRICS] = { .type = NLA_NESTED }, [RTA_METRICS] = { .type = NLA_NESTED },
}; };
...@@ -2048,68 +2049,75 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) ...@@ -2048,68 +2049,75 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg)
int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
{ {
struct rtattr **rta = arg; struct nlattr *tb[RTA_MAX+1];
int iif = 0; struct rt6_info *rt;
int err = -ENOBUFS;
struct sk_buff *skb; struct sk_buff *skb;
struct rtmsg *rtm;
struct flowi fl; struct flowi fl;
struct rt6_info *rt; int err, iif = 0;
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL)
goto out;
/* Reserve room for dummy headers, this skb can pass err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
through good chunk of routing engine. if (err < 0)
*/ goto errout;
skb->mac.raw = skb->data;
skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
err = -EINVAL;
memset(&fl, 0, sizeof(fl)); memset(&fl, 0, sizeof(fl));
if (rta[RTA_SRC-1])
ipv6_addr_copy(&fl.fl6_src,
(struct in6_addr*)RTA_DATA(rta[RTA_SRC-1]));
if (rta[RTA_DST-1])
ipv6_addr_copy(&fl.fl6_dst,
(struct in6_addr*)RTA_DATA(rta[RTA_DST-1]));
if (rta[RTA_IIF-1]) if (tb[RTA_SRC]) {
memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int)); if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
goto errout;
ipv6_addr_copy(&fl.fl6_src, nla_data(tb[RTA_SRC]));
}
if (tb[RTA_DST]) {
if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr))
goto errout;
ipv6_addr_copy(&fl.fl6_dst, nla_data(tb[RTA_DST]));
}
if (tb[RTA_IIF])
iif = nla_get_u32(tb[RTA_IIF]);
if (tb[RTA_OIF])
fl.oif = nla_get_u32(tb[RTA_OIF]);
if (iif) { if (iif) {
struct net_device *dev; struct net_device *dev;
dev = __dev_get_by_index(iif); dev = __dev_get_by_index(iif);
if (!dev) { if (!dev) {
err = -ENODEV; err = -ENODEV;
goto out_free; goto errout;
} }
} }
fl.oif = 0; skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (rta[RTA_OIF-1]) if (skb == NULL) {
memcpy(&fl.oif, RTA_DATA(rta[RTA_OIF-1]), sizeof(int)); err = -ENOBUFS;
goto errout;
}
rt = (struct rt6_info*)ip6_route_output(NULL, &fl); /* Reserve room for dummy headers, this skb can pass
through good chunk of routing engine.
*/
skb->mac.raw = skb->data;
skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
rt = (struct rt6_info*) ip6_route_output(NULL, &fl);
skb->dst = &rt->u.dst; skb->dst = &rt->u.dst;
NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif,
err = rt6_fill_node(skb, rt,
&fl.fl6_dst, &fl.fl6_src,
iif,
RTM_NEWROUTE, NETLINK_CB(in_skb).pid, RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
nlh->nlmsg_seq, 0, 0); nlh->nlmsg_seq, 0, 0);
if (err < 0) { if (err < 0) {
err = -EMSGSIZE; kfree_skb(skb);
goto out_free; goto errout;
} }
err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
out: errout:
return err; return err;
out_free:
kfree_skb(skb);
goto out;
} }
void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment