net: inet: Support UID-based routing in IP protocols.
authorLorenzo Colitti <lorenzo@google.com>
Thu, 3 Nov 2016 17:23:43 +0000 (02:23 +0900)
committerDanny Wood <danwood76@gmail.com>
Tue, 28 Jul 2020 08:47:02 +0000 (09:47 +0100)
- 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.

[Backport of net-next e2d118a1cb5e60d077131a09db1d81b90a5295fe]

Bug: 16355602
Change-Id: I126f8359887b5b5bbac68daf0ded89e899cb7cb0
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>
30 files changed:
include/net/flow.h
include/net/ip.h
include/net/ip6_route.h
include/net/route.h
net/ipv4/icmp.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_output.c
net/ipv4/ping.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/syncookies.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/af_inet6.c
net/ipv6/ah6.c
net/ipv6/datagram.c
net/ipv6/esp6.c
net/ipv6/icmp.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/ipcomp6.c
net/ipv6/netfilter.c
net/ipv6/ping.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/syncookies.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/l2tp/l2tp_ip6.c

index 1964eeb57a325f740e85959568aa9bb83db74860..15ecdd07e19263dee26b7fcfe1d49b6d9628a3eb 100644 (file)
@@ -89,7 +89,8 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
                                      __u32 mark, __u8 tos, __u8 scope,
                                      __u8 proto, __u8 flags,
                                      __be32 daddr, __be32 saddr,
-                                     __be16 dport, __be16 sport)
+                                     __be16 dport, __be16 sport,
+                                     kuid_t uid)
 {
        fl4->flowi4_oif = oif;
        fl4->flowi4_iif = LOOPBACK_IFINDEX;
@@ -99,6 +100,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
        fl4->flowi4_proto = proto;
        fl4->flowi4_flags = flags;
        fl4->flowi4_secid = 0;
+       fl4->flowi4_uid = uid;
        fl4->daddr = daddr;
        fl4->saddr = saddr;
        fl4->fl4_dport = dport;
index 2e5194a230223e2bb04bb86e6a9573b74ce5fddf..a04070b8249633826e81765e34f48819d8d46779 100644 (file)
@@ -155,6 +155,7 @@ struct ip_reply_arg {
                                /* -1 if not needed */ 
        int         bound_dev_if;
        u8          tos;
+       kuid_t      uid;
 }; 
 
 #define IP_REPLY_ARG_NOSRCCHECK 1
index 8d977b3436474b057bd29d3898bfa771e14c23fb..30f068fafaadb51f72cae7e48f2db1d0c7d23902 100644 (file)
@@ -136,10 +136,11 @@ extern int                        rt6_route_rcv(struct net_device *dev,
                                              const struct in6_addr *gwaddr);
 
 extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
-                           int oif, u32 mark);
+                           int oif, u32 mark, kuid_t uid);
 extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk,
                               __be32 mtu);
-extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
+                        kuid_t uid);
 extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
 
 struct netlink_callback;
index 2ea40c1b5e009746dacb8f146fdcc37309aa7ff3..4fe676279a475ae6e142b43bd007e8faa21b69e5 100644 (file)
@@ -142,7 +142,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,
                           RT_SCOPE_UNIVERSE, proto,
                           sk ? inet_sk_flowi_flags(sk) : 0,
-                          daddr, saddr, dport, sport);
+                          daddr, saddr, dport, sport, sock_net_uid(net, sk));
        if (sk)
                security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
        return ip_route_output_flow(net, fl4, sk);
@@ -253,7 +253,8 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32
                flow_flags |= FLOWI_FLAG_CAN_SLEEP;
 
        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,
index 5af8781b65e13f49c0f3ce90bcfa695cf83756a6..59e63dcb80dadf6987bd18063c06b6ce9fdbf14b 100644 (file)
@@ -364,6 +364,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
        fl4.daddr = daddr;
        fl4.saddr = saddr;
        fl4.flowi4_mark = mark;
+       fl4.flowi4_uid = sock_net_uid(net, NULL);
        fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
        fl4.flowi4_proto = IPPROTO_ICMP;
        security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
@@ -395,6 +396,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
                      param->replyopts.opt.opt.faddr : iph->saddr);
        fl4->saddr = saddr;
        fl4->flowi4_mark = mark;
+       fl4->flowi4_uid = sock_net_uid(net, NULL);
        fl4->flowi4_tos = RT_TOS(tos);
        fl4->flowi4_proto = IPPROTO_ICMP;
        fl4->fl4_icmp_type = type;
index d6ac8269407e80491ebcdb25e9a26e0c8e121526..4a259ab3931e71c257a776ac702bb96fcd16128a 100644 (file)
@@ -422,7 +422,8 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
                           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,
