diff options
| author | mattis fjallstrom <mattis@acm.org> | 2015-05-21 12:00:33 -0700 | 
|---|---|---|
| committer | mattis fjallstrom <mattis@acm.org> | 2015-05-21 13:24:30 -0700 | 
| commit | 7d990a059acf5eb46ae99c058fc9911cbdce131d (patch) | |
| tree | ac9531b3ff2b2670dabc84c248a1770c84109586 /net | |
| parent | e8980e2a6a7392ae5a1f882d1ba01e03ac83f899 (diff) | |
| parent | 89fdc2c4bb83fff36199cd883a27efb317f02037 (diff) | |
| download | olio-linux-3.10-mattis_dev.tar.xz olio-linux-3.10-mattis_dev.zip  | |
Merge branch 'android-omap-minnow-3.10-lollipop-wear-release' of https://android.googlesource.com/kernel/omap into mattis_devmattis_dev
Change-Id: I46165dd7747b9b6289eb44cb96cbef2de46c10ba
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/fib_rules.c | 56 | ||||
| -rw-r--r-- | net/ipv4/fib_frontend.c | 1 | ||||
| -rw-r--r-- | net/ipv4/icmp.c | 11 | ||||
| -rw-r--r-- | net/ipv4/inet_connection_sock.c | 12 | ||||
| -rw-r--r-- | net/ipv4/ip_output.c | 6 | ||||
| -rw-r--r-- | net/ipv4/ping.c | 3 | ||||
| -rw-r--r-- | net/ipv4/raw.c | 3 | ||||
| -rw-r--r-- | net/ipv4/route.c | 32 | ||||
| -rw-r--r-- | net/ipv4/syncookies.c | 6 | ||||
| -rw-r--r-- | net/ipv4/sysctl_net_ipv4.c | 14 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 1 | ||||
| -rw-r--r-- | net/ipv4/udp.c | 3 | ||||
| -rw-r--r-- | net/ipv6/addrconf.c | 40 | ||||
| -rw-r--r-- | net/ipv6/af_inet6.c | 1 | ||||
| -rw-r--r-- | net/ipv6/ah6.c | 2 | ||||
| -rw-r--r-- | net/ipv6/datagram.c | 1 | ||||
| -rw-r--r-- | net/ipv6/esp6.c | 2 | ||||
| -rw-r--r-- | net/ipv6/icmp.c | 8 | ||||
| -rw-r--r-- | net/ipv6/inet6_connection_sock.c | 4 | ||||
| -rw-r--r-- | net/ipv6/ipcomp6.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ping.c | 2 | ||||
| -rw-r--r-- | net/ipv6/raw.c | 1 | ||||
| -rw-r--r-- | net/ipv6/route.c | 86 | ||||
| -rw-r--r-- | net/ipv6/syncookies.c | 5 | ||||
| -rw-r--r-- | net/ipv6/sysctl_net_ipv6.c | 7 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 3 | ||||
| -rw-r--r-- | net/ipv6/udp.c | 1 | 
27 files changed, 237 insertions, 76 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index d5a9f8ead0d..a40a876b855 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -31,6 +31,8 @@ int fib_default_rule_add(struct fib_rules_ops *ops,  	r->pref = pref;  	r->table = table;  	r->flags = flags; +	r->uid_start = INVALID_UID; +	r->uid_end = INVALID_UID;  	r->fr_net = hold_net(ops->fro_net);  	/* The lock is not required here, the list in unreacheable @@ -179,6 +181,23 @@ void fib_rules_unregister(struct fib_rules_ops *ops)  }  EXPORT_SYMBOL_GPL(fib_rules_unregister); +static inline kuid_t fib_nl_uid(struct nlattr *nla) +{ +	return make_kuid(current_user_ns(), nla_get_u32(nla)); +} + +static int nla_put_uid(struct sk_buff *skb, int idx, kuid_t uid) +{ +	return nla_put_u32(skb, idx, from_kuid_munged(current_user_ns(), uid)); +} + +static int fib_uid_range_match(struct flowi *fl, struct fib_rule *rule) +{ +	return (!uid_valid(rule->uid_start) && !uid_valid(rule->uid_end)) || +	       (uid_gte(fl->flowi_uid, rule->uid_start) && +		uid_lte(fl->flowi_uid, rule->uid_end)); +} +  static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,  			  struct flowi *fl, int flags)  { @@ -193,6 +212,9 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,  	if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask)  		goto out; +	if (!fib_uid_range_match(fl, rule)) +		goto out; +  	ret = ops->match(rule, fl, flags);  out:  	return (rule->flags & FIB_RULE_INVERT) ? !ret : ret; @@ -363,6 +385,19 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)  	} else if (rule->action == FR_ACT_GOTO)  		goto errout_free; +	/* UID start and end must either both be valid or both unspecified. */ +	rule->uid_start = rule->uid_end = INVALID_UID; +	if (tb[FRA_UID_START] || tb[FRA_UID_END]) { +		if (tb[FRA_UID_START] && tb[FRA_UID_END]) { +			rule->uid_start = fib_nl_uid(tb[FRA_UID_START]); +			rule->uid_end = fib_nl_uid(tb[FRA_UID_END]); +		} +		if (!uid_valid(rule->uid_start) || +		    !uid_valid(rule->uid_end) || +		    !uid_lte(rule->uid_start, rule->uid_end)) +		goto errout_free; +	} +  	err = ops->configure(rule, skb, frh, tb);  	if (err < 0)  		goto errout_free; @@ -445,7 +480,8 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)  		if (frh->action && (frh->action != rule->action))  			continue; -		if (frh->table && (frh_get_table(frh, tb) != rule->table)) +		if (frh_get_table(frh, tb) && +		    (frh_get_table(frh, tb) != rule->table))  			continue;  		if (tb[FRA_PRIORITY] && @@ -468,6 +504,14 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)  		    (rule->mark_mask != nla_get_u32(tb[FRA_FWMASK])))  			continue; +		if (tb[FRA_UID_START] && +		    !uid_eq(rule->uid_start, fib_nl_uid(tb[FRA_UID_START]))) +			continue; + +		if (tb[FRA_UID_END] && +		    !uid_eq(rule->uid_end, fib_nl_uid(tb[FRA_UID_END]))) +			continue; +  		if (!ops->compare(rule, frh, tb))  			continue; @@ -524,7 +568,9 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,  			 + nla_total_size(4) /* FRA_PRIORITY */  			 + nla_total_size(4) /* FRA_TABLE */  			 + nla_total_size(4) /* FRA_FWMARK */ -			 + nla_total_size(4); /* FRA_FWMASK */ +			 + nla_total_size(4) /* FRA_FWMASK */ +			 + nla_total_size(4) /* FRA_UID_START */ +			 + nla_total_size(4); /* FRA_UID_END */  	if (ops->nlmsg_payload)  		payload += ops->nlmsg_payload(rule); @@ -578,7 +624,11 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,  	    ((rule->mark_mask || rule->mark) &&  	     nla_put_u32(skb, FRA_FWMASK, rule->mark_mask)) ||  	    (rule->target && -	     nla_put_u32(skb, FRA_GOTO, rule->target))) +	     nla_put_u32(skb, FRA_GOTO, rule->target)) || +	    (uid_valid(rule->uid_start) && +	     nla_put_uid(skb, FRA_UID_START, rule->uid_start)) || +	    (uid_valid(rule->uid_end) && +	     nla_put_uid(skb, FRA_UID_END, rule->uid_end)))  		goto nla_put_failure;  	if (ops->fill(rule, skb, frh) < 0)  		goto nla_put_failure; diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index c7629a209f9..ffffeb448ec 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -531,6 +531,7 @@ const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = {  	[RTA_METRICS]		= { .type = NLA_NESTED },  	[RTA_MULTIPATH]		= { .len = sizeof(struct rtnexthop) },  	[RTA_FLOW]		= { .type = NLA_U32 }, +	[RTA_UID]		= { .type = NLA_U32 },  };  static int rtm_to_fib_config(struct net *net, struct sk_buff *skb, diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 562efd91f45..cc38f44306e 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -337,6 +337,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)  	struct sock *sk;  	struct inet_sock *inet;  	__be32 daddr, saddr; +	u32 mark = IP4_REPLY_MARK(net, skb->mark);  	if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb))  		return; @@ -349,6 +350,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)  	icmp_param->data.icmph.checksum = 0;  	inet->tos = ip_hdr(skb)->tos; +	sk->sk_mark = mark;  	daddr = ipc.addr = ip_hdr(skb)->saddr;  	saddr = fib_compute_spec_dst(skb);  	ipc.opt = NULL; @@ -361,6 +363,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)  	memset(&fl4, 0, sizeof(fl4));  	fl4.daddr = daddr;  	fl4.saddr = saddr; +	fl4.flowi4_mark = mark;  	fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);  	fl4.flowi4_proto = IPPROTO_ICMP;  	security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); @@ -379,7 +382,7 @@ static struct rtable *icmp_route_lookup(struct net *net,  					struct flowi4 *fl4,  					struct sk_buff *skb_in,  					const struct iphdr *iph, -					__be32 saddr, u8 tos, +					__be32 saddr, u8 tos, u32 mark,  					int type, int code,  					struct icmp_bxm *param)  { @@ -391,6 +394,7 @@ static struct rtable *icmp_route_lookup(struct net *net,  	fl4->daddr = (param->replyopts.opt.opt.srr ?  		      param->replyopts.opt.opt.faddr : iph->saddr);  	fl4->saddr = saddr; +	fl4->flowi4_mark = mark;  	fl4->flowi4_tos = RT_TOS(tos);  	fl4->flowi4_proto = IPPROTO_ICMP;  	fl4->fl4_icmp_type = type; @@ -488,6 +492,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)  	struct flowi4 fl4;  	__be32 saddr;  	u8  tos; +	u32 mark;  	struct net *net;  	struct sock *sk; @@ -584,6 +589,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)  	tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) |  					   IPTOS_PREC_INTERNETCONTROL) :  					  iph->tos; +	mark = IP4_REPLY_MARK(net, skb_in->mark);  	if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in))  		goto out_unlock; @@ -600,11 +606,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)  	icmp_param.skb	  = skb_in;  	icmp_param.offset = skb_network_offset(skb_in);  	inet_sk(sk)->tos = tos; +	sk->sk_mark = mark;  	ipc.addr = iph->saddr;  	ipc.opt = &icmp_param.replyopts.opt;  	ipc.tx_flags = 0; -	rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, +	rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, mark,  			       type, code, &icmp_param);  	if (IS_ERR(rt))  		goto out_unlock; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 6acb541c909..6dfec2f1821 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -417,12 +417,13 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,  	struct net *net = sock_net(sk);  	int flags = inet_sk_flowi_flags(sk); -	flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, +	flowi4_init_output(fl4, sk->sk_bound_dev_if, ireq->ir_mark,  			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,  			   sk->sk_protocol,  			   flags,  			   (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr, -			   ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport); +			   ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport, +			   sock_i_uid(sk));  	security_req_classify_flow(req, flowi4_to_flowi(fl4));  	rt = ip_route_output_flow(net, fl4, sk);  	if (IS_ERR(rt)) @@ -454,11 +455,12 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,  	rcu_read_lock();  	opt = rcu_dereference(newinet->inet_opt); -	flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, +	flowi4_init_output(fl4, sk->sk_bound_dev_if, inet_rsk(req)->ir_mark,  			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,  			   sk->sk_protocol, inet_sk_flowi_flags(sk),  			   (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr, -			   ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport); +			   ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport, +			   sock_i_uid(sk));  	security_req_classify_flow(req, flowi4_to_flowi(fl4));  	rt = ip_route_output_flow(net, fl4, sk);  	if (IS_ERR(rt)) @@ -688,6 +690,8 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,  		inet_sk(newsk)->inet_sport = inet_rsk(req)->loc_port;  		newsk->sk_write_space = sk_stream_write_space; +		newsk->sk_mark = inet_rsk(req)->ir_mark; +  		newicsk->icsk_retransmits = 0;  		newicsk->icsk_backoff	  = 0;  		newicsk->icsk_probes_out  = 0; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 4bcabf3ab4c..8e20e940558 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1497,12 +1497,14 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,  			daddr = replyopts.opt.opt.faddr;  	} -	flowi4_init_output(&fl4, arg->bound_dev_if, 0, +	flowi4_init_output(&fl4, arg->bound_dev_if, +			   IP4_REPLY_MARK(net, skb->mark),  			   RT_TOS(arg->tos),  			   RT_SCOPE_UNIVERSE, ip_hdr(skb)->protocol,  			   ip_reply_arg_flowi_flags(arg),  			   daddr, saddr, -			   tcp_hdr(skb)->source, tcp_hdr(skb)->dest); +			   tcp_hdr(skb)->source, tcp_hdr(skb)->dest, +			   arg->uid);  	security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));  	rt = ip_route_output_key(net, &fl4);  	if (IS_ERR(rt)) diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 111e5a40959..b83d82951ca 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -768,7 +768,8 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,  	flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,  			   RT_SCOPE_UNIVERSE, sk->sk_protocol, -			   inet_sk_flowi_flags(sk), faddr, saddr, 0, 0); +			   inet_sk_flowi_flags(sk), faddr, saddr, 0, 0, +			   sock_i_uid(sk));  	security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));  	rt = ip_route_output_flow(net, &fl4, sk); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index dd44e0ab600..b8287330c57 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -572,7 +572,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,  			   RT_SCOPE_UNIVERSE,  			   inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,  			   inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP, -			   daddr, saddr, 0, 0); +			   daddr, saddr, 0, 0, +			   sock_i_uid(sk));  	if (!inet->hdrincl) {  		err = raw_probe_proto_opt(&fl4, msg); 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; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index b05c96e7af8..c94032b95c6 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -312,6 +312,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,  	ireq->rmt_port		= th->source;  	ireq->loc_addr		= ip_hdr(skb)->daddr;  	ireq->rmt_addr		= ip_hdr(skb)->saddr; +	ireq->ir_mark		= inet_request_mark(sk, skb);  	ireq->ecn_ok		= ecn_ok;  	ireq->snd_wscale	= tcp_opt.snd_wscale;  	ireq->sack_ok		= tcp_opt.sack_ok; @@ -348,11 +349,12 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,  	 * hasn't changed since we received the original syn, but I see  	 * no easy way to do this.  	 */ -	flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark, +	flowi4_init_output(&fl4, sk->sk_bound_dev_if, ireq->ir_mark,  			   RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,  			   inet_sk_flowi_flags(sk),  			   (opt && opt->srr) ? opt->faddr : ireq->rmt_addr, -			   ireq->loc_addr, th->source, th->dest); +			   ireq->loc_addr, th->source, th->dest, +			   sock_i_uid(sk));  	security_req_classify_flow(req, flowi4_to_flowi(&fl4));  	rt = ip_route_output_key(sock_net(sk), &fl4);  	if (IS_ERR(rt)) { diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index f9bb5d7488e..cc5fa7da12e 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -859,6 +859,20 @@ static struct ctl_table ipv4_net_table[] = {  		.mode		= 0644,  		.proc_handler	= ipv4_tcp_mem,  	}, +	{ +		.procname	= "fwmark_reflect", +		.data		= &init_net.ipv4.sysctl_fwmark_reflect, +		.maxlen		= sizeof(int), +		.mode		= 0644, +		.proc_handler	= proc_dointvec, +	}, +	{ +		.procname	= "tcp_fwmark_accept", +		.data		= &init_net.ipv4.sysctl_tcp_fwmark_accept, +		.maxlen		= sizeof(int), +		.mode		= 0644, +		.proc_handler	= proc_dointvec, +	},  	{ }  }; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 7999fc55c83..40ec14507f7 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1527,6 +1527,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)  	ireq->rmt_addr = saddr;  	ireq->no_srccheck = inet_sk(sk)->transparent;  	ireq->opt = tcp_v4_save_options(skb); +	ireq->ir_mark = inet_request_mark(sk, skb);  	if (security_inet_conn_request(sk, skb, req))  		goto drop_and_free; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 0bf5d399a03..35ab330ed95 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -962,7 +962,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,  		flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos,  				   RT_SCOPE_UNIVERSE, sk->sk_protocol,  				   inet_sk_flowi_flags(sk)|FLOWI_FLAG_CAN_SLEEP, -				   faddr, saddr, dport, inet->inet_sport); +				   faddr, saddr, dport, inet->inet_sport, +				   sock_i_uid(sk));  		security_sk_classify_flow(sk, flowi4_to_flowi(fl4));  		rt = ip_route_output_flow(net, fl4, sk); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4ab4c38958c..cec8cb4d292 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -198,6 +198,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {  	.accept_ra_rt_info_max_plen = 0,  #endif  #endif +	.accept_ra_rt_table	= 0,  	.proxy_ndp		= 0,  	.accept_source_route	= 0,	/* we do not accept RH0 by default. */  	.disable_ipv6		= 0, @@ -232,6 +233,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {  	.accept_ra_rt_info_max_plen = 0,  #endif  #endif +	.accept_ra_rt_table	= 0,  	.proxy_ndp		= 0,  	.accept_source_route	= 0,	/* we do not accept RH0 by default. */  	.disable_ipv6		= 0, @@ -1910,6 +1912,31 @@ static void  __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmp  }  #endif +u32 addrconf_rt_table(const struct net_device *dev, u32 default_table) { +	/* Determines into what table to put autoconf PIO/RIO/default routes +	 * learned on this device. +	 * +	 * - If 0, use the same table for every device. This puts routes into +	 *   one of RT_TABLE_{PREFIX,INFO,DFLT} depending on the type of route +	 *   (but note that these three are currently all equal to +	 *   RT6_TABLE_MAIN). +	 * - If > 0, use the specified table. +	 * - If < 0, put routes into table dev->ifindex + (-rt_table). +	 */ +	struct inet6_dev *idev = in6_dev_get(dev); +	u32 table; +	int sysctl = idev->cnf.accept_ra_rt_table; +	if (sysctl == 0) { +		table = default_table; +	} else if (sysctl > 0) { +		table = (u32) sysctl; +	} else { +		table = (unsigned) dev->ifindex + (-sysctl); +	} +	in6_dev_put(idev); +	return table; +} +  /*   *	Add prefix route.   */ @@ -1919,7 +1946,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,  		      unsigned long expires, u32 flags)  {  	struct fib6_config cfg = { -		.fc_table = RT6_TABLE_PREFIX, +		.fc_table = addrconf_rt_table(dev, RT6_TABLE_PREFIX),  		.fc_metric = IP6_RT_PRIO_ADDRCONF,  		.fc_ifindex = dev->ifindex,  		.fc_expires = expires, @@ -1953,7 +1980,8 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,  	struct rt6_info *rt = NULL;  	struct fib6_table *table; -	table = fib6_get_table(dev_net(dev), RT6_TABLE_PREFIX); +	table = fib6_get_table(dev_net(dev), +			       addrconf_rt_table(dev, RT6_TABLE_PREFIX));  	if (table == NULL)  		return NULL; @@ -4159,6 +4187,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,  	array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;  #endif  #endif +	array[DEVCONF_ACCEPT_RA_RT_TABLE] = cnf->accept_ra_rt_table;  	array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;  	array[DEVCONF_ACCEPT_SOURCE_ROUTE] = cnf->accept_source_route;  #ifdef CONFIG_IPV6_OPTIMISTIC_DAD @@ -4868,6 +4897,13 @@ static struct addrconf_sysctl_table  #endif  #endif  		{ +			.procname	= "accept_ra_rt_table", +			.data		= &ipv6_devconf.accept_ra_rt_table, +			.maxlen		= sizeof(int), +			.mode		= 0644, +			.proc_handler	= proc_dointvec, +		}, +		{  			.procname	= "proxy_ndp",  			.data		= &ipv6_devconf.proxy_ndp,  			.maxlen		= sizeof(int), diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index f0081f9cc84..ae17f62189a 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -695,6 +695,7 @@ int inet6_sk_rebuild_header(struct sock *sk)  		fl6.flowi6_mark = sk->sk_mark;  		fl6.fl6_dport = inet->inet_dport;  		fl6.fl6_sport = inet->inet_sport; +		fl6.flowi6_uid = sock_i_uid(sk);  		security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));  		final_p = fl6_update_dst(&fl6, np->opt, &final); diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index bb02e176cb7..b903e19463c 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -630,7 +630,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,  	if (type == NDISC_REDIRECT)  		ip6_redirect(skb, net, 0, 0);  	else -		ip6_update_pmtu(skb, net, info, 0, 0); +		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);  	xfrm_state_put(x);  } diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 4b56cbbc789..00b4a5f6eea 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -162,6 +162,7 @@ ipv4_connected:  	fl6.flowi6_mark = sk->sk_mark;  	fl6.fl6_dport = inet->inet_dport;  	fl6.fl6_sport = inet->inet_sport; +	fl6.flowi6_uid = sock_i_uid(sk);  	if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST))  		fl6.flowi6_oif = np->mcast_oif; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 40ffd72243a..fdc81cb29e8 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -449,7 +449,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,  	if (type == NDISC_REDIRECT)  		ip6_redirect(skb, net, 0, 0);  	else -		ip6_update_pmtu(skb, net, info, 0, 0); +		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);  	xfrm_state_put(x);  } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 1d2902e6178..12b1a942dc9 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -90,7 +90,7 @@ static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,  	struct net *net = dev_net(skb->dev);  	if (type == ICMPV6_PKT_TOOBIG) -		ip6_update_pmtu(skb, net, info, 0, 0); +		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);  	else if (type == NDISC_REDIRECT)  		ip6_redirect(skb, net, 0, 0); @@ -397,6 +397,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)  	int len;  	int hlimit;  	int err = 0; +	u32 mark = IP6_REPLY_MARK(net, skb->mark);  	if ((u8 *)hdr < skb->head ||  	    (skb->network_header + sizeof(*hdr)) > skb->tail) @@ -462,6 +463,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)  	fl6.daddr = hdr->saddr;  	if (saddr)  		fl6.saddr = *saddr; +	fl6.flowi6_mark = mark;  	fl6.flowi6_oif = iif;  	fl6.fl6_icmp_type = type;  	fl6.fl6_icmp_code = code; @@ -470,6 +472,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)  	sk = icmpv6_xmit_lock(net);  	if (sk == NULL)  		return; +	sk->sk_mark = mark;  	np = inet6_sk(sk);  	if (!icmpv6_xrlim_allow(sk, type, &fl6)) @@ -551,6 +554,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)  	struct dst_entry *dst;  	int err = 0;  	int hlimit; +	u32 mark = IP6_REPLY_MARK(net, skb->mark);  	saddr = &ipv6_hdr(skb)->daddr; @@ -567,11 +571,13 @@ static void icmpv6_echo_reply(struct sk_buff *skb)  		fl6.saddr = *saddr;  	fl6.flowi6_oif = skb->dev->ifindex;  	fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY; +	fl6.flowi6_mark = mark;  	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));  	sk = icmpv6_xmit_lock(net);  	if (sk == NULL)  		return; +	sk->sk_mark = mark;  	np = inet6_sk(sk);  	if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index e4311cbc8b4..65a46058c85 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -81,9 +81,10 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk,  	final_p = fl6_update_dst(fl6, np->opt, &final);  	fl6->saddr = treq->loc_addr;  	fl6->flowi6_oif = treq->iif; -	fl6->flowi6_mark = sk->sk_mark; +	fl6->flowi6_mark = inet_rsk(req)->ir_mark;  	fl6->fl6_dport = inet_rsk(req)->rmt_port;  	fl6->fl6_sport = inet_rsk(req)->loc_port; +	fl6->flowi6_uid = sock_i_uid(sk);  	security_req_classify_flow(req, flowi6_to_flowi(fl6));  	dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); @@ -211,6 +212,7 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,  	fl6->flowi6_mark = sk->sk_mark;  	fl6->fl6_sport = inet->inet_sport;  	fl6->fl6_dport = inet->inet_dport; +	fl6->flowi6_uid = sock_i_uid(sk);  	security_sk_classify_flow(sk, flowi6_to_flowi(fl6));  	final_p = fl6_update_dst(fl6, np->opt, &final); diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 7af5aee75d9..a1beb59a841 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -78,7 +78,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,  	if (type == NDISC_REDIRECT)  		ip6_redirect(skb, net, 0, 0);  	else -		ip6_update_pmtu(skb, net, info, 0, 0); +		ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);  	xfrm_state_put(x);  } diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index e2cc17cd1cf..5f0d294b36c 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c @@ -158,6 +158,8 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,  	fl6.flowi6_proto = IPPROTO_ICMPV6;  	fl6.saddr = np->saddr;  	fl6.daddr = *daddr; +	fl6.flowi6_mark = sk->sk_mark; +	fl6.flowi6_uid = sock_i_uid(sk);  	fl6.fl6_icmp_type = user_icmph.icmp6_type;  	fl6.fl6_icmp_code = user_icmph.icmp6_code;  	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index eedff8ccded..dfef31581f8 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -761,6 +761,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,  	memset(&fl6, 0, sizeof(fl6));  	fl6.flowi6_mark = sk->sk_mark; +	fl6.flowi6_uid = sock_i_uid(sk);  	if (sin6) {  		if (addr_len < SIN6_LEN_RFC2133) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index ad0aa6b0b86..bad36468dcd 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -85,13 +85,12 @@ static void		rt6_do_redirect(struct dst_entry *dst, struct sock *sk,  					struct sk_buff *skb);  #ifdef CONFIG_IPV6_ROUTE_INFO -static struct rt6_info *rt6_add_route_info(struct net *net, +static struct rt6_info *rt6_add_route_info(struct net_device *dev,  					   const struct in6_addr *prefix, int prefixlen, -					   const struct in6_addr *gwaddr, int ifindex, -					   unsigned int pref); -static struct rt6_info *rt6_get_route_info(struct net *net, +					   const struct in6_addr *gwaddr, unsigned int pref); +static struct rt6_info *rt6_get_route_info(struct net_device *dev,  					   const struct in6_addr *prefix, int prefixlen, -					   const struct in6_addr *gwaddr, int ifindex); +					   const struct in6_addr *gwaddr);  #endif  static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) @@ -643,7 +642,6 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)  int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,  		  const struct in6_addr *gwaddr)  { -	struct net *net = dev_net(dev);  	struct route_info *rinfo = (struct route_info *) opt;  	struct in6_addr prefix_buf, *prefix;  	unsigned int pref; @@ -685,8 +683,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,  		prefix = &prefix_buf;  	} -	rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr, -				dev->ifindex); +	rt = rt6_get_route_info(dev, prefix, rinfo->prefix_len, gwaddr);  	if (rt && !lifetime) {  		ip6_del_rt(rt); @@ -694,8 +691,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,  	}  	if (!rt && lifetime) -		rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex, -					pref); +		rt = rt6_add_route_info(dev, prefix, rinfo->prefix_len, gwaddr, pref);  	else if (rt)  		rt->rt6i_flags = RTF_ROUTEINFO |  				 (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); @@ -1103,7 +1099,7 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,  }  void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, -		     int oif, u32 mark) +		     int oif, u32 mark, kuid_t uid)  {  	const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;  	struct dst_entry *dst; @@ -1111,11 +1107,12 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,  	memset(&fl6, 0, sizeof(fl6));  	fl6.flowi6_oif = oif; -	fl6.flowi6_mark = mark; +	fl6.flowi6_mark = mark ? mark : IP6_REPLY_MARK(net, skb->mark);  	fl6.flowi6_flags = 0;  	fl6.daddr = iph->daddr;  	fl6.saddr = iph->saddr;  	fl6.flowlabel = ip6_flowinfo(iph); +	fl6.flowi6_uid = uid;  	dst = ip6_route_output(net, NULL, &fl6);  	if (!dst->error) @@ -1127,7 +1124,7 @@ EXPORT_SYMBOL_GPL(ip6_update_pmtu);  void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)  {  	ip6_update_pmtu(skb, sock_net(sk), mtu, -			sk->sk_bound_dev_if, sk->sk_mark); +			sk->sk_bound_dev_if, sk->sk_mark, sock_i_uid(sk));  }  EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu); @@ -1796,15 +1793,16 @@ static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,  }  #ifdef CONFIG_IPV6_ROUTE_INFO -static struct rt6_info *rt6_get_route_info(struct net *net, +static struct rt6_info *rt6_get_route_info(struct net_device *dev,  					   const struct in6_addr *prefix, int prefixlen, -					   const struct in6_addr *gwaddr, int ifindex) +					   const struct in6_addr *gwaddr)  {  	struct fib6_node *fn;  	struct rt6_info *rt = NULL;  	struct fib6_table *table; -	table = fib6_get_table(net, RT6_TABLE_INFO); +	table = fib6_get_table(dev_net(dev), +			       addrconf_rt_table(dev, RT6_TABLE_INFO));  	if (!table)  		return NULL; @@ -1814,7 +1812,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net,  		goto out;  	for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { -		if (rt->dst.dev->ifindex != ifindex) +		if (rt->dst.dev->ifindex != dev->ifindex)  			continue;  		if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))  			continue; @@ -1828,21 +1826,20 @@ out:  	return rt;  } -static struct rt6_info *rt6_add_route_info(struct net *net, +static struct rt6_info *rt6_add_route_info(struct net_device *dev,  					   const struct in6_addr *prefix, int prefixlen, -					   const struct in6_addr *gwaddr, int ifindex, -					   unsigned int pref) +					   const struct in6_addr *gwaddr, unsigned int pref)  {  	struct fib6_config cfg = { -		.fc_table	= RT6_TABLE_INFO, +		.fc_table	= addrconf_rt_table(dev, RT6_TABLE_INFO),  		.fc_metric	= IP6_RT_PRIO_USER, -		.fc_ifindex	= ifindex, +		.fc_ifindex	= dev->ifindex,  		.fc_dst_len	= prefixlen,  		.fc_flags	= RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |  				  RTF_UP | RTF_PREF(pref),  		.fc_nlinfo.portid = 0,  		.fc_nlinfo.nlh = NULL, -		.fc_nlinfo.nl_net = net, +		.fc_nlinfo.nl_net = dev_net(dev),  	};  	cfg.fc_dst = *prefix; @@ -1854,7 +1851,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net,  	ip6_route_add(&cfg); -	return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex); +	return rt6_get_route_info(dev, prefix, prefixlen, gwaddr);  }  #endif @@ -1863,7 +1860,8 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev  	struct rt6_info *rt;  	struct fib6_table *table; -	table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT); +	table = fib6_get_table(dev_net(dev), +			       addrconf_rt_table(dev, RT6_TABLE_MAIN));  	if (!table)  		return NULL; @@ -1885,7 +1883,7 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,  				     unsigned int pref)  {  	struct fib6_config cfg = { -		.fc_table	= RT6_TABLE_DFLT, +		.fc_table	= addrconf_rt_table(dev, RT6_TABLE_DFLT),  		.fc_metric	= IP6_RT_PRIO_USER,  		.fc_ifindex	= dev->ifindex,  		.fc_flags	= RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | @@ -1902,28 +1900,17 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,  	return rt6_get_dflt_router(gwaddr, dev);  } -void rt6_purge_dflt_routers(struct net *net) -{ -	struct rt6_info *rt; -	struct fib6_table *table; -	/* NOTE: Keep consistent with rt6_get_dflt_router */ -	table = fib6_get_table(net, RT6_TABLE_DFLT); -	if (!table) -		return; +int rt6_addrconf_purge(struct rt6_info *rt, void *arg) { +	if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) && +	    (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) +		return -1; +	return 0; +} -restart: -	read_lock_bh(&table->tb6_lock); -	for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { -		if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) && -		    (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) { -			dst_hold(&rt->dst); -			read_unlock_bh(&table->tb6_lock); -			ip6_del_rt(rt); -			goto restart; -		} -	} -	read_unlock_bh(&table->tb6_lock); +void rt6_purge_dflt_routers(struct net *net) +{ +	fib6_clean_all(net, rt6_addrconf_purge, 0, NULL);  }  static void rtmsg_to_fib6_config(struct net *net, @@ -2213,6 +2200,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {  	[RTA_PRIORITY]          = { .type = NLA_U32 },  	[RTA_METRICS]           = { .type = NLA_NESTED },  	[RTA_MULTIPATH]		= { .len = sizeof(struct rtnexthop) }, +	[RTA_UID]		= { .type = NLA_U32 },  };  static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, @@ -2599,6 +2587,12 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh)  	if (tb[RTA_OIF])  		oif = nla_get_u32(tb[RTA_OIF]); +	if (tb[RTA_UID]) +		fl6.flowi6_uid = make_kuid(current_user_ns(), +					   nla_get_u32(tb[RTA_UID])); +	else +		fl6.flowi6_uid = iif ? INVALID_UID : current_uid(); +  	if (iif) {  		struct net_device *dev;  		int flags = 0; diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index d5dda20bd71..ba8622daffd 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -212,6 +212,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)  	    ipv6_addr_type(&ireq6->rmt_addr) & IPV6_ADDR_LINKLOCAL)  		ireq6->iif = inet6_iif(skb); +	ireq->ir_mark = inet_request_mark(sk, skb); +  	req->expires = 0UL;  	req->num_retrans = 0;  	ireq->ecn_ok		= ecn_ok; @@ -238,9 +240,10 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)  		final_p = fl6_update_dst(&fl6, np->opt, &final);  		fl6.saddr = ireq6->loc_addr;  		fl6.flowi6_oif = sk->sk_bound_dev_if; -		fl6.flowi6_mark = sk->sk_mark; +		fl6.flowi6_mark = ireq->ir_mark;  		fl6.fl6_dport = inet_rsk(req)->rmt_port;  		fl6.fl6_sport = inet_sk(sk)->inet_sport; +		fl6.flowi6_uid = sock_i_uid(sk);  		security_req_classify_flow(req, flowi6_to_flowi(&fl6));  		dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index e85c48bd404..53a9f5a6453 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c @@ -24,6 +24,13 @@ static ctl_table ipv6_table_template[] = {  		.mode		= 0644,  		.proc_handler	= proc_dointvec  	}, +	{ +		.procname	= "fwmark_reflect", +		.data		= &init_net.ipv6.sysctl.fwmark_reflect, +		.maxlen		= sizeof(int), +		.mode		= 0644, +		.proc_handler	= proc_dointvec +	},  	{ }  }; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0a17ed9eaf3..a4fc647deb0 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -252,6 +252,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,  	fl6.flowi6_mark = sk->sk_mark;  	fl6.fl6_dport = usin->sin6_port;  	fl6.fl6_sport = inet->inet_sport; +	fl6.flowi6_uid = sock_i_uid(sk);  	final_p = fl6_update_dst(&fl6, np->opt, &final); @@ -791,6 +792,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,  	fl6.flowi6_proto = IPPROTO_TCP;  	if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)  		fl6.flowi6_oif = inet6_iif(skb); +	fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark);  	fl6.fl6_dport = t1->dest;  	fl6.fl6_sport = t1->source;  	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); @@ -999,6 +1001,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)  		TCP_ECN_create_request(req, skb, sock_net(sk));  	treq->iif = sk->sk_bound_dev_if; +	inet_rsk(req)->ir_mark = inet_request_mark(sk, skb);  	/* So that link locals have meaning */  	if (!sk->sk_bound_dev_if && diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 42923b14dfa..e6dd85da906 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1147,6 +1147,7 @@ do_udp_sendmsg:  		fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;  	fl6.flowi6_mark = sk->sk_mark; +	fl6.flowi6_uid = sock_i_uid(sk);  	if (msg->msg_controllen) {  		opt = &opt_space;  |