net: inet: Support UID-based routing in IP protocols.

- Use the UID in routing lookups made by protocol connect() and
  sendmsg() functions.
- Make sure that routing lookups triggered by incoming packets
  (e.g., Path MTU discovery) take the UID of the socket into
  account.
- For packets not associated with a userspace socket, (e.g., ping
  replies) use UID 0 inside the user namespace corresponding to
  the network namespace the socket belongs to. This allows
  all namespaces to apply routing and iptables rules to
  kernel-originated traffic in that namespaces by matching UID 0.
  This is better than using the UID of the kernel socket that is
  sending the traffic, because the UID of kernel sockets created
  at namespace creation time (e.g., the per-processor ICMP and
  TCP sockets) is the UID of the user that created the socket,
  which might not be mapped in the namespace.

Tested: compiles allnoconfig, allyesconfig, allmodconfig
Tested: https://android-review.googlesource.com/253302
Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Lorenzo Colitti 2016-11-04 02:23:43 +09:00 committed by David S. Miller
parent 622ec2c9d5
commit e2d118a1cb
31 changed files with 89 additions and 40 deletions

View File

@ -96,7 +96,8 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
__u32 mark, __u8 tos, __u8 scope, __u32 mark, __u8 tos, __u8 scope,
__u8 proto, __u8 flags, __u8 proto, __u8 flags,
__be32 daddr, __be32 saddr, __be32 daddr, __be32 saddr,
__be16 dport, __be16 sport) __be16 dport, __be16 sport,
kuid_t uid)
{ {
fl4->flowi4_oif = oif; fl4->flowi4_oif = oif;
fl4->flowi4_iif = LOOPBACK_IFINDEX; fl4->flowi4_iif = LOOPBACK_IFINDEX;
@ -107,6 +108,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
fl4->flowi4_flags = flags; fl4->flowi4_flags = flags;
fl4->flowi4_secid = 0; fl4->flowi4_secid = 0;
fl4->flowi4_tun_key.tun_id = 0; fl4->flowi4_tun_key.tun_id = 0;
fl4->flowi4_uid = uid;
fl4->daddr = daddr; fl4->daddr = daddr;
fl4->saddr = saddr; fl4->saddr = saddr;
fl4->fl4_dport = dport; fl4->fl4_dport = dport;

View File

@ -179,6 +179,7 @@ struct ip_reply_arg {
/* -1 if not needed */ /* -1 if not needed */
int bound_dev_if; int bound_dev_if;
u8 tos; u8 tos;
kuid_t uid;
}; };
#define IP_REPLY_ARG_NOSRCCHECK 1 #define IP_REPLY_ARG_NOSRCCHECK 1

View File

@ -140,9 +140,10 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
const struct in6_addr *gwaddr); const struct in6_addr *gwaddr);
void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif, void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif,
u32 mark); u32 mark, kuid_t uid);
void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu); void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu);
void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark); void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
kuid_t uid);
void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
u32 mark); u32 mark);
void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk); void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);

View File

@ -153,7 +153,7 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi
flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos, flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos,
RT_SCOPE_UNIVERSE, proto, RT_SCOPE_UNIVERSE, proto,
sk ? inet_sk_flowi_flags(sk) : 0, sk ? inet_sk_flowi_flags(sk) : 0,
daddr, saddr, dport, sport); daddr, saddr, dport, sport, sock_net_uid(net, sk));
if (sk) if (sk)
security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
return ip_route_output_flow(net, fl4, sk); return ip_route_output_flow(net, fl4, sk);
@ -269,7 +269,8 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32
flow_flags |= FLOWI_FLAG_ANYSRC; flow_flags |= FLOWI_FLAG_ANYSRC;
flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE, flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
protocol, flow_flags, dst, src, dport, sport); protocol, flow_flags, dst, src, dport, sport,
sk->sk_uid);
} }
static inline struct rtable *ip_route_connect(struct flowi4 *fl4, static inline struct rtable *ip_route_connect(struct flowi4 *fl4,

View File

@ -425,6 +425,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
fl4.daddr = daddr; fl4.daddr = daddr;
fl4.saddr = saddr; fl4.saddr = saddr;
fl4.flowi4_mark = mark; fl4.flowi4_mark = mark;
fl4.flowi4_uid = sock_net_uid(net, NULL);
fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
fl4.flowi4_proto = IPPROTO_ICMP; fl4.flowi4_proto = IPPROTO_ICMP;
fl4.flowi4_oif = l3mdev_master_ifindex(skb->dev); fl4.flowi4_oif = l3mdev_master_ifindex(skb->dev);
@ -473,6 +474,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
param->replyopts.opt.opt.faddr : iph->saddr); param->replyopts.opt.opt.faddr : iph->saddr);
fl4->saddr = saddr; fl4->saddr = saddr;
fl4->flowi4_mark = mark; fl4->flowi4_mark = mark;
fl4->flowi4_uid = sock_net_uid(net, NULL);
fl4->flowi4_tos = RT_TOS(tos); fl4->flowi4_tos = RT_TOS(tos);
fl4->flowi4_proto = IPPROTO_ICMP; fl4->flowi4_proto = IPPROTO_ICMP;
fl4->fl4_icmp_type = type; fl4->fl4_icmp_type = type;

