Patchwork [1/1] Ubuntu: Bluetooth: Fix sleeping function in RFCOMM within invalid context

login
register
mail settings
Submitter Chase Douglas
Date March 12, 2010, 5:04 p.m.
Message ID <1268413491-15172-2-git-send-email-chase.douglas@canonical.com>
Download mbox | patch
Permalink /patch/47682/
State Accepted
Delegated to: Andy Whitcroft
Headers show

Comments

Chase Douglas - March 12, 2010, 5:04 p.m.
From: Marcel Holtmann <marcel@holtmann.org>

With the commit 9e726b17422bade75fba94e625cd35fd1353e682 the
rfcomm_session_put() gets accidentially called from a timeout
callback and results in this:

BUG: sleeping function called from invalid context at net/core/sock.c:1897
in_atomic(): 1, irqs_disabled(): 0, pid: 0, name: swapper
Pid: 0, comm: swapper Tainted: P           2.6.32 #31
Call Trace:
 <IRQ>  [<ffffffff81036455>] __might_sleep+0xf8/0xfa
 [<ffffffff8138ef1d>] lock_sock_nested+0x29/0xc4
 [<ffffffffa03921b3>] lock_sock+0xb/0xd [l2cap]
 [<ffffffffa03948e6>] l2cap_sock_shutdown+0x1c/0x76 [l2cap]
 [<ffffffff8106adea>] ? clockevents_program_event+0x75/0x7e
 [<ffffffff8106bea2>] ? tick_dev_program_event+0x37/0xa5
 [<ffffffffa0394967>] l2cap_sock_release+0x27/0x67 [l2cap]
 [<ffffffff8138c971>] sock_release+0x1a/0x67
 [<ffffffffa03d2492>] rfcomm_session_del+0x34/0x53 [rfcomm]
 [<ffffffffa03d24c5>] rfcomm_session_put+0x14/0x16 [rfcomm]
 [<ffffffffa03d28b4>] rfcomm_session_timeout+0xe/0x1a [rfcomm]
 [<ffffffff810554a8>] run_timer_softirq+0x1e2/0x29a
 [<ffffffffa03d28a6>] ? rfcomm_session_timeout+0x0/0x1a [rfcomm]
 [<ffffffff8104e0f6>] __do_softirq+0xfe/0x1c5
 [<ffffffff8100e8ce>] ? timer_interrupt+0x1a/0x21
 [<ffffffff8100cc4c>] call_softirq+0x1c/0x28
 [<ffffffff8100e05b>] do_softirq+0x33/0x6b
 [<ffffffff8104daf6>] irq_exit+0x36/0x85
 [<ffffffff8100d7a9>] do_IRQ+0xa6/0xbd
 [<ffffffff8100c493>] ret_from_intr+0x0/0xa
 <EOI>  [<ffffffff812585b3>] ? acpi_idle_enter_bm+0x269/0x294
 [<ffffffff812585a9>] ? acpi_idle_enter_bm+0x25f/0x294
 [<ffffffff81373ddc>] ? cpuidle_idle_call+0x97/0x107
 [<ffffffff8100aca0>] ? cpu_idle+0x53/0xaa
 [<ffffffff81429006>] ? rest_init+0x7a/0x7c
 [<ffffffff8177bc8c>] ? start_kernel+0x389/0x394
 [<ffffffff8177b29c>] ? x86_64_start_reservations+0xac/0xb0
 [<ffffffff8177b384>] ? x86_64_start_kernel+0xe4/0xeb

To fix this, the rfcomm_session_put() needs to be moved out of
rfcomm_session_timeout() into rfcomm_process_sessions(). In that
context it is perfectly fine to sleep and disconnect the socket.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Tested-by: David John <davidjon@xenontk.org>
(cherry picked from commit 485f1eff73a7b932fd3abb0dfcf804e1a1f59025)

BugLink: http://bugs.launchpad.net/bugs/534549

Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
---
 net/bluetooth/rfcomm/core.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Stefan Bader - March 15, 2010, 12:16 p.m.
As it causes crashes I think we want it as pre-stable. It also should be
acceptable to upstream stable, but it will at least miss the next release as it
looks. In general, could you (probably all that do) cc me on mails going to
stable? It would help me to keep track on those things, too.

