[PATCH] Bluetooth: RFCOMM: serialize session teardown

Chengfeng Ye <[email protected]>
Newsgroups org.kernel.vger.stable,org.kernel.vger.linux-bluetooth,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
rfcomm_kill_listener() walks session_list and deletes every session
without holding rfcomm_mutex.  A connect task holds that mutex while
rfcomm_session_create() adds a session and while its error path deletes
the session, but the unlocked teardown can still observe the object
between those operations.

The race can proceed as follows:

  connect task                    krfcommd
  ------------                    --------
  rfcomm_lock()
  rfcomm_session_add()
                                  fetch session from session_list
  kernel_connect() fails
  rfcomm_session_del()
    remove and free session
                                  rfcomm_session_del(session)

The final call then reads the freed session and may corrupt the list.

KASAN reported:

  BUG: KASAN: slab-use-after-free in rfcomm_session_del+0x15f/0x170
  Read of size 8 at addr ffff8881019e9b40 by task krfcommd/87
  Call Trace:
   rfcomm_session_del+0x15f/0x170
   rfcomm_run+0x16d5/0x3de0
   kthread+0x2c6/0x3b0
   ret_from_fork+0x36e/0x5a0
  Allocated by task 96:
   rfcomm_session_add+0x9e/0x300
   rfcomm_dlc_open+0x8b1/0xdf0
   rfcomm_sock_connect+0x34c/0x530
  Freed by task 96:
   kfree+0x131/0x3c0
   rfcomm_session_del+0x109/0x170
   rfcomm_dlc_open+0x9eb/0xdf0
   rfcomm_sock_connect+0x34c/0x530

Hold rfcomm_mutex across the teardown traversal, matching the locking
used by normal session processing and connect error cleanup.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: [email protected]
Signed-off-by: Chengfeng Ye <[email protected]>
---
 net/bluetooth/rfcomm/core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 9cdfea666a2c..5fe2758e8c47 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2178,8 +2178,10 @@ static void rfcomm_kill_listener(void)
 
 	BT_DBG("");
 
+	rfcomm_lock();
 	list_for_each_entry_safe(s, n, &session_list, list)
 		rfcomm_session_del(s);
+	rfcomm_unlock();
 }
 
 static int rfcomm_run(void *unused)
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.