[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: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									be403ea185
								
							
						
					
					
						commit
						d889ce3b29
					
				| @ -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); | ||||
|  | ||||
| @ -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 }, | ||||
|  | ||||
| @ -2737,18 +2737,24 @@ nla_put_failure: | ||||
| 
 | ||||
| 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); | ||||
| 		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) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user