2008-06-02 01:45:28

by Dave Young

[permalink] [raw]
Subject: [PATCH] bluetooth: rfcomm_dev_state_change deadlock fix

There's logic in __rfcomm_dlc_close:
rfcomm_dlc_lock(d);
d->state = BT_CLOSED;
d->state_changed(d, err);
rfcomm_dlc_unlock(d);

In rfcomm_dev_state_change, it's possible that rfcomm_dev_put try to take the
dlc lock, then we will deadlock.

Here fixed it by unlock dlc before rfcomm_dev_get in rfcomm_dev_state_change.

why not unlock just before rfcomm_dev_put? it's because there's another problem.
rfcomm_dev_get/rfcomm_dev_del will take rfcomm_dev_lock, but in rfcomm_dev_add
the lock order is : rfcomm_dev_lock --> dlc lock

so I unlock dlc before the taken of rfcomm_dev_lock.

Actually it's a regression caused by commit
1905f6c736cb618e07eca0c96e60e3c024023428, the dlc state_change could be two
callbacks : rfcomm_sk_state_change and rfcomm_dev_state_change. I missed the rfcomm_sk_state_change that time.

Thanks Arjan van de Ven <[email protected]> for the effort in commit
4c8411f8c115def968820a4df6658ccfd55d7f1a
but he missed the rfcomm_dev_state_change lock issue.

Signed-off-by: Dave Young <[email protected]>

---
net/bluetooth/rfcomm/tty.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)

diff -upr linux/net/bluetooth/rfcomm/tty.c linux.new/net/bluetooth/rfcomm/tty.c
--- linux/net/bluetooth/rfcomm/tty.c 2008-05-30 15:46:33.000000000 +0800
+++ linux.new/net/bluetooth/rfcomm/tty.c 2008-06-02 09:16:31.000000000 +0800
@@ -566,11 +566,22 @@ static void rfcomm_dev_state_change(stru
if (dlc->state == BT_CLOSED) {
if (!dev->tty) {
if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) {
- if (rfcomm_dev_get(dev->id) == NULL)
+ /* Drop DLC lock here to avoid deadlock
+ * 1. rfcomm_dev_get will take rfcomm_dev_lock
+ * but in rfcomm_dev_add there's lock order:
+ * rfcomm_dev_lock -> dlc lock
+ * 2. rfcomm_dev_put will deadlock if it's
+ * the last reference
+ */
+ rfcomm_dlc_unlock(dlc);
+ if (rfcomm_dev_get(dev->id) == NULL) {
+ rfcomm_dlc_lock(dlc);
return;
+ }

rfcomm_dev_del(dev);
rfcomm_dev_put(dev);
+ rfcomm_dlc_lock(dlc);
}
} else
tty_hangup(dev->tty);


2008-06-02 06:15:31

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH] bluetooth: rfcomm_dev_state_change deadlock fix

Hi Dave,

> There's logic in __rfcomm_dlc_close:
> rfcomm_dlc_lock(d);
> d->state = BT_CLOSED;
> d->state_changed(d, err);
> rfcomm_dlc_unlock(d);
>
> In rfcomm_dev_state_change, it's possible that rfcomm_dev_put try to
> take the
> dlc lock, then we will deadlock.
>
> Here fixed it by unlock dlc before rfcomm_dev_get in
> rfcomm_dev_state_change.
>
> why not unlock just before rfcomm_dev_put? it's because there's
> another problem.
> rfcomm_dev_get/rfcomm_dev_del will take rfcomm_dev_lock, but in
> rfcomm_dev_add
> the lock order is : rfcomm_dev_lock --> dlc lock
>
> so I unlock dlc before the taken of rfcomm_dev_lock.
>
> Actually it's a regression caused by commit
> 1905f6c736cb618e07eca0c96e60e3c024023428, the dlc state_change could
> be two
> callbacks : rfcomm_sk_state_change and rfcomm_dev_state_change. I
> missed the rfcomm_sk_state_change that time.
>
> Thanks Arjan van de Ven <[email protected]> for the effort in
> commit
> 4c8411f8c115def968820a4df6658ccfd55d7f1a
> but he missed the rfcomm_dev_state_change lock issue.
>
> Signed-off-by: Dave Young <[email protected]>

looks good. Thanks for adding a clear comment why we have to do it
this way.

Acked-by: Marcel Holtmann <[email protected]>

Regards

Marcel

2008-06-02 06:50:33

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] bluetooth: rfcomm_dev_state_change deadlock fix

From: Marcel Holtmann <[email protected]>
Date: Mon, 2 Jun 2008 08:15:03 +0200

> Acked-by: Marcel Holtmann <[email protected]>

Applied, but I had to add the commit header string to the two SHA ID
commit references. Please always provide the header line text as well
as the SHA ID when referencing commits because when backporting or
putting the patch into a different tree the SHA ID will be different
and people will have a terrible time trying to find the commits you
are referring to.

Thanks.

2008-06-02 06:57:58

by Dave Young

[permalink] [raw]
Subject: Re: [PATCH] bluetooth: rfcomm_dev_state_change deadlock fix

On Mon, Jun 2, 2008 at 2:50 PM, David Miller <[email protected]> wrote:
> From: Marcel Holtmann <[email protected]>
> Date: Mon, 2 Jun 2008 08:15:03 +0200
>
>> Acked-by: Marcel Holtmann <[email protected]>
>
> Applied, but I had to add the commit header string to the two SHA ID
> commit references. Please always provide the header line text as well
> as the SHA ID when referencing commits because when backporting or
> putting the patch into a different tree the SHA ID will be different
> and people will have a terrible time trying to find the commits you
> are referring to.

Will do next time, thanks.

>
> Thanks.
>



--
---
Regards
dave