View File

@ -415,7 +415,7 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
sk->sk_protocol, inet_sk_flowi_flags(sk), sk->sk_protocol, inet_sk_flowi_flags(sk),
(opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr, (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
ireq->ir_loc_addr, ireq->ir_rmt_port, ireq->ir_loc_addr, ireq->ir_rmt_port,
htons(ireq->ir_num)); htons(ireq->ir_num), sk->sk_uid);
security_req_classify_flow(req, flowi4_to_flowi(fl4)); security_req_classify_flow(req, flowi4_to_flowi(fl4));
rt = ip_route_output_flow(net, fl4, sk); rt = ip_route_output_flow(net, fl4, sk);
if (IS_ERR(rt)) if (IS_ERR(rt))
@ -452,7 +452,7 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
sk->sk_protocol, inet_sk_flowi_flags(sk), sk->sk_protocol, inet_sk_flowi_flags(sk),
(opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr, (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
ireq->ir_loc_addr, ireq->ir_rmt_port, ireq->ir_loc_addr, ireq->ir_rmt_port,
htons(ireq->ir_num)); htons(ireq->ir_num), sk->sk_uid);
security_req_classify_flow(req, flowi4_to_flowi(fl4)); security_req_classify_flow(req, flowi4_to_flowi(fl4));
rt = ip_route_output_flow(net, fl4, sk); rt = ip_route_output_flow(net, fl4, sk);
if (IS_ERR(rt)) if (IS_ERR(rt))

View File

@ -1587,7 +1587,8 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
RT_SCOPE_UNIVERSE, ip_hdr(skb)->protocol, RT_SCOPE_UNIVERSE, ip_hdr(skb)->protocol,
ip_reply_arg_flowi_flags(arg), ip_reply_arg_flowi_flags(arg),
daddr, saddr, 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)); security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
rt = ip_route_output_key(net, &fl4); rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt)) if (IS_ERR(rt))

View File

@ -789,7 +789,8 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE, sk->sk_protocol, RT_SCOPE_UNIVERSE, sk->sk_protocol,
inet_sk_flowi_flags(sk), faddr, saddr, 0, 0); inet_sk_flowi_flags(sk), faddr, saddr, 0, 0,
sk->sk_uid);
security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
rt = ip_route_output_flow(net, &fl4, sk); rt = ip_route_output_flow(net, &fl4, sk);

View File

