Skip to content

Commit 1143277

Browse files
dcuigregkh
authored andcommitted
vsock: Fix a lockdep warning in __vsock_release()
[ Upstream commit 0d9138f ] Lockdep is unhappy if two locks from the same class are held. Fix the below warning for hyperv and virtio sockets (vmci socket code doesn't have the issue) by using lock_sock_nested() when __vsock_release() is called recursively: ============================================ WARNING: possible recursive locking detected 5.3.0+ #1 Not tainted -------------------------------------------- server/1795 is trying to acquire lock: ffff8880c5158990 (sk_lock-AF_VSOCK){+.+.}, at: hvs_release+0x10/0x120 [hv_sock] but task is already holding lock: ffff8880c5158150 (sk_lock-AF_VSOCK){+.+.}, at: __vsock_release+0x2e/0xf0 [vsock] other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(sk_lock-AF_VSOCK); lock(sk_lock-AF_VSOCK); *** DEADLOCK *** May be due to missing lock nesting notation 2 locks held by server/1795: #0: ffff8880c5d05ff8 (&sb->s_type->i_mutex_key#10){+.+.}, at: __sock_release+0x2d/0xa0 #1: ffff8880c5158150 (sk_lock-AF_VSOCK){+.+.}, at: __vsock_release+0x2e/0xf0 [vsock] stack backtrace: CPU: 5 PID: 1795 Comm: server Not tainted 5.3.0+ #1 Call Trace: dump_stack+0x67/0x90 __lock_acquire.cold.67+0xd2/0x20b lock_acquire+0xb5/0x1c0 lock_sock_nested+0x6d/0x90 hvs_release+0x10/0x120 [hv_sock] __vsock_release+0x24/0xf0 [vsock] __vsock_release+0xa0/0xf0 [vsock] vsock_release+0x12/0x30 [vsock] __sock_release+0x37/0xa0 sock_close+0x14/0x20 __fput+0xc1/0x250 task_work_run+0x98/0xc0 do_exit+0x344/0xc60 do_group_exit+0x47/0xb0 get_signal+0x15c/0xc50 do_signal+0x30/0x720 exit_to_usermode_loop+0x50/0xa0 do_syscall_64+0x24e/0x270 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x7f4184e85f31 Tested-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: Dexuan Cui <decui@microsoft.com> Reviewed-by: Stefano Garzarella <sgarzare@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent fba0b06 commit 1143277

File tree

3 files changed

+14
-6
lines changed

3 files changed

+14
-6
lines changed

net/vmw_vsock/af_vsock.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ struct sock *__vsock_create(struct net *net,
638638
}
639639
EXPORT_SYMBOL_GPL(__vsock_create);
640640

641-
static void __vsock_release(struct sock *sk)
641+
static void __vsock_release(struct sock *sk, int level)
642642
{
643643
if (sk) {
644644
struct sk_buff *skb;
@@ -648,9 +648,17 @@ static void __vsock_release(struct sock *sk)
648648
vsk = vsock_sk(sk);
649649
pending = NULL; /* Compiler warning. */
650650

651+
/* The release call is supposed to use lock_sock_nested()
652+
* rather than lock_sock(), if a sock lock should be acquired.
653+
*/
651654
transport->release(vsk);
652655

653-
lock_sock(sk);
656+
/* When "level" is SINGLE_DEPTH_NESTING, use the nested
657+
* version to avoid the warning "possible recursive locking
658+
* detected". When "level" is 0, lock_sock_nested(sk, level)
659+
* is the same as lock_sock(sk).
660+
*/
661+
lock_sock_nested(sk, level);
654662
sock_orphan(sk);
655663
sk->sk_shutdown = SHUTDOWN_MASK;
656664

@@ -659,7 +667,7 @@ static void __vsock_release(struct sock *sk)
659667

660668
/* Clean up any sockets that never were accepted. */
661669
while ((pending = vsock_dequeue_accept(sk)) != NULL) {
662-
__vsock_release(pending);
670+
__vsock_release(pending, SINGLE_DEPTH_NESTING);
663671
sock_put(pending);
664672
}
665673

@@ -708,7 +716,7 @@ EXPORT_SYMBOL_GPL(vsock_stream_has_space);
708716

709717
static int vsock_release(struct socket *sock)
710718
{
711-
__vsock_release(sock->sk);
719+
__vsock_release(sock->sk, 0);
712720
sock->sk = NULL;
713721
sock->state = SS_FREE;
714722

net/vmw_vsock/hyperv_transport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ static void hvs_release(struct vsock_sock *vsk)
528528
struct sock *sk = sk_vsock(vsk);
529529
bool remove_sock;
530530

531-
lock_sock(sk);
531+
lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
532532
remove_sock = hvs_close_lock_held(vsk);
533533
release_sock(sk);
534534
if (remove_sock)

net/vmw_vsock/virtio_transport_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ void virtio_transport_release(struct vsock_sock *vsk)
790790
struct sock *sk = &vsk->sk;
791791
bool remove_sock = true;
792792

793-
lock_sock(sk);
793+
lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
794794
if (sk->sk_type == SOCK_STREAM)
795795
remove_sock = virtio_transport_close(vsk);
796796

0 commit comments

Comments
 (0)