Message ID | 1268413491-15172-2-git-send-email-chase.douglas@canonical.com |
---|---|
State | Accepted |
Delegated to: | Andy Whitcroft |
Headers | show |
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; > } >
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; }