@ -606,7 +606,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
inet_sk_flowi_flags(sk) | inet_sk_flowi_flags(sk) |
(inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
daddr, saddr, 0, 0); daddr, saddr, 0, 0, sk->sk_uid);
if (!inet->hdrincl) { if (!inet->hdrincl) {
rfv.msg = msg; rfv.msg = msg;

View File

@ -507,7 +507,8 @@ void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
} }
EXPORT_SYMBOL(__ip_select_ident); EXPORT_SYMBOL(__ip_select_ident);
static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk, static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
const struct sock *sk,
const struct iphdr *iph, const struct iphdr *iph,
int oif, u8 tos, int oif, u8 tos,
u8 prot, u32 mark, int flow_flags) u8 prot, u32 mark, int flow_flags)
@ -523,7 +524,8 @@ static void __build_flow_key(struct flowi4 *fl4, const struct sock *sk,
flowi4_init_output(fl4, oif, mark, tos, flowi4_init_output(fl4, oif, mark, tos,
RT_SCOPE_UNIVERSE, prot, RT_SCOPE_UNIVERSE, prot,
flow_flags, flow_flags,
iph->daddr, iph->saddr, 0, 0); iph->daddr, iph->saddr, 0, 0,
sock_net_uid(net, sk));
} }
static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb, static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
@ -535,7 +537,7 @@ static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
u8 prot = iph->protocol; u8 prot = iph->protocol;
u32 mark = skb->mark; u32 mark = skb->mark;
__build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0); __build_flow_key(sock_net(sk), 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, const struct sock *sk)
@ -552,7 +554,7 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
inet_sk_flowi_flags(sk), inet_sk_flowi_flags(sk),
daddr, inet->inet_saddr, 0, 0); daddr, inet->inet_saddr, 0, 0, sk->sk_uid);
rcu_read_unlock(); rcu_read_unlock();
} }
@ -800,7 +802,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
rt = (struct rtable *) dst; rt = (struct rtable *) dst;
__build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0); __build_flow_key(sock_net(sk), &fl4, sk, iph, oif, tos, prot, mark, 0);
__ip_do_redirect(rt, skb, &fl4, true); __ip_do_redirect(rt, skb, &fl4, true);
} }
@ -1018,7 +1020,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
if (!mark) if (!mark)
mark = IP4_REPLY_MARK(net, skb->mark); mark = IP4_REPLY_MARK(net, skb->mark);
__build_flow_key(&fl4, NULL, iph, oif, __build_flow_key(net, &fl4, NULL, iph, oif,
RT_TOS(iph->tos), protocol, mark, flow_flags); RT_TOS(iph->tos), protocol, mark, flow_flags);
rt = __ip_route_output_key(net, &fl4); rt = __ip_route_output_key(net, &fl4);
if (!IS_ERR(rt)) { if (!IS_ERR(rt)) {
@ -1034,7 +1036,7 @@ static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
struct flowi4 fl4; struct flowi4 fl4;
struct rtable *rt; struct rtable *rt;
__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); __build_flow_key(sock_net(sk), &fl4, sk, iph, 0, 0, 0, 0, 0);
if (!fl4.flowi4_mark) if (!fl4.flowi4_mark)
fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark); fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark);
@ -1053,6 +1055,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
struct rtable *rt; struct rtable *rt;
struct dst_entry *odst = NULL; struct dst_entry *odst = NULL;
bool new = false; bool new = false;
struct net *net = sock_net(sk);
bh_lock_sock(sk); bh_lock_sock(sk);
@ -1066,7 +1069,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
goto out; goto out;
} }
__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
rt = (struct rtable *)odst; rt = (struct rtable *)odst;
if (odst->obsolete && !odst->ops->check(odst, 0)) { if (odst->obsolete && !odst->ops->check(odst, 0)) {
@ -1106,7 +1109,7 @@ void ipv4_redirect(struct sk_buff *skb, struct net *net,
struct flowi4 fl4; struct flowi4 fl4;
struct rtable *rt; struct rtable *rt;
__build_flow_key(&fl4, NULL, iph, oif, __build_flow_key(net, &fl4, NULL, iph, oif,
RT_TOS(iph->tos), protocol, mark, flow_flags); RT_TOS(iph->tos), protocol, mark, flow_flags);
rt = __ip_route_output_key(net, &fl4); rt = __ip_route_output_key(net, &fl4);
if (!IS_ERR(rt)) { if (!IS_ERR(rt)) {
@ -1121,9 +1124,10 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
const struct iphdr *iph = (const struct iphdr *) skb->data; const struct iphdr *iph = (const struct iphdr *) skb->data;
struct flowi4 fl4; struct flowi4 fl4;
struct rtable *rt; struct rtable *rt;
struct net *net = sock_net(sk);
__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
rt = __ip_route_output_key(sock_net(sk), &fl4); rt = __ip_route_output_key(net, &fl4);
if (!IS_ERR(rt)) { if (!IS_ERR(rt)) {
__ip_do_redirect(rt, skb, &fl4, false); __ip_do_redirect(rt, skb, &fl4, false);
ip_rt_put(rt); ip_rt_put(rt);

View File

@ -372,7 +372,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP, RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
inet_sk_flowi_flags(sk), inet_sk_flowi_flags(sk),
opt->srr ? opt->faddr : ireq->ir_rmt_addr, opt->srr ? opt->faddr : ireq->ir_rmt_addr,
ireq->ir_loc_addr, th->source, th->dest); ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid);
security_req_classify_flow(req, flowi4_to_flowi(&fl4)); security_req_classify_flow(req, flowi4_to_flowi(&fl4));
rt = ip_route_output_key(sock_net(sk), &fl4); rt = ip_route_output_key(sock_net(sk), &fl4);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {

View File

@ -691,6 +691,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
offsetof(struct inet_timewait_sock, tw_bound_dev_if)); offsetof(struct inet_timewait_sock, tw_bound_dev_if));
arg.tos = ip_hdr(skb)->tos; arg.tos = ip_hdr(skb)->tos;
arg.uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
local_bh_disable(); local_bh_disable();
ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
skb, &TCP_SKB_CB(skb)->header.h4.opt, skb, &TCP_SKB_CB(skb)->header.h4.opt,
@ -711,7 +712,7 @@ out:
outside socket context is ugly, certainly. What can I do? outside socket context is ugly, certainly. What can I do?
*/ */
static void tcp_v4_send_ack(struct net *net, static void tcp_v4_send_ack(const struct sock *sk,
struct sk_buff *skb, u32 seq, u32 ack, struct sk_buff *skb, u32 seq, u32 ack,
u32 win, u32 tsval, u32 tsecr, int oif, u32 win, u32 tsval, u32 tsecr, int oif,
struct tcp_md5sig_key *key, struct tcp_md5sig_key *key,
@ -726,6 +727,7 @@ static void tcp_v4_send_ack(struct net *net,
#endif #endif
]; ];
} rep; } rep;
struct net *net = sock_net(sk);
struct ip_reply_arg arg; struct ip_reply_arg arg;
memset(&rep.th, 0, sizeof(struct tcphdr)); memset(&rep.th, 0, sizeof(struct tcphdr));
@ -775,6 +777,7 @@ static void tcp_v4_send_ack(struct net *net,
if (oif) if (oif)
arg.bound_dev_if = oif; arg.bound_dev_if = oif;
arg.tos = tos; arg.tos = tos;
arg.uid = sock_net_uid(net, sk_fullsock(sk) ? sk : NULL);
local_bh_disable(); local_bh_disable();
ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk), ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
skb, &TCP_SKB_CB(skb)->header.h4.opt, skb, &TCP_SKB_CB(skb)->header.h4.opt,
@ -790,7 +793,7 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
struct inet_timewait_sock *tw = inet_twsk(sk); struct inet_timewait_sock *tw = inet_twsk(sk);
struct tcp_timewait_sock *tcptw = tcp_twsk(sk); struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
tcp_v4_send_ack(sock_net(sk), skb, tcp_v4_send_ack(sk, skb,
tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
tcp_time_stamp + tcptw->tw_ts_offset, tcp_time_stamp + tcptw->tw_ts_offset,
@ -818,7 +821,7 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
* exception of <SYN> segments, MUST be right-shifted by * exception of <SYN> segments, MUST be right-shifted by
* Rcv.Wind.Shift bits: * Rcv.Wind.Shift bits:
*/ */
tcp_v4_send_ack(sock_net(sk), skb, seq, tcp_v4_send_ack(sk, skb, seq,
tcp_rsk(req)->rcv_nxt, tcp_rsk(req)->rcv_nxt,
req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale, req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
tcp_time_stamp, tcp_time_stamp,

View File

@ -1019,7 +1019,8 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos, flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE, sk->sk_protocol, RT_SCOPE_UNIVERSE, sk->sk_protocol,
flow_flags, flow_flags,
faddr, saddr, dport, inet->inet_sport); faddr, saddr, dport, inet->inet_sport,
sk->sk_uid);
security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
rt = ip_route_output_flow(net, fl4, sk); rt = ip_route_output_flow(net, fl4, sk);

View File

@ -678,6 +678,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
fl6.flowi6_mark = sk->sk_mark; fl6.flowi6_mark = sk->sk_mark;
fl6.fl6_dport = inet->inet_dport; fl6.fl6_dport = inet->inet_dport;
fl6.fl6_sport = inet->inet_sport; fl6.fl6_sport = inet->inet_sport;
fl6.flowi6_uid = sk->sk_uid;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
rcu_read_lock(); rcu_read_lock();

View File

@ -662,9 +662,10 @@ static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0; return 0;
if (type == NDISC_REDIRECT) if (type == NDISC_REDIRECT)
ip6_redirect(skb, net, skb->dev->ifindex, 0); ip6_redirect(skb, net, skb->dev->ifindex, 0,
sock_net_uid(net, NULL));
else else
ip6_update_pmtu(skb, net, info, 0, 0); ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
xfrm_state_put(x); xfrm_state_put(x);
return 0; return 0;

View File

@ -54,6 +54,7 @@ static void ip6_datagram_flow_key_init(struct flowi6 *fl6, struct sock *sk)
fl6->fl6_dport = inet->inet_dport; fl6->fl6_dport = inet->inet_dport;
fl6->fl6_sport = inet->inet_sport; fl6->fl6_sport = inet->inet_sport;
fl6->flowlabel = np->flow_label; fl6->flowlabel = np->flow_label;
fl6->flowi6_uid = sk->sk_uid;
if (!fl6->flowi6_oif) if (!fl6->flowi6_oif)
fl6->flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; fl6->flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;

View File

@ -474,9 +474,10 @@ static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0; return 0;
if (type == NDISC_REDIRECT) if (type == NDISC_REDIRECT)
ip6_redirect(skb, net, skb->dev->ifindex, 0); ip6_redirect(skb, net, skb->dev->ifindex, 0,
sock_net_uid(net, NULL));
else else
ip6_update_pmtu(skb, net, info, 0, 0); ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
xfrm_state_put(x); xfrm_state_put(x);
return 0; return 0;

View File

@ -92,9 +92,10 @@ static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
struct net *net = dev_net(skb->dev); struct net *net = dev_net(skb->dev);
if (type == ICMPV6_PKT_TOOBIG) if (type == ICMPV6_PKT_TOOBIG)
ip6_update_pmtu(skb, net, info, 0, 0); ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
else if (type == NDISC_REDIRECT) else if (type == NDISC_REDIRECT)
ip6_redirect(skb, net, skb->dev->ifindex, 0); ip6_redirect(skb, net, skb->dev->ifindex, 0,
sock_net_uid(net, NULL));
if (!(type & ICMPV6_INFOMSG_MASK)) if (!(type & ICMPV6_INFOMSG_MASK))
if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST) if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
@ -484,6 +485,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
fl6.flowi6_oif = iif; fl6.flowi6_oif = iif;
fl6.fl6_icmp_type = type; fl6.fl6_icmp_type = type;
fl6.fl6_icmp_code = code; fl6.fl6_icmp_code = code;
fl6.flowi6_uid = sock_net_uid(net, NULL);
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
sk = icmpv6_xmit_lock(net); sk = icmpv6_xmit_lock(net);
@ -658,6 +660,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
fl6.flowi6_oif = skb->dev->ifindex; fl6.flowi6_oif = skb->dev->ifindex;
fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY; fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
fl6.flowi6_mark = mark; fl6.flowi6_mark = mark;
fl6.flowi6_uid = sock_net_uid(net, NULL);
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
sk = icmpv6_xmit_lock(net); sk = icmpv6_xmit_lock(net);

View File

@ -88,6 +88,7 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk,
fl6->flowi6_mark = ireq->ir_mark; fl6->flowi6_mark = ireq->ir_mark;
fl6->fl6_dport = ireq->ir_rmt_port; fl6->fl6_dport = ireq->ir_rmt_port;
fl6->fl6_sport = htons(ireq->ir_num); fl6->fl6_sport = htons(ireq->ir_num);
fl6->flowi6_uid = sk->sk_uid;
security_req_classify_flow(req, flowi6_to_flowi(fl6)); security_req_classify_flow(req, flowi6_to_flowi(fl6));
dst = ip6_dst_lookup_flow(sk, fl6, final_p); dst = ip6_dst_lookup_flow(sk, fl6, final_p);
@ -136,6 +137,7 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
fl6->flowi6_mark = sk->sk_mark; fl6->flowi6_mark = sk->sk_mark;
fl6->fl6_sport = inet->inet_sport; fl6->fl6_sport = inet->inet_sport;
fl6->fl6_dport = inet->inet_dport; fl6->fl6_dport = inet->inet_dport;
fl6->flowi6_uid = sk->sk_uid;
security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
rcu_read_lock(); rcu_read_lock();

View File

@ -548,6 +548,8 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
fl6.flowi6_mark = skb->mark; fl6.flowi6_mark = skb->mark;
fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)); err = gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM));
if (err) if (err)
return -1; return -1;
@ -602,6 +604,8 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
fl6.flowi6_mark = skb->mark; fl6.flowi6_mark = skb->mark;
fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
if (gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM))) if (gre_handle_offloads(skb, !!(t->parms.o_flags & TUNNEL_CSUM)))
return -1; return -1;

