diff options
author | Szymon Janc <szymon.janc@tieto.com> | 2011-09-26 08:19:47 -0400 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-10-14 14:04:54 -0400 |
commit | 88149db4948ef90cf6220d76e34955e46c2ff9f9 (patch) | |
tree | ea4293d07db101b0f9ff3f1d1f50047ba5f429d9 /net | |
parent | 8c23516fbb209ccf8f8c36268311c721faff29ee (diff) |
Bluetooth: rfcomm: Fix sleep in invalid context in rfcomm_security_cfm
This was triggered by turning off encryption on ACL link when rfcomm
was using high security. rfcomm_security_cfm (which is called from rx
task) was closing DLC and this involves sending disconnect message
(and locking socket).
Move closing DLC to rfcomm_process_dlcs and only flag DLC for closure
in rfcomm_security_cfm.
BUG: sleeping function called from invalid context at net/core/sock.c:2032
in_atomic(): 1, irqs_disabled(): 0, pid: 1788, name: kworker/0:3
[<c0068a08>] (unwind_backtrace+0x0/0x108) from [<c05e25dc>] (dump_stack+0x20/0x24)
[<c05e25dc>] (dump_stack+0x20/0x24) from [<c0087ba8>] (__might_sleep+0x110/0x12c)
[<c0087ba8>] (__might_sleep+0x110/0x12c) from [<c04801d8>] (lock_sock_nested+0x2c/0x64)
[<c04801d8>] (lock_sock_nested+0x2c/0x64) from [<c05670c8>] (l2cap_sock_sendmsg+0x58/0xcc)
[<c05670c8>] (l2cap_sock_sendmsg+0x58/0xcc) from [<c047cf6c>] (sock_sendmsg+0xb0/0xd0)
[<c047cf6c>] (sock_sendmsg+0xb0/0xd0) from [<c047cfc8>] (kernel_sendmsg+0x3c/0x44)
[<c047cfc8>] (kernel_sendmsg+0x3c/0x44) from [<c056b0e8>] (rfcomm_send_frame+0x50/0x58)
[<c056b0e8>] (rfcomm_send_frame+0x50/0x58) from [<c056b168>] (rfcomm_send_disc+0x78/0x80)
[<c056b168>] (rfcomm_send_disc+0x78/0x80) from [<c056b9f4>] (__rfcomm_dlc_close+0x2d0/0x2fc)
[<c056b9f4>] (__rfcomm_dlc_close+0x2d0/0x2fc) from [<c056bbac>] (rfcomm_security_cfm+0x140/0x1e0)
[<c056bbac>] (rfcomm_security_cfm+0x140/0x1e0) from [<c0555ec0>] (hci_event_packet+0x1ce8/0x4d84)
[<c0555ec0>] (hci_event_packet+0x1ce8/0x4d84) from [<c0550380>] (hci_rx_task+0x1d0/0x2d0)
[<c0550380>] (hci_rx_task+0x1d0/0x2d0) from [<c009ee04>] (tasklet_action+0x138/0x1e4)
[<c009ee04>] (tasklet_action+0x138/0x1e4) from [<c009f21c>] (__do_softirq+0xcc/0x274)
[<c009f21c>] (__do_softirq+0xcc/0x274) from [<c009f6c0>] (do_softirq+0x60/0x6c)
[<c009f6c0>] (do_softirq+0x60/0x6c) from [<c009f794>] (local_bh_enable_ip+0xc8/0xd4)
[<c009f794>] (local_bh_enable_ip+0xc8/0xd4) from [<c05e5804>] (_raw_spin_unlock_bh+0x48/0x4c)
[<c05e5804>] (_raw_spin_unlock_bh+0x48/0x4c) from [<c040d470>] (data_from_chip+0xf4/0xaec)
[<c040d470>] (data_from_chip+0xf4/0xaec) from [<c04136c0>] (send_skb_to_core+0x40/0x178)
[<c04136c0>] (send_skb_to_core+0x40/0x178) from [<c04139f4>] (cg2900_hu_receive+0x15c/0x2d0)
[<c04139f4>] (cg2900_hu_receive+0x15c/0x2d0) from [<c0414cb8>] (hci_uart_tty_receive+0x74/0xa0)
[<c0414cb8>] (hci_uart_tty_receive+0x74/0xa0) from [<c02cbd9c>] (flush_to_ldisc+0x188/0x198)
[<c02cbd9c>] (flush_to_ldisc+0x188/0x198) from [<c00b2774>] (process_one_work+0x144/0x4b8)
[<c00b2774>] (process_one_work+0x144/0x4b8) from [<c00b2e8c>] (worker_thread+0x198/0x468)
[<c00b2e8c>] (worker_thread+0x198/0x468) from [<c00b9bc8>] (kthread+0x98/0xa0)
[<c00b9bc8>] (kthread+0x98/0xa0) from [<c0061744>] (kernel_thread_exit+0x0/0x8)
Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 5ba3f6df665c..71ef2581c60f 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -1802,6 +1802,11 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s) | |||
1802 | continue; | 1802 | continue; |
1803 | } | 1803 | } |
1804 | 1804 | ||
1805 | if (test_bit(RFCOMM_ENC_DROP, &d->flags)) { | ||
1806 | __rfcomm_dlc_close(d, ECONNREFUSED); | ||
1807 | continue; | ||
1808 | } | ||
1809 | |||
1805 | if (test_and_clear_bit(RFCOMM_AUTH_ACCEPT, &d->flags)) { | 1810 | if (test_and_clear_bit(RFCOMM_AUTH_ACCEPT, &d->flags)) { |
1806 | rfcomm_dlc_clear_timer(d); | 1811 | rfcomm_dlc_clear_timer(d); |
1807 | if (d->out) { | 1812 | if (d->out) { |
@@ -2074,7 +2079,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
2074 | if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) { | 2079 | if (test_and_clear_bit(RFCOMM_SEC_PENDING, &d->flags)) { |
2075 | rfcomm_dlc_clear_timer(d); | 2080 | rfcomm_dlc_clear_timer(d); |
2076 | if (status || encrypt == 0x00) { | 2081 | if (status || encrypt == 0x00) { |
2077 | __rfcomm_dlc_close(d, ECONNREFUSED); | 2082 | set_bit(RFCOMM_ENC_DROP, &d->flags); |
2078 | continue; | 2083 | continue; |
2079 | } | 2084 | } |
2080 | } | 2085 | } |
@@ -2085,7 +2090,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
2085 | rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT); | 2090 | rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT); |
2086 | continue; | 2091 | continue; |
2087 | } else if (d->sec_level == BT_SECURITY_HIGH) { | 2092 | } else if (d->sec_level == BT_SECURITY_HIGH) { |
2088 | __rfcomm_dlc_close(d, ECONNREFUSED); | 2093 | set_bit(RFCOMM_ENC_DROP, &d->flags); |
2089 | continue; | 2094 | continue; |
2090 | } | 2095 | } |
2091 | } | 2096 | } |