+                          sk->sk_uid);
        security_req_classify_flow(req, flowi4_to_flowi(fl4));
        rt = ip_route_output_flow(net, fl4, sk);
        if (IS_ERR(rt))
@@ -458,7 +459,8 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,
                           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,
+                          sk->sk_uid);
        security_req_classify_flow(req, flowi4_to_flowi(fl4));
        rt = ip_route_output_flow(net, fl4, sk);
        if (IS_ERR(rt))
index a15b080130a3dff4e6a3363af56672bed144b9ef..1204570dcced174a5b2707f1d11a9eaa7d417d89 100644 (file)
@@ -1494,7 +1494,8 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr,
                           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))
index eb9b1fa222135253fa4526da409d56c3e61db6c2..53af3500df453df9834fa3bed2e34a90f56f08b3 100644 (file)
@@ -782,7 +782,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,
+                          sk->sk_uid);
 
        security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
        rt = ip_route_output_flow(net, &fl4, sk);
index a2e361c956b753b0f1c0a0b5382b42baab7973ef..7e1588ccf60d5de98c16e302f8c71ffe137a94c4 100644 (file)
@@ -576,7 +576,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                           inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
                           inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP |
                            (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
-                          daddr, saddr, 0, 0);
+                          daddr, saddr, 0, 0, sk->sk_uid);
 
        if (!inet->hdrincl) {
                err = raw_probe_proto_opt(&fl4, msg);
index c564dcf2c80cbe823af74d0b593ee6dd0c63029d..292c08985b0f5e055e5ebec6a0327b7419f7a818 100644 (file)
@@ -515,7 +515,8 @@ void __ip_select_ident(struct iphdr *iph, int segs)
 }
 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,
                             int oif, u8 tos,
                             u8 prot, u32 mark, int flow_flags)
@@ -531,7 +532,8 @@ 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,
+                          sock_net_uid(net, sk));
 }
 
 static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
@@ -543,7 +545,7 @@ static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
        u8 prot = iph->protocol;
        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)
@@ -560,7 +562,7 @@ 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, sk->sk_uid);
        rcu_read_unlock();
 }
 
@@ -762,7 +764,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
 
        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);
 }
 
@@ -980,7 +982,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
        if (!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 = __ip_route_output_key(net, &fl4);
        if (!IS_ERR(rt)) {
@@ -996,7 +998,7 @@ static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
        struct flowi4 fl4;
        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)
                fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark);
@@ -1015,6 +1017,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
        struct rtable *rt;
        struct dst_entry *odst = NULL;
        bool new = false;
+       struct net *net = sock_net(sk);
 
        bh_lock_sock(sk);
        odst = sk_dst_get(sk);
@@ -1024,7 +1027,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
                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;
        if (odst->obsolete && odst->ops->check(odst, 0) == NULL) {
@@ -1064,7 +1067,7 @@ void ipv4_redirect(struct sk_buff *skb, struct net *net,
        struct flowi4 fl4;
        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 = __ip_route_output_key(net, &fl4);
        if (!IS_ERR(rt)) {
@@ -1079,9 +1082,10 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
        const struct iphdr *iph = (const struct iphdr *) skb->data;
        struct flowi4 fl4;
        struct rtable *rt;
+       struct net *net = sock_net(sk);
 
-       __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
-       rt = __ip_route_output_key(sock_net(sk), &fl4);
+       __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
+       rt = __ip_route_output_key(net, &fl4);
        if (!IS_ERR(rt)) {
                __ip_do_redirect(rt, skb, &fl4, false);
                ip_rt_put(rt);
index 5abb45e281bea0ffdcfd14d9e017742d7b19c71a..296a0a42b2b8716942e9f9da27985e3e0bf13dec 100644 (file)
@@ -353,7 +353,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
                           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, sk->sk_uid);
        security_req_classify_flow(req, flowi4_to_flowi(&fl4));
        rt = ip_route_output_key(sock_net(sk), &fl4);
        if (IS_ERR(rt)) {
index 58e2947cf5e5d2791f10763fe85bb429d443f371..64c1fcb6fd2fef79464d029cc95667bec3b15951 100644 (file)
@@ -711,6 +711,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
                arg.bound_dev_if = sk->sk_bound_dev_if;
 
        arg.tos = ip_hdr(skb)->tos;
+       arg.uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
        ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
                              skb, ip_hdr(skb)->saddr,
                              ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len);
@@ -731,7 +732,8 @@ release_sk1:
    outside socket context is ugly, certainly. What can I do?
  */
 
-static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
+static void tcp_v4_send_ack(const struct sock *sk, struct sk_buff *skb,
+                           u32 seq, u32 ack,
                            u32 win, u32 tsval, u32 tsecr, int oif,
                            struct tcp_md5sig_key *key,
                            int reply_flags, u8 tos)
@@ -746,7 +748,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
                        ];
        } rep;
        struct ip_reply_arg arg;
-       struct net *net = dev_net(skb_dst(skb)->dev);
+       struct net *net = sock_net(sk);
 
        memset(&rep.th, 0, sizeof(struct tcphdr));
        memset(&arg, 0, sizeof(arg));
@@ -795,6 +797,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
        if (oif)
                arg.bound_dev_if = oif;
        arg.tos = tos;
+       arg.uid = sock_net_uid(net, sk_fullsock(sk) ? sk : NULL);
        ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
                              skb, ip_hdr(skb)->saddr,
                              ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len);