View File

@ -1240,6 +1240,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
fl6.flowi6_mark = skb->mark; fl6.flowi6_mark = skb->mark;
} }
fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
return -1; return -1;
@ -1318,6 +1320,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
fl6.flowi6_mark = skb->mark; fl6.flowi6_mark = skb->mark;
} }
fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
return -1; return -1;

View File

@ -608,9 +608,10 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0; return 0;
if (type == NDISC_REDIRECT) if (type == NDISC_REDIRECT)
ip6_redirect(skb, net, skb->dev->ifindex, 0); ip6_redirect(skb, net, skb->dev->ifindex, 0,
sock_net_uid(net, NULL));
else else
ip6_update_pmtu(skb, net, info, 0, 0); ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
xfrm_state_put(x); xfrm_state_put(x);
return 0; return 0;

View File

@ -74,9 +74,10 @@ static int ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return 0; return 0;
if (type == NDISC_REDIRECT) if (type == NDISC_REDIRECT)
ip6_redirect(skb, net, skb->dev->ifindex, 0); ip6_redirect(skb, net, skb->dev->ifindex, 0,
sock_net_uid(net, NULL));
else else
ip6_update_pmtu(skb, net, info, 0, 0); ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
xfrm_state_put(x); xfrm_state_put(x);
return 0; return 0;

