[NET] NETNS: Omit sock->sk_net without CONFIG_NET_NS.
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / af_inet.c
index 44f5ce1fbfa4849c6c00941b978d799b56a121df..5882a13164418bb29ed985181009d0b6514d5a79 100644 (file)
@@ -243,6 +243,23 @@ void build_ehash_secret(void)
 }
 EXPORT_SYMBOL(build_ehash_secret);
 
+static inline int inet_netns_ok(struct net *net, int protocol)
+{
+       int hash;
+       struct net_protocol *ipprot;
+
+       if (net == &init_net)
+               return 1;
+
+       hash = protocol & (MAX_INET_PROTOS - 1);
+       ipprot = rcu_dereference(inet_protos[hash]);
+
+       if (ipprot == NULL)
+               /* raw IP is OK */
+               return 1;
+       return ipprot->netns_ok;
+}
+
 /*
  *     Create an inet socket.
  */
@@ -259,9 +276,6 @@ static int inet_create(struct net *net, struct socket *sock, int protocol)
        int try_loading_module = 0;
        int err;
 
-       if (net != &init_net)
-               return -EAFNOSUPPORT;
-
        if (sock->type != SOCK_RAW &&
            sock->type != SOCK_DGRAM &&
            !inet_ehash_secret)
@@ -320,6 +334,10 @@ lookup_protocol:
        if (answer->capability > 0 && !capable(answer->capability))
                goto out_rcu_unlock;
 
+       err = -EAFNOSUPPORT;
+       if (!inet_netns_ok(net, protocol))
+               goto out_rcu_unlock;
+
        sock->ops = answer->ops;
        answer_prot = answer->prot;
        answer_no_check = answer->no_check;
@@ -446,7 +464,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        if (addr_len < sizeof(struct sockaddr_in))
                goto out;
 
-       chk_addr_ret = inet_addr_type(&init_net, addr->sin_addr.s_addr);
+       chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
 
        /* Not specified by any standard per-se, however it breaks too
         * many applications when removed.  It is unfortunate since
@@ -784,7 +802,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
        struct sock *sk = sock->sk;
        int err = 0;
-       struct net *net = sk->sk_net;
+       struct net *net = sock_net(sk);
 
        switch (cmd) {
                case SIOCGSTAMP:
@@ -1114,7 +1132,7 @@ int inet_sk_rebuild_header(struct sock *sk)
        };
 
        security_sk_classify_flow(sk, &fl);
-       err = ip_route_output_flow(&init_net, &rt, &fl, sk, 0);
+       err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0);
 }
        if (!err)
                sk_setup_caps(sk, &rt->u.dst);
@@ -1284,17 +1302,20 @@ static struct net_protocol tcp_protocol = {
        .gso_send_check = tcp_v4_gso_send_check,
        .gso_segment =  tcp_tso_segment,
        .no_policy =    1,
+       .netns_ok =     1,
 };
 
 static struct net_protocol udp_protocol = {
        .handler =      udp_rcv,
        .err_handler =  udp_err,
        .no_policy =    1,
+       .netns_ok =     1,
 };
 
 static struct net_protocol icmp_protocol = {
        .handler =      icmp_rcv,
        .no_policy =    1,
+       .netns_ok =     1,
 };
 
 static int __init init_ipv4_mibs(void)