History

Bluetooth: RFCOMM: Fix session UAF in set_termios

rfcomm_tty_set_termios() tests dlc->session without rfcomm_mutex and later passes the pointer to rfcomm_send_rpn(). The latter dereferences both session->initiator and session->sock. Meanwhile, krfcommd can unlink the DLC and free the session while holding rfcomm_mutex. The race can proceed as follows: TTY ioctl task krfcommd -------------- -------- load dlc->session enter rfcomm_send_rpn() lock rfcomm_mutex clear dlc->session free session unlock rfcomm_mutex read session->initiator KASAN reported: BUG: KASAN: slab-use-after-free in rfcomm_send_rpn+0x297/0x2a0 Read of size 4 at addr ffff88810012a850 by task poc/92 Call Trace: rfcomm_send_rpn+0x297/0x2a0 rfcomm_tty_set_termios+0x50d/0x850 tty_set_termios+0x596/0x950 set_termios+0x46a/0x6e0 tty_mode_ioctl+0x152/0xbd0 tty_ioctl+0x915/0x1240 __x64_sys_ioctl+0x134/0x1c0 Allocated by task 92: rfcomm_session_add+0x9e/0x2e0 rfcomm_dlc_open+0x8b1/0xe00 rfcomm_dev_activate+0x85/0x1a0 rfcomm_tty_open+0x90/0x280 Freed by task 68: kfree+0x131/0x3c0 rfcomm_session_del+0x119/0x180 rfcomm_run+0x737/0x4710 Add rfcomm_dlc_send_rpn(), which holds rfcomm_mutex while it verifies that the DLC is still attached and sends the RPN frame. Have the TTY path use the helper and drop its unlocked session check. This keeps the session valid through both the frame construction and socket send.

Chengfeng Ye committed 3 months ago

Commit c7833991 parent e9027ff3 files · +23 −4Browse files

Unified · Split

3 files
  1. include/net/bluetooth/rfcomm.h +3 −0
  2. net/bluetooth/rfcomm/core.c +17 −0
  3. net/bluetooth/rfcomm/tty.c +3 −4
include/net/bluetooth/rfcomm.h+3−0
@@ -226,6 +226,9 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, · 225 unmodified lines
226 u8 bit_rate, u8 data_bits, u8 stop_bits,226 u8 bit_rate, u8 data_bits, u8 stop_bits,
227 u8 parity, u8 flow_ctrl_settings,227 u8 parity, u8 flow_ctrl_settings,
228 u8 xon_char, u8 xoff_char, u16 param_mask);228 u8 xon_char, u8 xoff_char, u16 param_mask);
229int rfcomm_dlc_send_rpn(struct rfcomm_dlc *d, u8 bit_rate, u8 data_bits,
230 u8 stop_bits, u8 parity, u8 flow_ctrl_settings,
231 u8 xon_char, u8 xoff_char, u16 param_mask);
229 232
230/* ---- RFCOMM DLCs (channels) ---- */233/* ---- RFCOMM DLCs (channels) ---- */
231struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio);234struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio);
net/bluetooth/rfcomm/core.c+17−0
@@ -1028,6 +1028,23 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, · 1027 unmodified lines
1028 return rfcomm_send_frame(s, buf, ptr - buf);1028 return rfcomm_send_frame(s, buf, ptr - buf);
1029}1029}
1030 1030
1031int rfcomm_dlc_send_rpn(struct rfcomm_dlc *d, u8 bit_rate, u8 data_bits,
1032 u8 stop_bits, u8 parity, u8 flow_ctrl_settings,
1033 u8 xon_char, u8 xoff_char, u16 param_mask)
1034{
1035 int err = -ENOTCONN;
1036
1037 rfcomm_lock();
1038 if (d->session)
1039 err = rfcomm_send_rpn(d->session, 1, d->dlci, bit_rate,
1040 data_bits, stop_bits, parity,
1041 flow_ctrl_settings, xon_char, xoff_char,
1042 param_mask);
1043 rfcomm_unlock();
1044
1045 return err;
1046}
1047
1031static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status)1048static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status)
1032{1049{
1033 struct rfcomm_hdr *hdr;1050 struct rfcomm_hdr *hdr;
net/bluetooth/rfcomm/tty.c+3−4
@@ -858,7 +858,7 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, · 857 unmodified lines
858 858
859 BT_DBG("tty %p termios %p", tty, old);859 BT_DBG("tty %p termios %p", tty, old);
860 860
861 if (!dev || !dev->dlc || !dev->dlc->session)861 if (!dev || !dev->dlc)
862 return;862 return;
863 863
864 /* Handle turning off CRTSCTS */864 /* Handle turning off CRTSCTS */
@@ -979,9 +979,8 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, · 114 unmodified lines
979 }979 }
980 980
981 if (changes)981 if (changes)
982 rfcomm_send_rpn(dev->dlc->session, 1, dev->dlc->dlci, baud,982 rfcomm_dlc_send_rpn(dev->dlc, baud, data_bits, stop_bits, parity,
983 data_bits, stop_bits, parity,983 RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes);
984 RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes);
985}984}
986 985
987static void rfcomm_tty_throttle(struct tty_struct *tty)986static void rfcomm_tty_throttle(struct tty_struct *tty)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t