diff options
Diffstat (limited to 'net/ipv4/route.c')
| -rw-r--r-- | net/ipv4/route.c | 32 | 
1 files changed, 26 insertions, 6 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d35bbf0cf40..42cd979d163 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -500,7 +500,7 @@ void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more)  }  EXPORT_SYMBOL(__ip_select_ident); -static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk, +static void __build_flow_key(struct flowi4 *fl4, struct sock *sk,  			     const struct iphdr *iph,  			     int oif, u8 tos,  			     u8 prot, u32 mark, int flow_flags) @@ -516,11 +516,12 @@ static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk,  	flowi4_init_output(fl4, oif, mark, tos,  			   RT_SCOPE_UNIVERSE, prot,  			   flow_flags, -			   iph->daddr, iph->saddr, 0, 0); +			   iph->daddr, iph->saddr, 0, 0, +			   sk ? sock_i_uid(sk) : 0);  }  static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb, -			       const struct sock *sk) +			       struct sock *sk)  {  	const struct iphdr *iph = ip_hdr(skb);  	int oif = skb->dev->ifindex; @@ -531,7 +532,7 @@ static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,  	__build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0);  } -static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk) +static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk)  {  	const struct inet_sock *inet = inet_sk(sk);  	const struct ip_options_rcu *inet_opt; @@ -545,11 +546,12 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)  			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,  			   inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,  			   inet_sk_flowi_flags(sk), -			   daddr, inet->inet_saddr, 0, 0); +			   daddr, inet->inet_saddr, 0, 0, +			   sock_i_uid(sk));  	rcu_read_unlock();  } -static void ip_rt_build_flow_key(struct flowi4 *fl4, const struct sock *sk, +static void ip_rt_build_flow_key(struct flowi4 *fl4, struct sock *sk,  				 const struct sk_buff *skb)  {  	if (skb) @@ -956,6 +958,9 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,  	struct flowi4 fl4;  	struct rtable *rt; +	if (!mark) +		mark = IP4_REPLY_MARK(net, skb->mark); +  	__build_flow_key(&fl4, NULL, iph, oif,  			 RT_TOS(iph->tos), protocol, mark, flow_flags);  	rt = __ip_route_output_key(net, &fl4); @@ -973,6 +978,10 @@ static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)  	struct rtable *rt;  	__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); + +	if (!fl4.flowi4_mark) +		fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark); +  	rt = __ip_route_output_key(sock_net(sk), &fl4);  	if (!IS_ERR(rt)) {  		__ip_rt_update_pmtu(rt, &fl4, mtu); @@ -2280,6 +2289,11 @@ static int rt_fill_info(struct net *net,  __be32 dst, __be32 src,  	    nla_put_u32(skb, RTA_MARK, fl4->flowi4_mark))  		goto nla_put_failure; +	if (!uid_eq(fl4->flowi4_uid, INVALID_UID) && +	    nla_put_u32(skb, RTA_UID, +			from_kuid_munged(current_user_ns(), fl4->flowi4_uid))) +		goto nla_put_failure; +  	error = rt->dst.error;  	if (rt_is_input_route(rt)) { @@ -2329,6 +2343,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)  	int err;  	int mark;  	struct sk_buff *skb; +	kuid_t uid;  	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);  	if (err < 0) @@ -2356,6 +2371,10 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)  	dst = tb[RTA_DST] ? nla_get_be32(tb[RTA_DST]) : 0;  	iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0;  	mark = tb[RTA_MARK] ? nla_get_u32(tb[RTA_MARK]) : 0; +	if (tb[RTA_UID]) +		uid = make_kuid(current_user_ns(), nla_get_u32(tb[RTA_UID])); +	else +		uid = (iif ? INVALID_UID : current_uid());  	memset(&fl4, 0, sizeof(fl4));  	fl4.daddr = dst; @@ -2363,6 +2382,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)  	fl4.flowi4_tos = rtm->rtm_tos;  	fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0;  	fl4.flowi4_mark = mark; +	fl4.flowi4_uid = uid;  	if (iif) {  		struct net_device *dev;  |