Skip to content

Commit

Permalink
NFC: Fix sleeping in atomic when releasing socket
Browse files Browse the repository at this point in the history
nfc_llcp_socket_release is calling lock_sock/release_sock while holding
write lock for rwlock. Use bh_lock/unlock_sock instead.

BUG: sleeping function called from invalid context at net/core/sock.c:2138
in_atomic(): 1, irqs_disabled(): 0, pid: 56, name: kworker/1:1
4 locks held by kworker/1:1/56:
Pid: 56, comm: kworker/1:1 Not tainted 3.5.0-999-nfc+ imx6-dongle#7
Call Trace:
[<ffffffff810952c5>] __might_sleep+0x145/0x200
[<ffffffff815d7686>] lock_sock_nested+0x36/0xa0
[<ffffffff81731569>] ? _raw_write_lock+0x49/0x50
[<ffffffffa04aa100>] ? nfc_llcp_socket_release+0x30/0x200 [nfc]
[<ffffffffa04aa122>] nfc_llcp_socket_release+0x52/0x200 [nfc]
[<ffffffffa04ab9f0>] nfc_llcp_mac_is_down+0x20/0x30 [nfc]
[<ffffffffa04a6fea>] nfc_dep_link_down+0xaa/0xf0 [nfc]
[<ffffffffa04a9bb5>] nfc_llcp_timeout_work+0x15/0x20 [nfc]
[<ffffffff810825f7>] process_one_work+0x197/0x7c0
[<ffffffff81082596>] ? process_one_work+0x136/0x7c0
[<ffffffff8172fbc9>] ? __schedule+0x419/0x9c0
[<ffffffffa04a9ba0>] ? nfc_llcp_build_gb+0x1b0/0x1b0 [nfc]
[<ffffffff81083090>] worker_thread+0x190/0x4c0
[<ffffffff81082f00>] ? rescuer_thread+0x2a0/0x2a0
[<ffffffff81088d1e>] kthread+0xae/0xc0
[<ffffffff810caafd>] ? trace_hardirqs_on+0xd/0x10
[<ffffffff8173acc4>] kernel_thread_helper+0x4/0x10
[<ffffffff81732174>] ? retint_restore_args+0x13/0x13
[<ffffffff81088c70>] ? flush_kthread_worker+0x150/0x150
[<ffffffff8173acc0>] ? gs_change+0x13/0x13

Signed-off-by: Szymon Janc <[email protected]>
Signed-off-by: Samuel Ortiz <[email protected]>
  • Loading branch information
Szymon Janc authored and Samuel Ortiz committed Sep 27, 2012
1 parent 3c0cc8a commit 50b78b2
Showing 1 changed file with 5 additions and 5 deletions.
10 changes: 5 additions & 5 deletions net/nfc/llcp/llcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
sk_for_each_safe(sk, node, tmp, &local->sockets.head) {
llcp_sock = nfc_llcp_sock(sk);

lock_sock(sk);
bh_lock_sock(sk);

if (sk->sk_state == LLCP_CONNECTED)
nfc_put_device(llcp_sock->dev);
Expand All @@ -68,26 +68,26 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue,
accept_queue) {
accept_sk = &lsk->sk;
lock_sock(accept_sk);
bh_lock_sock(accept_sk);

nfc_llcp_accept_unlink(accept_sk);

accept_sk->sk_state = LLCP_CLOSED;

release_sock(accept_sk);
bh_unlock_sock(accept_sk);

sock_orphan(accept_sk);
}

if (listen == true) {
release_sock(sk);
bh_unlock_sock(sk);
continue;
}
}

sk->sk_state = LLCP_CLOSED;

release_sock(sk);
bh_unlock_sock(sk);

sock_orphan(sk);

Expand Down

0 comments on commit 50b78b2

Please sign in to comment.