Thread (21 messages) 21 messages, 3 authors, 2012-03-09

Re: [PATCH 1/2] bluetooth: hci_ldisc: fix NULL-pointer dereference on tty_close

From: David Herrmann <hidden>
Date: 2012-03-09 13:57:14
Also in: lkml, netdev, stable

On Fri, Mar 9, 2012 at 2:04 PM, Johan Hovold [off-list ref] wrote:
On Thu, Mar 08, 2012 at 09:45:22AM -0800, Marcel Holtmann wrote:
quoted
Hi Johan,
quoted
quoted
quoted
Do not close protocol driver until device has been unregistered.

This fixes a race between tty_close and hci_dev_open which can res=
ult in
quoted
quoted
quoted
quoted
a NULL-pointer dereference.

The line discipline closes the protocol driver while we may still =
have
quoted
quoted
quoted
quoted
hci_dev_open sleeping on the req_lock mutex resulting in a NULL-po=
inter
quoted
quoted
quoted
quoted
dereference when lock is acquired and hci_init_req called.
[...]
quoted
what kernel version is this against? Our changes in bluetooth-next f=
ixed
quoted
quoted
quoted
some of the destruct handling.
This is against the latest rc as it needs to be fixed in 3.3, but I
missed a dependency to bluetooth-next as you point out below.
quoted
Also hci_unregister_dev should be calling the destruct handler and t=
hus
quoted
quoted
quoted
your change is now accessing hu but it got freed already.
You're right, my patch depends on 010666a126fc ("Bluetooth: Make
hci-destruct callback optional") and 797fe796c4 ("Bluetooth: uart-ldis=
c:
quoted
quoted
Fix memory leak and remove destruct cb") from bluetooth-next.

But since the latter one fixes a memory leak it should have been marke=
d
quoted hunk ↗ jump to hunk
quoted
quoted
for stable as well as pushed to Linus for 3.3, right?
we need to look into this and propose patches for -stable. Is your
problem still present with bluetooth-next or not?
Yes, both races are present in bluetooth-next of today (b8622cbd58f34)
and only takes an additional manual step to trigger (as the core no
longer tries to open the device twice automatically).

My two patches on top of either the two patches by David Herrmann
mentioned above or the following minimal fix of the same memory leak
would be sufficient to fix both races in 3.3:
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.=
c
quoted hunk ↗ jump to hunk
index 0711448..97c5faa 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -237,7 +237,6 @@ static void hci_uart_destruct(struct hci_dev *hdev)
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return;

=A0 =A0 =A0 =A0BT_DBG("%s", hdev->name);
- =A0 =A0 =A0 kfree(hdev->driver_data);
=A0}

=A0/* ------ LDISC part ------ */
@@ -316,6 +315,7 @@ static void hci_uart_tty_close(struct tty_struct *tty=
)
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0hci_free_d=
ev(hdev);
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 kfree(hu);
=A0 =A0 =A0 =A0}
=A0}
The "destruct"-callback was broken in many ways but working around it
without removing it seems wrong. This memory-leak occurs only if a
tty-device uses the uart-ldisc without a protocol bound to it.
Therefore, I didn't consider it important enough for stable. However,
if you want to fix this, leave the kfree() inside the destruct
callback but add another kfree() into the hci_uart_close() in an
"else"-clause like this:

if (test_and_clear_bit(...)) {
} else {
+   kfree(...);
}

This will still keep the bogus ref-counts inside hci_dev with the
destruct() callback but will also free the ldisc if no protocol is
set.
Regards
David
Thanks,
Johan
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth=
" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at =A0http://vger.kernel.org/majordomo-info.html
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help