@@ -807,7 +810,7 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
        struct inet_timewait_sock *tw = inet_twsk(sk);
        struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
 
-       tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+       tcp_v4_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
                        tcp_time_stamp + tcptw->tw_ts_offset,
                        tcptw->tw_ts_recent,
@@ -826,7 +829,7 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
        /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
         * sk->sk_state == TCP_SYN_RECV -> for Fast Open.
         */
-       tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ?
+       tcp_v4_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ?
                        tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
                        tcp_rsk(req)->rcv_nxt,
                        req->rcv_wnd >> inet_rsk(req)->rcv_wscale,
index eca809f19bccc49de8f77105a3f80ef870ec1b5d..8e96f51fef2a5fab8ff42dc99c3328b55e6a53da 100644 (file)
@@ -963,7 +963,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,
+                                  sk->sk_uid);
 
                security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
                rt = ip_route_output_flow(net, fl4, sk);
index 112e14fa81bceb65a4de598c19ea5c6b69413907..db3b20e10c65149d738958cec93624a032b31009 100644 (file)
@@ -702,6 +702,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 = sk->sk_uid;
                security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
                rcu_read_lock();
index bb02e176cb70537ac7cdc01a03c0c641ab672741..15e41c5bea3a9872b6ed6d71d2afdca7ba9e1e6f 100644 (file)
@@ -628,9 +628,9 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return;
 
        if (type == NDISC_REDIRECT)
-               ip6_redirect(skb, net, 0, 0);
+               ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL));
        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);
 }
 
index 0deea6ef4cc1eda275346ca9252460246cd9f183..8abb98c38d3e69ab03ef580c600e29103a1fa41f 100644 (file)
@@ -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 = sk->sk_uid;
 
        if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST))
                fl6.flowi6_oif = np->mcast_oif;
index 40ffd72243a4f2d1ec9e5da494b3f2650dd027a6..4ad65258f549aefc50e78eccfff914b81f7eecab 100644 (file)
@@ -447,9 +447,9 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return;
 
        if (type == NDISC_REDIRECT)
-               ip6_redirect(skb, net, 0, 0);
+               ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL));
        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);
 }
 
index 84bdcd06dd34bcb89bc2d13a1750c7d0f19dec40..adb715b22f73ffe2f6d41ea4ed33cb5654393b8c 100644 (file)
@@ -90,9 +90,9 @@ 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, sock_net_uid(net, NULL));
        else if (type == NDISC_REDIRECT)
-               ip6_redirect(skb, net, 0, 0);
+               ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL));
 
        if (!(type & ICMPV6_INFOMSG_MASK))
                if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
@@ -467,6 +467,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
        fl6.flowi6_oif = iif;
        fl6.fl6_icmp_type = type;
        fl6.fl6_icmp_code = code;
+       fl6.flowi6_uid = sock_net_uid(net, NULL);
        security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
        sk = icmpv6_xmit_lock(net);
@@ -572,6 +573,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        fl6.flowi6_oif = skb->dev->ifindex;
        fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
        fl6.flowi6_mark = mark;
+       fl6.flowi6_uid = sock_net_uid(net, NULL);
        security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
        sk = icmpv6_xmit_lock(net);
index 9cdb8e434513a43de2854f35c234bbbf9374777e..a2072a81c933b7c1ed6f34924c49862e0178e68b 100644 (file)
@@ -86,6 +86,7 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk,
        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 = sk->sk_uid;
        security_req_classify_flow(req, flowi6_to_flowi(fl6));
 
        dst = ip6_dst_lookup_flow(sk, fl6, final_p, false);
@@ -213,6 +214,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 = sk->sk_uid;
        security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
 
        rcu_read_lock();
index 529348e6a98be10576cff0835ab07db2a1fde703..70453acb83852a1fa0c275df693df06781a1711b 100644 (file)
@@ -801,6 +801,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)
                fl6.flowi6_mark = skb->mark;
 
+       fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
        err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
        if (err != 0) {
                /* XXX: send ICMP error even if DF is not set. */
@@ -851,6 +853,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)
                fl6.flowi6_mark = skb->mark;
 
