Merge branch 'netns-defrag'
authorDavid S. Miller <davem@davemloft.net>
Tue, 13 Oct 2015 02:44:22 +0000 (19:44 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 13 Oct 2015 02:44:22 +0000 (19:44 -0700)
Eric W. Biederman says:

====================
net: Pass net into defragmentation

This is the next installment of my work to pass struct net through the
output path so the code does not need to guess how to figure out which
network namespace it is in, and ultimately routes can have output
devices in another network namespace.

In netfilter and af_packet we defragment packets in the output path,
and there is the usual amount of confusion about how to compute which
net we are processing the packets in.  This patchset clears that
confusion up by explicitly passing in struct net in ip_defrag,
ip_check_defrag, and nf_ct_frag6_gather.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/macvlan.c
include/net/ip.h
include/net/netfilter/ipv6/nf_defrag_ipv6.h
net/ipv4/ip_fragment.c
net/ipv4/ip_input.c
net/ipv4/netfilter/nf_defrag_ipv4.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
net/netfilter/ipvs/ip_vs_core.c
net/openvswitch/conntrack.c
net/packet/af_packet.c

index 47da43595ac271c570e8536a2e1a3b697a9dbd79..86f6c6292c2726c6991f305bc8794a5af2c648af 100644 (file)
@@ -412,7 +412,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
 
        port = macvlan_port_get_rcu(skb->dev);
        if (is_multicast_ether_addr(eth->h_dest)) {
-               skb = ip_check_defrag(skb, IP_DEFRAG_MACVLAN);
+               skb = ip_check_defrag(dev_net(skb->dev), skb, IP_DEFRAG_MACVLAN);
                if (!skb)
                        return RX_HANDLER_CONSUMED;
                eth = eth_hdr(skb);
index 3c904a28d5e5a0091c5aeb86432be8ea9365a2e1..1a98f1ca16383d2b9cd0867091e323ab7c81f045 100644 (file)
@@ -506,11 +506,11 @@ static inline bool ip_defrag_user_in_between(u32 user,
        return user >= lower_bond && user <= upper_bond;
 }
 
-int ip_defrag(struct sk_buff *skb, u32 user);
+int ip_defrag(struct net *net, struct sk_buff *skb, u32 user);
 #ifdef CONFIG_INET
-struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user);
+struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user);
 #else
-static inline struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
+static inline struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
 {
        return skb;
 }
index 27666d8a0bd07f38f644bf7c768678ade981155b..fb7da5bb76cc8a58716b59d1ed421868ce18c697 100644 (file)
@@ -5,7 +5,7 @@ void nf_defrag_ipv6_enable(void);
 
 int nf_ct_frag6_init(void);
 void nf_ct_frag6_cleanup(void);
-struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user);
+struct sk_buff *nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user);
 void nf_ct_frag6_consume_orig(struct sk_buff *skb);
 
 struct inet_frags_ctl;
index 9772b789adf34deb0a532b1d9431d6e0178b6e3c..5482745d5d6843b8a3da1b2845bba0030e854944 100644 (file)
@@ -654,11 +654,10 @@ out_fail:
 }
 
 /* Process an incoming IP datagram fragment. */
-int ip_defrag(struct sk_buff *skb, u32 user)
+int ip_defrag(struct net *net, struct sk_buff *skb, u32 user)
 {
        struct net_device *dev = skb->dev ? : skb_dst(skb)->dev;
        int vif = l3mdev_master_ifindex_rcu(dev);
-       struct net *net = dev_net(dev);
        struct ipq *qp;
 
        IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS);
@@ -683,7 +682,7 @@ int ip_defrag(struct sk_buff *skb, u32 user)
 }
 EXPORT_SYMBOL(ip_defrag);
 
-struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
+struct sk_buff *ip_check_defrag(struct net *net, struct sk_buff *skb, u32 user)
 {
        struct iphdr iph;
        int netoff;
@@ -712,7 +711,7 @@ struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
                        if (pskb_trim_rcsum(skb, netoff + len))
                                return skb;
                        memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
-                       if (ip_defrag(skb, user))
+                       if (ip_defrag(net, skb, user))
                                return NULL;
                        skb_clear_hash(skb);
                }
index 7cc9f7bb7fb778bcb895634a97ea9de0e88b0d66..b1209b63381f6f9ae81cf258ad3724e1b6a6b9d8 100644 (file)
@@ -157,6 +157,7 @@ bool ip_call_ra_chain(struct sk_buff *skb)
        u8 protocol = ip_hdr(skb)->protocol;
        struct sock *last = NULL;
        struct net_device *dev = skb->dev;
