Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d889ce3b authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller
Browse files

[IPv4]: Convert route get to 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 be403ea1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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 },
+45 −39
Original line number Diff line number Diff line
@@ -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.
@@ -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);
		struct net_device *dev;

		dev = __dev_get_by_index(iif);
		if (dev == NULL) {
			err = -ENODEV;
		if (!dev)
			goto out_free;
			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)
		if (err == 0 && rt->u.dst.error)
			err = -rt->u.dst.error;
	} else {
		struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst,
		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;
					.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)