+       fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
        err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
        if (err != 0) {
                if (err == -EMSGSIZE)
index efc77acbe9e193d4730ec99fc66ea38c4f247607..cd0a8bed1ea47d82b7e75bd252258beafdb7ad44 100644 (file)
@@ -1096,6 +1096,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6));
        fl6.flowi6_proto = IPPROTO_IPIP;
 
+       fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
        dsfield = ipv4_get_dsfield(iph);
 
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
@@ -1147,6 +1149,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 
        memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6));
        fl6.flowi6_proto = IPPROTO_IPV6;
+       fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
 
        dsfield = ipv6_get_dsfield(ipv6h);
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
index 7af5aee75d982327e7b258f72091780e83a01cc4..a4a4e1c2c9faf96f5ad88387f01a4211fe2484b7 100644 (file)
@@ -76,9 +76,9 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return;
 
        if (type == NDISC_REDIRECT)
-               ip6_redirect(skb, net, 0, 0);
+               ip6_redirect(skb, net, 0, 0, sock_net_uid(net, NULL));
        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);
 }
 
index d38e6a8d8b9fb82ec7d583a5ab2abc652838d470..e48d26beda464fb627c560d34c5aa81fd2cdb7c1 100644 (file)
@@ -27,6 +27,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
        struct flowi6 fl6 = {
                .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
                .flowi6_mark = skb->mark,
+               .flowi6_uid = sock_net_uid(net, skb->sk),
                .daddr = iph->daddr,
                .saddr = iph->saddr,
        };
index 34b0639d0b920a8dcb1a596e9e3696efa6abc102..0ef815e8f761465f15370e6e7ded8ecaf5857d79 100644 (file)
@@ -165,6 +165,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        fl6.daddr = *daddr;
        fl6.flowi6_oif = oif;
        fl6.flowi6_mark = sk->sk_mark;
+       fl6.flowi6_uid = sk->sk_uid;
        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));
index 5fa9c06b43002b27bc9810e783390678608c241b..d879772d97803d44e582bef5f8b6ac434ff12f9c 100644 (file)
@@ -765,6 +765,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 = sk->sk_uid;
 
        if (sin6) {
                if (addr_len < SIN6_LEN_RFC2133)
index 2c79063b665383c98a5132f09bddd05b7fd9f1bc..c97e4ab54cc7fe9a26f1384a9b64c0fd9dc99b89 100644 (file)
@@ -1143,7 +1143,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;
@@ -1156,6 +1156,7 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
        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)
@@ -1167,11 +1168,12 @@ 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, sk->sk_uid);
 }
 EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu);
 
-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;
        struct dst_entry *dst;
@@ -1184,6 +1186,7 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
        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)
@@ -1194,7 +1197,8 @@ EXPORT_SYMBOL_GPL(ip6_redirect);
 
 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);
 
index a596f388339d0a227c874dfb61514b7d098d345d..0428544a2bed414b5824c07ea77792fb65043748 100644 (file)
@@ -243,6 +243,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
                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 = sk->sk_uid;
                security_req_classify_flow(req, flowi6_to_flowi(&fl6));
 
                dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
index 15cd50d3ccea4afae66c458fa9a91dbf12602775..c35b4ff323e00d4edaa13ea972b51c5c0b7ae266 100644 (file)
@@ -253,6 +253,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 = sk->sk_uid;
 
        opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
        final_p = fl6_update_dst(&fl6, opt, &final);
@@ -799,6 +800,7 @@ static void tcp_v6_send_response(struct sock *sk, struct sk_buff *skb, u32 seq,
        fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark);
        fl6.fl6_dport = t1->dest;
        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));
 
        /* Pass a socket to ip6_dst_lookup either it is for RST
index 79a44443777a075cf1e9d615e742546536e0a793..bd8e3c55a145343068282db8cd707a3caea0d4e2 100644 (file)
@@ -1149,6 +1149,7 @@ do_udp_sendmsg:
                fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
 
        fl6.flowi6_mark = sk->sk_mark;
+       fl6.flowi6_uid = sk->sk_uid;
 
        if (msg->msg_controllen) {
                opt = &opt_space;
index 8783dfe5ac6ca74c6d5ea6df5f96a1b7e37826a8..5bd181e296e53d7f3277f08b9930133cc088fafa 100644 (file)
@@ -517,6 +517,7 @@ static int l2tp_ip6_sendmsg(struct kiocb *iocb, struct sock *sk,
        memset(&fl6, 0, sizeof(fl6));
 
        fl6.flowi6_mark = sk->sk_mark;
+       fl6.flowi6_uid = sk->sk_uid;
 
        if (lsa) {
                if (addr_len < SIN6_LEN_RFC2133)