+       struct net *net = dev_net(dev);
 
        for (ra = rcu_dereference(ip_ra_chain); ra; ra = rcu_dereference(ra->next)) {
                struct sock *sk = ra->sk;
@@ -167,9 +168,9 @@ bool ip_call_ra_chain(struct sk_buff *skb)
                if (sk && inet_sk(sk)->inet_num == protocol &&
                    (!sk->sk_bound_dev_if ||
                     sk->sk_bound_dev_if == dev->ifindex) &&
-                   net_eq(sock_net(sk), dev_net(dev))) {
+                   net_eq(sock_net(sk), net)) {
                        if (ip_is_fragment(ip_hdr(skb))) {
-                               if (ip_defrag(skb, IP_DEFRAG_CALL_RA_CHAIN))
+                               if (ip_defrag(net, skb, IP_DEFRAG_CALL_RA_CHAIN))
                                        return true;
                        }
                        if (last) {
@@ -246,14 +247,15 @@ int ip_local_deliver(struct sk_buff *skb)
        /*
         *      Reassemble IP fragments.
         */
+       struct net *net = dev_net(skb->dev);
 
        if (ip_is_fragment(ip_hdr(skb))) {
-               if (ip_defrag(skb, IP_DEFRAG_LOCAL_DELIVER))
+               if (ip_defrag(net, skb, IP_DEFRAG_LOCAL_DELIVER))
                        return 0;
        }
 
        return NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN,
-                      dev_net(skb->dev), NULL, skb, skb->dev, NULL,
+                      net, NULL, skb, skb->dev, NULL,
                       ip_local_deliver_finish);
 }
 
index b246346ee849921029243d3f42fe536b29c50bac..bf25f45b23d24305bfa8a22f4bb5946153052221 100644 (file)
 #endif
 #include <net/netfilter/nf_conntrack_zones.h>
 
-static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
+static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb,
+                                  u_int32_t user)
 {
        int err;
 
        skb_orphan(skb);
 
        local_bh_disable();
-       err = ip_defrag(skb, user);
+       err = ip_defrag(net, skb, user);
        local_bh_enable();
 
        if (!err) {
@@ -85,7 +86,7 @@ static unsigned int ipv4_conntrack_defrag(void *priv,
                enum ip_defrag_users user =
                        nf_ct_defrag_user(state->hook, skb);
 
-               if (nf_ct_ipv4_gather_frags(skb, user))
+               if (nf_ct_ipv4_gather_frags(state->net, skb, user))
                        return NF_STOLEN;
        }
        return NF_ACCEPT;
index 701cd2bae0a9224d56005f67d8b9f5e71f45825f..2fb86a99bf5f1325cb97e1bd75c5870b38f64116 100644 (file)
@@ -563,12 +563,10 @@ find_prev_fhdr(struct sk_buff *skb, u8 *prevhdrp, int *prevhoff, int *fhoff)
        return 0;
 }
 
-struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user)
+struct sk_buff *nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
 {
        struct sk_buff *clone;
        struct net_device *dev = skb->dev;
-       struct net *net = skb_dst(skb) ? dev_net(skb_dst(skb)->dev)
-                                      : dev_net(skb->dev);
        struct frag_hdr *fhdr;
        struct frag_queue *fq;
        struct ipv6hdr *hdr;
index a99baf63eccf7768eb07777310ea8ba5aad2067b..5173a89a238ef37e2862b7e91abafb84700fc191 100644 (file)
@@ -63,7 +63,8 @@ static unsigned int ipv6_defrag(void *priv,
                return NF_ACCEPT;
 #endif
 
-       reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(state->hook, skb));
+       reasm = nf_ct_frag6_gather(state->net, skb,
+                                  nf_ct6_defrag_user(state->hook, skb));
        /* queued */
        if (reasm == NULL)
                return NF_STOLEN;
index 37dd77a3d0fb4d91f802d6051cd058b53ce63268..07a791ecdfbab9fee7f6c78bcc53a6f9204cbe90 100644 (file)
@@ -694,7 +694,7 @@ static inline int ip_vs_gather_frags(struct netns_ipvs *ipvs,
        int err;
 
        local_bh_disable();
-       err = ip_defrag(skb, user);
+       err = ip_defrag(ipvs->net, skb, user);
        local_bh_enable();
        if (!err)
                ip_send_check(ip_hdr(skb));
index eb759e3a88cafe4e4b565e587d7f45d0f9ac2cc3..ad614267cc2a620249e18e4ef6bec35c7fa19f8f 100644 (file)
@@ -304,7 +304,7 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
                int err;
 
                memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
-               err = ip_defrag(skb, user);
+               err = ip_defrag(net, skb, user);
                if (err)
                        return err;
 
@@ -315,7 +315,7 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
                struct sk_buff *reasm;
 
                memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
-               reasm = nf_ct_frag6_gather(skb, user);
+               reasm = nf_ct_frag6_gather(net, skb, user);
                if (!reasm)
                        return -EINPROGRESS;
 
index 396b3f1e7cc0371b74abc40c34b77e76cd4e772f..691660b9b7effdc59d10517ebf099ca8736efe14 100644 (file)
@@ -1439,17 +1439,17 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
 {
        struct packet_fanout *f = pt->af_packet_priv;
        unsigned int num = READ_ONCE(f->num_members);
+       struct net *net = read_pnet(&f->net);
        struct packet_sock *po;
        unsigned int idx;
 
-       if (!net_eq(dev_net(dev), read_pnet(&f->net)) ||
-           !num) {
+       if (!net_eq(dev_net(dev), net) || !num) {
                kfree_skb(skb);
                return 0;
        }
 
        if (fanout_has_flag(f, PACKET_FANOUT_FLAG_DEFRAG)) {
-               skb = ip_check_defrag(skb, IP_DEFRAG_AF_PACKET);
+               skb = ip_check_defrag(net, skb, IP_DEFRAG_AF_PACKET);
                if (!skb)
                        return 0;
        }