gfp_t priority,
                                          struct proto *prot);
 extern void                    sk_free(struct sock *sk);
+extern void                    sk_release_kernel(struct sock *sk);
 extern struct sock             *sk_clone(const struct sock *sk,
                                          const gfp_t priority);
 
 }
 #endif
 
+/*
+ * Kernel sockets, f.e. rtnl or icmp_socket, are a part of a namespace.
+ * They should not hold a referrence to a namespace in order to allow
+ * to stop it.
+ * Sockets after sk_change_net should be released using sk_release_kernel
+ */
+static inline void sk_change_net(struct sock *sk, struct net *net)
+{
+       put_net(sk->sk_net);
+       sk->sk_net = net;
+}
+
 extern void sock_enable_timestamp(struct sock *sk);
 extern int sock_get_timestamp(struct sock *, struct timeval __user *);
 extern int sock_get_timestampns(struct sock *, struct timespec __user *);
 
        sk_prot_free(sk->sk_prot_creator, sk);
 }
 
+/*
+ * Last sock_put should drop referrence to sk->sk_net. It has already
+ * been dropped in sk_change_net. Taking referrence to stopping namespace
+ * is not an option.
+ * Take referrence to a socket to remove it from hash _alive_ and after that
+ * destroy it in the context of init_net.
+ */
+void sk_release_kernel(struct sock *sk)
+{
+       if (sk == NULL || sk->sk_socket == NULL)
+               return;
+
+       sock_hold(sk);
+       sock_release(sk->sk_socket);
+       sk->sk_net = get_net(&init_net);
+       sock_put(sk);
+}
+
 struct sock *sk_clone(const struct sock *sk, const gfp_t priority)
 {
        struct sock *newsk;
 
                goto out_sock_release_nosk;
 
        sk = sock->sk;
-       put_net(sk->sk_net);
-       sk->sk_net = net;
+       sk_change_net(sk, net);
 
        if (groups < 32)
                groups = 32;
 void
 netlink_kernel_release(struct sock *sk)
 {
-       /*
-        * Last sock_put should drop referrence to sk->sk_net. It has already
-        * been dropped in netlink_kernel_create. Taking referrence to stopping
-        * namespace is not an option.
-        * Take referrence to a socket to remove it from netlink lookup table
-        * _alive_ and after that destroy it in the context of init_net.
-        */
-       if (sk == NULL || sk->sk_socket == NULL)
-               return;
-
-       sock_hold(sk);
-       sock_release(sk->sk_socket);
-       sk->sk_net = get_net(&init_net);
-       sock_put(sk);
+       sk_release_kernel(sk);
 }
 EXPORT_SYMBOL(netlink_kernel_release);