View File

@ -26,6 +26,7 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
struct flowi6 fl6 = { struct flowi6 fl6 = {
.flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
.flowi6_mark = skb->mark, .flowi6_mark = skb->mark,
.flowi6_uid = sock_net_uid(net, skb->sk),
.daddr = iph->daddr, .daddr = iph->daddr,
.saddr = iph->saddr, .saddr = iph->saddr,
}; };

View File

@ -113,6 +113,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
fl6.daddr = *daddr; fl6.daddr = *daddr;
fl6.flowi6_oif = oif; fl6.flowi6_oif = oif;
fl6.flowi6_mark = sk->sk_mark; fl6.flowi6_mark = sk->sk_mark;
fl6.flowi6_uid = sk->sk_uid;
fl6.fl6_icmp_type = user_icmph.icmp6_type; fl6.fl6_icmp_type = user_icmph.icmp6_type;
fl6.fl6_icmp_code = user_icmph.icmp6_code; fl6.fl6_icmp_code = user_icmph.icmp6_code;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));

View File

@ -776,6 +776,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
memset(&fl6, 0, sizeof(fl6)); memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_mark = sk->sk_mark; fl6.flowi6_mark = sk->sk_mark;
fl6.flowi6_uid = sk->sk_uid;
ipc6.hlimit = -1; ipc6.hlimit = -1;
ipc6.tclass = -1; ipc6.tclass = -1;