Chase Douglas wrote:
> From: Marcel Holtmann <marcel@holtmann.org>
> 
> With the commit 9e726b17422bade75fba94e625cd35fd1353e682 the
> rfcomm_session_put() gets accidentially called from a timeout
> callback and results in this:
> 
> BUG: sleeping function called from invalid context at net/core/sock.c:1897
> in_atomic(): 1, irqs_disabled(): 0, pid: 0, name: swapper
> Pid: 0, comm: swapper Tainted: P           2.6.32 #31
> Call Trace:
>  <IRQ>  [<ffffffff81036455>] __might_sleep+0xf8/0xfa
>  [<ffffffff8138ef1d>] lock_sock_nested+0x29/0xc4
>  [<ffffffffa03921b3>] lock_sock+0xb/0xd [l2cap]
>  [<ffffffffa03948e6>] l2cap_sock_shutdown+0x1c/0x76 [l2cap]
>  [<ffffffff8106adea>] ? clockevents_program_event+0x75/0x7e
>  [<ffffffff8106bea2>] ? tick_dev_program_event+0x37/0xa5
>  [<ffffffffa0394967>] l2cap_sock_release+0x27/0x67 [l2cap]
>  [<ffffffff8138c971>] sock_release+0x1a/0x67
>  [<ffffffffa03d2492>] rfcomm_session_del+0x34/0x53 [rfcomm]
>  [<ffffffffa03d24c5>] rfcomm_session_put+0x14/0x16 [rfcomm]
>  [<ffffffffa03d28b4>] rfcomm_session_timeout+0xe/0x1a [rfcomm]
>  [<ffffffff810554a8>] run_timer_softirq+0x1e2/0x29a
>  [<ffffffffa03d28a6>] ? rfcomm_session_timeout+0x0/0x1a [rfcomm]
>  [<ffffffff8104e0f6>] __do_softirq+0xfe/0x1c5
>  [<ffffffff8100e8ce>] ? timer_interrupt+0x1a/0x21
>  [<ffffffff8100cc4c>] call_softirq+0x1c/0x28
>  [<ffffffff8100e05b>] do_softirq+0x33/0x6b
>  [<ffffffff8104daf6>] irq_exit+0x36/0x85
>  [<ffffffff8100d7a9>] do_IRQ+0xa6/0xbd
>  [<ffffffff8100c493>] ret_from_intr+0x0/0xa
>  <EOI>  [<ffffffff812585b3>] ? acpi_idle_enter_bm+0x269/0x294
>  [<ffffffff812585a9>] ? acpi_idle_enter_bm+0x25f/0x294
>  [<ffffffff81373ddc>] ? cpuidle_idle_call+0x97/0x107
>  [<ffffffff8100aca0>] ? cpu_idle+0x53/0xaa
>  [<ffffffff81429006>] ? rest_init+0x7a/0x7c
>  [<ffffffff8177bc8c>] ? start_kernel+0x389/0x394
>  [<ffffffff8177b29c>] ? x86_64_start_reservations+0xac/0xb0
>  [<ffffffff8177b384>] ? x86_64_start_kernel+0xe4/0xeb
> 
> To fix this, the rfcomm_session_put() needs to be moved out of
> rfcomm_session_timeout() into rfcomm_process_sessions(). In that
> context it is perfectly fine to sleep and disconnect the socket.
> 
> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
> Tested-by: David John <davidjon@xenontk.org>
> (cherry picked from commit 485f1eff73a7b932fd3abb0dfcf804e1a1f59025)
> 
> BugLink: http://bugs.launchpad.net/bugs/534549
> 
> Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
> ---
>  net/bluetooth/rfcomm/core.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
> index 25692bc..b3bcd4b 100644
> --- a/net/bluetooth/rfcomm/core.c
> +++ b/net/bluetooth/rfcomm/core.c
> @@ -251,7 +251,6 @@ static void rfcomm_session_timeout(unsigned long arg)
>  	BT_DBG("session %p state %ld", s, s->state);
>  
>  	set_bit(RFCOMM_TIMED_OUT, &s->flags);
> -	rfcomm_session_put(s);
>  	rfcomm_schedule(RFCOMM_SCHED_TIMEO);
>  }
>  
> @@ -1917,6 +1916,7 @@ static inline void rfcomm_process_sessions(void)
>  		if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) {
>  			s->state = BT_DISCONN;
>  			rfcomm_send_disc(s, 0);
> +			rfcomm_session_put(s);
>  			continue;
>  		}
>

Patch

diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 25692bc..b3bcd4b 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -251,7 +251,6 @@  static void rfcomm_session_timeout(unsigned long arg)
 	BT_DBG("session %p state %ld", s, s->state);
 
 	set_bit(RFCOMM_TIMED_OUT, &s->flags);
-	rfcomm_session_put(s);
 	rfcomm_schedule(RFCOMM_SCHED_TIMEO);
 }
 
@@ -1917,6 +1916,7 @@  static inline void rfcomm_process_sessions(void)
 		if (test_and_clear_bit(RFCOMM_TIMED_OUT, &s->flags)) {
 			s->state = BT_DISCONN;
 			rfcomm_send_disc(s, 0);
+			rfcomm_session_put(s);
 			continue;
 		}