From b922622ec6efad1f28ad13053fd17e744614f77b Mon Sep 17 00:00:00 2001 From: Craig Gallek Date: Tue, 30 Jun 2015 12:49:32 -0400 Subject: [PATCH] sock_diag: don't broadcast kernel sockets Kernel sockets do not hold a reference for the network namespace to which they point. Socket destruction broadcasting relies on the network namespace and will cause the splat below when a kernel socket is destroyed. This fix simply ignores kernel sockets when they are destroyed. Reported as: general protection fault: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC CPU: 1 PID: 9130 Comm: kworker/1:1 Not tainted 4.1.0-gelk-debug+ #1 Workqueue: sock_diag_events sock_diag_broadcast_destroy_work Stack: ffff8800b9c586c0 ffff8800b9c586c0 ffff8800ac4692c0 ffff8800936d4a90 ffff8800352efd38 ffffffff8469a93e ffff8800352efd98 ffffffffc09b9b90 ffff8800352efd78 ffff8800ac4692c0 ffff8800b9c586c0 ffff8800831b6ab8 Call Trace: [] ? mutex_unlock+0xe/0x10 [] ? inet_diag_handler_get_info+0x110/0x1fb [inet_diag] [] netlink_broadcast+0x1d/0x20 [] ? mutex_unlock+0xe/0x10 [] sock_diag_broadcast_destroy_work+0xd5/0x160 [] process_one_work+0x147/0x420 [] worker_thread+0x69/0x470 [] ? preempt_count_sub+0xa3/0xf0 [] ? rescuer_thread+0x320/0x320 [] kthread+0x107/0x120 [] ? kthread_create_on_node+0x1b0/0x1b0 [] ret_from_fork+0x3f/0x70 [] ? kthread_create_on_node+0x1b0/0x1b0 Tested: Using a debug kernel while 'ss -E' is running: ip netns add test-ns ip netns delete test-ns Fixes: eb4cb008529c sock_diag: define destruction multicast groups Fixes: 26abe14379f8 net: Modify sk_alloc to not reference count the netns of kernel sockets. Reported-by: Dave Jones Suggested-by: Eric Dumazet Signed-off-by: Craig Gallek Signed-off-by: David S. Miller --- net/core/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index e4be66fb3bd5..08f16db46070 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1454,7 +1454,7 @@ void sk_destruct(struct sock *sk) static void __sk_free(struct sock *sk) { - if (unlikely(sock_diag_has_destroy_listeners(sk))) + if (unlikely(sock_diag_has_destroy_listeners(sk) && sk->sk_net_refcnt)) sock_diag_broadcast_destroy(sk); else sk_destruct(sk); -- 2.20.1