View File

@ -1405,7 +1405,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, 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; const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
struct dst_entry *dst; struct dst_entry *dst;
@ -1417,6 +1417,7 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
fl6.daddr = iph->daddr; fl6.daddr = iph->daddr;
fl6.saddr = iph->saddr; fl6.saddr = iph->saddr;
fl6.flowlabel = ip6_flowinfo(iph); fl6.flowlabel = ip6_flowinfo(iph);
fl6.flowi6_uid = uid;
dst = ip6_route_output(net, NULL, &fl6); dst = ip6_route_output(net, NULL, &fl6);
if (!dst->error) if (!dst->error)
@ -1430,7 +1431,7 @@ void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
struct dst_entry *dst; struct dst_entry *dst;
ip6_update_pmtu(skb, sock_net(sk), 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, sk->sk_uid);
dst = __sk_dst_get(sk); dst = __sk_dst_get(sk);
if (!dst || !dst->obsolete || if (!dst || !dst->obsolete ||
@ -1522,7 +1523,8 @@ static struct dst_entry *ip6_route_redirect(struct net *net,
flags, __ip6_route_redirect); flags, __ip6_route_redirect);
} }
void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark) void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
kuid_t uid)
{ {
const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
struct dst_entry *dst; struct dst_entry *dst;
@ -1535,6 +1537,7 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
fl6.daddr = iph->daddr; fl6.daddr = iph->daddr;
fl6.saddr = iph->saddr; fl6.saddr = iph->saddr;
fl6.flowlabel = ip6_flowinfo(iph); fl6.flowlabel = ip6_flowinfo(iph);
fl6.flowi6_uid = uid;
dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr); dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr);
rt6_do_redirect(dst, NULL, skb); rt6_do_redirect(dst, NULL, skb);
@ -1556,6 +1559,7 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
fl6.flowi6_mark = mark; fl6.flowi6_mark = mark;
fl6.daddr = msg->dest; fl6.daddr = msg->dest;
fl6.saddr = iph->daddr; fl6.saddr = iph->daddr;
fl6.flowi6_uid = sock_net_uid(net, NULL);
dst = ip6_route_redirect(net, &fl6, &iph->saddr); dst = ip6_route_redirect(net, &fl6, &iph->saddr);
rt6_do_redirect(dst, NULL, skb); rt6_do_redirect(dst, NULL, skb);
@ -1564,7 +1568,8 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk) void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
{ {
ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark); ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark,
sk->sk_uid);
} }
EXPORT_SYMBOL_GPL(ip6_sk_redirect); EXPORT_SYMBOL_GPL(ip6_sk_redirect);

