net: kernel socket should be released in init_net namespace
[firefly-linux-kernel-4.4.55.git] / net / core / sock.c
index 93c8b20c91e496648f7f2e5c769c062ca2dd679d..d9f9e48253627efc3d45b45802fc39aa17162e4e 100644 (file)
@@ -466,7 +466,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
        skb_dst_force(skb);
 
        spin_lock_irqsave(&list->lock, flags);
-       skb->dropcount = atomic_read(&sk->sk_drops);
+       sock_skb_set_dropcount(sk, skb);
        __skb_queue_tail(list, skb);
        spin_unlock_irqrestore(&list->lock, flags);
 
@@ -1454,9 +1454,8 @@ void sk_release_kernel(struct sock *sk)
                return;
 
        sock_hold(sk);
-       sock_release(sk->sk_socket);
-       release_net(sock_net(sk));
        sock_net_set(sk, get_net(&init_net));
+       sock_release(sk->sk_socket);
        sock_put(sk);
 }
 EXPORT_SYMBOL(sk_release_kernel);
@@ -1538,6 +1537,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
                newsk->sk_err      = 0;
                newsk->sk_priority = 0;
                newsk->sk_incoming_cpu = raw_smp_processor_id();
+               atomic64_set(&newsk->sk_cookie, 0);
                /*
                 * Before updating sk_refcnt, we must commit prior changes to memory
                 * (Documentation/RCU/rculist_nulls.txt for details)
@@ -1661,19 +1661,6 @@ void sock_efree(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(sock_efree);
 
-#ifdef CONFIG_INET
-void sock_edemux(struct sk_buff *skb)
-{
-       struct sock *sk = skb->sk;
-
-       if (sk->sk_state == TCP_TIME_WAIT)
-               inet_twsk_put(inet_twsk(sk));
-       else
-               sock_put(sk);
-}
-EXPORT_SYMBOL(sock_edemux);
-#endif
-
 kuid_t sock_i_uid(struct sock *sk)
 {
        kuid_t uid;
@@ -2163,15 +2150,14 @@ int sock_no_getsockopt(struct socket *sock, int level, int optname,
 }
 EXPORT_SYMBOL(sock_no_getsockopt);
 
-int sock_no_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-                   size_t len)
+int sock_no_sendmsg(struct socket *sock, struct msghdr *m, size_t len)
 {
        return -EOPNOTSUPP;
 }
 EXPORT_SYMBOL(sock_no_sendmsg);
 
-int sock_no_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
-                   size_t len, int flags)
+int sock_no_recvmsg(struct socket *sock, struct msghdr *m, size_t len,
+                   int flags)
 {
        return -EOPNOTSUPP;
 }
@@ -2543,14 +2529,14 @@ int compat_sock_common_getsockopt(struct socket *sock, int level, int optname,
 EXPORT_SYMBOL(compat_sock_common_getsockopt);
 #endif
 
-int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock,
-                       struct msghdr *msg, size_t size, int flags)
+int sock_common_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
+                       int flags)
 {
        struct sock *sk = sock->sk;
        int addr_len = 0;
        int err;
 
-       err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT,
+       err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT,
                                   flags & ~MSG_DONTWAIT, &addr_len);
        if (err >= 0)
                msg->msg_namelen = addr_len;
@@ -2727,6 +2713,42 @@ static inline void release_proto_idx(struct proto *prot)
 }
 #endif
 
+static void req_prot_cleanup(struct request_sock_ops *rsk_prot)
+{
+       if (!rsk_prot)
+               return;
+       kfree(rsk_prot->slab_name);
+       rsk_prot->slab_name = NULL;
+       if (rsk_prot->slab) {
+               kmem_cache_destroy(rsk_prot->slab);
+               rsk_prot->slab = NULL;
+       }
+}
+
+static int req_prot_init(const struct proto *prot)
+{
+       struct request_sock_ops *rsk_prot = prot->rsk_prot;
+
+       if (!rsk_prot)
+               return 0;
+
+       rsk_prot->slab_name = kasprintf(GFP_KERNEL, "request_sock_%s",
+                                       prot->name);
+       if (!rsk_prot->slab_name)
+               return -ENOMEM;
+
+       rsk_prot->slab = kmem_cache_create(rsk_prot->slab_name,
+                                          rsk_prot->obj_size, 0,
+                                          SLAB_HWCACHE_ALIGN, NULL);
+
+       if (!rsk_prot->slab) {
+               pr_crit("%s: Can't create request sock SLAB cache!\n",
+                       prot->name);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
 int proto_register(struct proto *prot, int alloc_slab)
 {
        if (alloc_slab) {
@@ -2740,21 +2762,8 @@ int proto_register(struct proto *prot, int alloc_slab)
                        goto out;
                }
 
-               if (prot->rsk_prot != NULL) {
-                       prot->rsk_prot->slab_name = kasprintf(GFP_KERNEL, "request_sock_%s", prot->name);
-                       if (prot->rsk_prot->slab_name == NULL)
-                               goto out_free_sock_slab;
-
-                       prot->rsk_prot->slab = kmem_cache_create(prot->rsk_prot->slab_name,
-                                                                prot->rsk_prot->obj_size, 0,
-                                                                SLAB_HWCACHE_ALIGN, NULL);
-
-                       if (prot->rsk_prot->slab == NULL) {
-                               pr_crit("%s: Can't create request sock SLAB cache!\n",
-                                       prot->name);
-                               goto out_free_request_sock_slab_name;
-                       }
-               }
+               if (req_prot_init(prot))
+                       goto out_free_request_sock_slab;
 
                if (prot->twsk_prot != NULL) {
                        prot->twsk_prot->twsk_slab_name = kasprintf(GFP_KERNEL, "tw_sock_%s", prot->name);
@@ -2783,14 +2792,8 @@ int proto_register(struct proto *prot, int alloc_slab)
 out_free_timewait_sock_slab_name:
        kfree(prot->twsk_prot->twsk_slab_name);
 out_free_request_sock_slab:
-       if (prot->rsk_prot && prot->rsk_prot->slab) {
-               kmem_cache_destroy(prot->rsk_prot->slab);
-               prot->rsk_prot->slab = NULL;
-       }
-out_free_request_sock_slab_name:
-       if (prot->rsk_prot)
-               kfree(prot->rsk_prot->slab_name);
-out_free_sock_slab:
+       req_prot_cleanup(prot->rsk_prot);
+
        kmem_cache_destroy(prot->slab);
        prot->slab = NULL;
 out:
@@ -2810,11 +2813,7 @@ void proto_unregister(struct proto *prot)
                prot->slab = NULL;
        }
 
-       if (prot->rsk_prot != NULL && prot->rsk_prot->slab != NULL) {
-               kmem_cache_destroy(prot->rsk_prot->slab);
-               kfree(prot->rsk_prot->slab_name);
-               prot->rsk_prot->slab = NULL;
-       }
+       req_prot_cleanup(prot->rsk_prot);
 
        if (prot->twsk_prot != NULL && prot->twsk_prot->twsk_slab != NULL) {
                kmem_cache_destroy(prot->twsk_prot->twsk_slab);