Skip to content

Commit

Permalink
[IPv4]: Convert route get to new netlink api
Browse files Browse the repository at this point in the history
Fixes various unvalidated netlink attributes causing memory
corruptions when left empty by userspace applications.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Thomas Graf authored and David S. Miller committed Sep 22, 2006
1 parent be403ea commit d889ce3
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 40 deletions.
1 change: 1 addition & 0 deletions include/net/ip_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ extern void fib_select_default(const struct flowi *flp, struct fib_result *res);
#endif /* CONFIG_IP_MULTIPLE_TABLES */

/* Exported by fib_frontend.c */
extern struct nla_policy rtm_ipv4_policy[];
extern void ip_fib_init(void);
extern int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
extern int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg);
Expand Down
2 changes: 1 addition & 1 deletion net/ipv4/fib_frontend.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ int ip_rt_ioctl(unsigned int cmd, void *arg)

#endif

static struct nla_policy rtm_ipv4_policy[RTA_MAX+1] __read_mostly = {
struct nla_policy rtm_ipv4_policy[RTA_MAX+1] __read_mostly = {
[RTA_DST] = { .type = NLA_U32 },
[RTA_SRC] = { .type = NLA_U32 },
[RTA_IIF] = { .type = NLA_U32 },
Expand Down
84 changes: 45 additions & 39 deletions net/ipv4/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -2737,18 +2737,24 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,

int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
{
struct rtattr **rta = arg;
struct rtmsg *rtm = NLMSG_DATA(nlh);
struct rtmsg *rtm;
struct nlattr *tb[RTA_MAX+1];
struct rtable *rt = NULL;
u32 dst = 0;
u32 src = 0;
int iif = 0;
int err = -ENOBUFS;
u32 dst, src, iif;
int err;
struct sk_buff *skb;

err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);
if (err < 0)
goto errout;

rtm = nlmsg_data(nlh);

skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb)
goto out;
if (skb == NULL) {
err = -ENOBUFS;
goto errout;
}

/* Reserve room for dummy headers, this skb can pass
through good chunk of routing engine.
Expand All @@ -2759,61 +2765,61 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
skb->nh.iph->protocol = IPPROTO_ICMP;
skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));

if (rta[RTA_SRC - 1])
memcpy(&src, RTA_DATA(rta[RTA_SRC - 1]), 4);
if (rta[RTA_DST - 1])
memcpy(&dst, RTA_DATA(rta[RTA_DST - 1]), 4);
if (rta[RTA_IIF - 1])
memcpy(&iif, RTA_DATA(rta[RTA_IIF - 1]), sizeof(int));
src = tb[RTA_SRC] ? nla_get_u32(tb[RTA_SRC]) : 0;
dst = tb[RTA_DST] ? nla_get_u32(tb[RTA_DST]) : 0;
iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;

if (iif) {
struct net_device *dev = __dev_get_by_index(iif);
err = -ENODEV;
if (!dev)
goto out_free;
struct net_device *dev;

dev = __dev_get_by_index(iif);
if (dev == NULL) {
err = -ENODEV;
goto errout_free;
}

skb->protocol = htons(ETH_P_IP);
skb->dev = dev;
local_bh_disable();
err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
local_bh_enable();
rt = (struct rtable*)skb->dst;
if (!err && rt->u.dst.error)

rt = (struct rtable*) skb->dst;
if (err == 0 && rt->u.dst.error)
err = -rt->u.dst.error;
} else {
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst,
.saddr = src,
.tos = rtm->rtm_tos } } };
int oif = 0;
if (rta[RTA_OIF - 1])
memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));
fl.oif = oif;
struct flowi fl = {
.nl_u = {
.ip4_u = {
.daddr = dst,
.saddr = src,
.tos = rtm->rtm_tos,
},
},
.oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0,
};
err = ip_route_output_key(&rt, &fl);
}

if (err)
goto out_free;
goto errout_free;

skb->dst = &rt->u.dst;
if (rtm->rtm_flags & RTM_F_NOTIFY)
rt->rt_flags |= RTCF_NOTIFY;

NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;

err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
RTM_NEWROUTE, 0, 0);
if (!err)
goto out_free;
if (err < 0) {
err = -EMSGSIZE;
goto out_free;
}
if (err <= 0)
goto errout_free;

err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
out:
errout:
return err;

out_free:
errout_free:
kfree_skb(skb);
goto out;
goto errout;
}

int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
Expand Down

0 comments on commit d889ce3

Please sign in to comment.