View File

@ -227,6 +227,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
fl6.flowi6_mark = ireq->ir_mark; fl6.flowi6_mark = ireq->ir_mark;
fl6.fl6_dport = ireq->ir_rmt_port; fl6.fl6_dport = ireq->ir_rmt_port;
fl6.fl6_sport = inet_sk(sk)->inet_sport; fl6.fl6_sport = inet_sk(sk)->inet_sport;
fl6.flowi6_uid = sk->sk_uid;
security_req_classify_flow(req, flowi6_to_flowi(&fl6)); security_req_classify_flow(req, flowi6_to_flowi(&fl6));
dst = ip6_dst_lookup_flow(sk, &fl6, final_p); dst = ip6_dst_lookup_flow(sk, &fl6, final_p);

View File

@ -233,6 +233,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
fl6.flowi6_mark = sk->sk_mark; fl6.flowi6_mark = sk->sk_mark;
fl6.fl6_dport = usin->sin6_port; fl6.fl6_dport = usin->sin6_port;
fl6.fl6_sport = inet->inet_sport; fl6.fl6_sport = inet->inet_sport;
fl6.flowi6_uid = sk->sk_uid;
opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk)); opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
final_p = fl6_update_dst(&fl6, opt, &final); final_p = fl6_update_dst(&fl6, opt, &final);
@ -824,6 +825,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark); fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark);
fl6.fl6_dport = t1->dest; fl6.fl6_dport = t1->dest;
fl6.fl6_sport = t1->source; fl6.fl6_sport = t1->source;
fl6.flowi6_uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
/* Pass a socket to ip6_dst_lookup either it is for RST /* Pass a socket to ip6_dst_lookup either it is for RST

View File

@ -1138,6 +1138,7 @@ do_udp_sendmsg:
fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex; fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
fl6.flowi6_mark = sk->sk_mark; fl6.flowi6_mark = sk->sk_mark;
fl6.flowi6_uid = sk->sk_uid;
sockc.tsflags = sk->sk_tsflags; sockc.tsflags = sk->sk_tsflags;
if (msg->msg_controllen) { if (msg->msg_controllen) {

View File

@ -519,6 +519,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
memset(&fl6, 0, sizeof(fl6)); memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_mark = sk->sk_mark; fl6.flowi6_mark = sk->sk_mark;
fl6.flowi6_uid = sk->sk_uid;
ipc6.hlimit = -1; ipc6.hlimit = -1;
ipc6.tclass = -1; ipc6.tclass = -1;