Remove rfcomm_security_records map, store records in tBTA_JV_PCB instead.
The map is globally keyed by SCN, which causes issues when SCNs are
reused (server vs client, or different device connections). tBTA_JV_PCBs
are distinct for every (port, device, server/client) tuple, and so fit
this use-case.
Tag: #stability
Bug: 230553684
Test: Manual (see bug)
Change-Id: Iae24f07fd5d19f66126abfe61052fab96d1b1bdf
diff --git a/system/bta/ag/bta_ag_sdp.cc b/system/bta/ag/bta_ag_sdp.cc
index e9af15c..bb39a43 100644
--- a/system/bta/ag/bta_ag_sdp.cc
+++ b/system/bta/ag/bta_ag_sdp.cc
@@ -271,7 +271,6 @@
bta_ag_cb.profile[i].sdp_handle = 0;
}
BTM_FreeSCN(bta_ag_cb.profile[i].scn);
- RFCOMM_ClearSecurityRecord(bta_ag_cb.profile[i].scn);
bta_sys_remove_uuid(bta_ag_uuid[i]);
}
}
diff --git a/system/bta/hf_client/bta_hf_client_sdp.cc b/system/bta/hf_client/bta_hf_client_sdp.cc
index 96b7a6d..4625b6d 100755
--- a/system/bta/hf_client/bta_hf_client_sdp.cc
+++ b/system/bta/hf_client/bta_hf_client_sdp.cc
@@ -204,7 +204,6 @@
SDP_DeleteRecord(client_cb->sdp_handle);
client_cb->sdp_handle = 0;
BTM_FreeSCN(client_cb->scn);
- RFCOMM_ClearSecurityRecord(client_cb->scn);
bta_sys_remove_uuid(UUID_SERVCLASS_HF_HANDSFREE);
}
}
diff --git a/system/bta/jv/bta_jv_act.cc b/system/bta/jv/bta_jv_act.cc
index 6f50077..db8b05c 100644
--- a/system/bta/jv/bta_jv_act.cc
+++ b/system/bta/jv/bta_jv_act.cc
@@ -317,15 +317,11 @@
p_pcb->handle = 0;
p_cb->curr_sess--;
if (p_cb->curr_sess == 0) {
- RFCOMM_ClearSecurityRecord(p_cb->scn);
p_cb->scn = 0;
p_cb->p_cback = NULL;
p_cb->handle = 0;
p_cb->curr_sess = -1;
}
- if (remove_server) {
- RFCOMM_ClearSecurityRecord(p_cb->scn);
- }
}
return status;
}
@@ -1356,7 +1352,6 @@
bta_jv.rfc_cl_init = evt_data;
p_cback(BTA_JV_RFCOMM_CL_INIT_EVT, &bta_jv, rfcomm_slot_id);
if (bta_jv.rfc_cl_init.status == BTA_JV_FAILURE) {
- RFCOMM_ClearSecurityRecord(remote_scn);
if (handle) RFCOMM_RemoveConnection(handle);
}
}
@@ -1532,6 +1527,7 @@
tPORT_STATE port_state;
uint32_t event_mask = BTA_JV_RFC_EV_MASK;
tBTA_JV_PCB* p_pcb = NULL;
+ tBTA_SEC sec_mask;
if (p_cb->max_sess > 1) {
for (i = 0; i < p_cb->max_sess; i++) {
if (p_cb->rfc_hdl[i] != 0) {
@@ -1562,10 +1558,16 @@
<< ", si=" << si;
if (used < p_cb->max_sess && listen == 1 && si) {
si--;
- if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, true,
- BTA_JV_DEF_RFC_MTU, RawAddress::kAny,
- &(p_cb->rfc_hdl[si]),
- bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS) {
+ if (PORT_GetSecurityMask(p_pcb_open->port_handle, &sec_mask) !=
+ PORT_SUCCESS) {
+ LOG(ERROR) << __func__
+ << ": RFCOMM_CreateConnection failed: invalid port_handle";
+ }
+
+ if (RFCOMM_CreateConnectionWithSecurity(
+ p_cb->sec_id, p_cb->scn, true, BTA_JV_DEF_RFC_MTU,
+ RawAddress::kAny, &(p_cb->rfc_hdl[si]), bta_jv_port_mgmt_sr_cback,
+ sec_mask) == PORT_SUCCESS) {
p_cb->curr_sess++;
p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1];
p_pcb->state = BTA_JV_ST_SR_LISTEN;
@@ -1652,7 +1654,6 @@
if (bta_jv.rfc_start.status == BTA_JV_SUCCESS) {
PORT_SetDataCOCallback(handle, bta_jv_port_data_co_cback);
} else {
- RFCOMM_ClearSecurityRecord(local_scn);
if (handle) RFCOMM_RemoveConnection(handle);
}
}
diff --git a/system/stack/include/btm_api_types.h b/system/stack/include/btm_api_types.h
index 3e68f46..ec49380 100644
--- a/system/stack/include/btm_api_types.h
+++ b/system/stack/include/btm_api_types.h
@@ -283,6 +283,7 @@
}
}
+/* BTM_SEC security masks */
enum : uint16_t {
/* Nothing required */
BTM_SEC_NONE = 0x0000,
diff --git a/system/stack/include/port_api.h b/system/stack/include/port_api.h
index 832832f..ed4733a 100644
--- a/system/stack/include/port_api.h
+++ b/system/stack/include/port_api.h
@@ -191,13 +191,6 @@
tPORT_CALLBACK* p_mgmt_cb,
uint16_t sec_mask);
-extern void RFCOMM_ClearSecurityRecord(uint32_t scn);
-
-extern int RFCOMM_CreateConnection(uint16_t uuid, uint8_t scn, bool is_server,
- uint16_t mtu, const RawAddress& bd_addr,
- uint16_t* p_handle,
- tPORT_CALLBACK* p_mgmt_cb);
-
/*******************************************************************************
*
* Function RFCOMM_RemoveConnection
@@ -434,4 +427,15 @@
******************************************************************************/
extern const char* PORT_GetResultString(const uint8_t result_code);
+/*******************************************************************************
+ *
+ * Function PORT_GetSecurityMask
+ *
+ * Description This function returns the security bitmask for a port.
+ *
+ * Returns the security bitmask.
+ *
+ ******************************************************************************/
+extern int PORT_GetSecurityMask(uint16_t handle, uint16_t* sec_mask);
+
#endif /* PORT_API_H */
diff --git a/system/stack/rfcomm/port_api.cc b/system/stack/rfcomm/port_api.cc
index cca0f05..3af79ab 100644
--- a/system/stack/rfcomm/port_api.cc
+++ b/system/stack/rfcomm/port_api.cc
@@ -71,30 +71,13 @@
"Invalid SCN",
"Unknown result code"};
-int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn,
- bool is_server, uint16_t mtu,
- const RawAddress& bd_addr,
- uint16_t* p_handle,
- tPORT_CALLBACK* p_mgmt_cb,
- uint16_t sec_mask) {
- rfcomm_security_records[scn] = sec_mask;
-
- return RFCOMM_CreateConnection(uuid, scn, is_server, mtu, bd_addr, p_handle,
- p_mgmt_cb);
-}
-
-extern void RFCOMM_ClearSecurityRecord(uint32_t scn) {
- rfcomm_security_records.erase(scn);
-}
-
/*******************************************************************************
*
- * Function RFCOMM_CreateConnection
+ * Function RFCOMM_CreateConnectionWithSecurity
*
- * Description RFCOMM_CreateConnection function is used from the
- * application to establish serial port connection to the peer
- * device, or allow RFCOMM to accept a connection from the peer
- * application.
+ * Description RFCOMM_CreateConnectionWithSecurity function is used from
+ *the application to establish serial port connection to the peer device, or
+ *allow RFCOMM to accept a connection from the peer application.
*
* Parameters: scn - Service Channel Number as registered with
* the SDP (server) or obtained using SDP from
@@ -102,12 +85,12 @@
* is_server - true if requesting application is a server
* mtu - Maximum frame size the application can accept
* bd_addr - address of the peer (client)
- * mask - specifies events to be enabled. A value
- * of zero disables all events.
* p_handle - OUT pointer to the handle.
* p_mgmt_cb - pointer to callback function to receive
* connection up/down events.
- * Notes:
+ * sec_mask - bitmask of BTM_SEC_* values indicating the
+ * minimum security requirements for this
+ *connection Notes:
*
* Server can call this function with the same scn parameter multiple times if
* it is ready to accept multiple simulteneous connections.
@@ -118,9 +101,12 @@
* (scn * 2 + 1) dlci.
*
******************************************************************************/
-int RFCOMM_CreateConnection(uint16_t uuid, uint8_t scn, bool is_server,
- uint16_t mtu, const RawAddress& bd_addr,
- uint16_t* p_handle, tPORT_CALLBACK* p_mgmt_cb) {
+int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn,
+ bool is_server, uint16_t mtu,
+ const RawAddress& bd_addr,
+ uint16_t* p_handle,
+ tPORT_CALLBACK* p_mgmt_cb,
+ uint16_t sec_mask) {
*p_handle = 0;
if ((scn == 0) || (scn >= PORT_MAX_RFC_PORTS)) {
@@ -176,6 +162,7 @@
<< ", dlci=" << +dlci;
return PORT_NO_RESOURCES;
}
+ p_port->sec_mask = sec_mask;
*p_handle = p_port->handle;
// Get default signal state
@@ -1126,7 +1113,6 @@
******************************************************************************/
void RFCOMM_Init(void) {
memset(&rfc_cb, 0, sizeof(tRFC_CB)); /* Init RFCOMM control block */
- rfcomm_security_records = {};
rfc_lcid_mcb = {};
rfc_cb.rfc.last_mux = MAX_BD_CONNECTIONS;
@@ -1173,3 +1159,23 @@
return result_code_strings[result_code];
}
+
+/*******************************************************************************
+ *
+ * Function PORT_GetSecurityMask
+ *
+ * Description This function returns the security bitmask for a port.
+ *
+ * Returns A result code, and writes the bitmask into the output
+ *parameter.
+ *
+ ******************************************************************************/
+int PORT_GetSecurityMask(uint16_t handle, uint16_t* sec_mask) {
+ /* Check if handle is valid to avoid crashing */
+ if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
+ return (PORT_BAD_HANDLE);
+ }
+ tPORT* p_port = &rfc_cb.port.port[handle - 1];
+ *sec_mask = p_port->sec_mask;
+ return (PORT_SUCCESS);
+}
diff --git a/system/stack/rfcomm/port_int.h b/system/stack/rfcomm/port_int.h
index e406d4a..61935b1 100644
--- a/system/stack/rfcomm/port_int.h
+++ b/system/stack/rfcomm/port_int.h
@@ -189,6 +189,8 @@
bool keep_port_handle; /* true if port is not deallocated when closing */
/* it is set to true for server when allocating port */
uint16_t keep_mtu; /* Max MTU that port can receive by server */
+ uint16_t sec_mask; /* Bitmask of security requirements for this port */
+ /* see the BTM_SEC_* values in btm_api_types.h */
} tPORT;
/* Define the PORT/RFCOMM control structure
diff --git a/system/stack/rfcomm/rfc_int.h b/system/stack/rfcomm/rfc_int.h
index 61706a2..f07485e 100644
--- a/system/stack/rfcomm/rfc_int.h
+++ b/system/stack/rfcomm/rfc_int.h
@@ -179,9 +179,6 @@
extern tRFC_CB rfc_cb;
-extern std::unordered_map<uint32_t /* scn */, uint16_t /* sec_mask */>
- rfcomm_security_records;
-
/* MCB based on the L2CAP's lcid */
extern std::unordered_map<uint16_t /* cid */, tRFC_MCB*> rfc_lcid_mcb;
diff --git a/system/stack/rfcomm/rfc_port_fsm.cc b/system/stack/rfcomm/rfc_port_fsm.cc
index 7c751d1..cd5cbb9 100644
--- a/system/stack/rfcomm/rfc_port_fsm.cc
+++ b/system/stack/rfcomm/rfc_port_fsm.cc
@@ -122,18 +122,12 @@
******************************************************************************/
void rfc_port_sm_state_closed(tPORT* p_port, tRFC_PORT_EVENT event,
void* p_data) {
- uint32_t scn = (uint32_t)(p_port->dlci / 2);
switch (event) {
case RFC_PORT_EVENT_OPEN:
p_port->rfc.state = RFC_STATE_ORIG_WAIT_SEC_CHECK;
- if (rfcomm_security_records.count(scn) == 0) {
- rfc_sec_check_complete(nullptr, BT_TRANSPORT_BR_EDR, p_port,
- BTM_NO_RESOURCES);
- return;
- }
btm_sec_mx_access_request(p_port->rfc.p_mcb->bd_addr, true,
- rfcomm_security_records[scn],
- &rfc_sec_check_complete, p_port);
+ p_port->sec_mask, &rfc_sec_check_complete,
+ p_port);
return;
case RFC_PORT_EVENT_CLOSE:
@@ -153,14 +147,9 @@
/* Open will be continued after security checks are passed */
p_port->rfc.state = RFC_STATE_TERM_WAIT_SEC_CHECK;
- if (rfcomm_security_records.count(scn) == 0) {
- rfc_sec_check_complete(nullptr, BT_TRANSPORT_BR_EDR, p_port,
- BTM_NO_RESOURCES);
- return;
- }
btm_sec_mx_access_request(p_port->rfc.p_mcb->bd_addr, true,
- rfcomm_security_records[scn],
- &rfc_sec_check_complete, p_port);
+ p_port->sec_mask, &rfc_sec_check_complete,
+ p_port);
return;
case RFC_PORT_EVENT_UA:
diff --git a/system/stack/rfcomm/rfc_port_if.cc b/system/stack/rfcomm/rfc_port_if.cc
index 300d848..5ef820e 100644
--- a/system/stack/rfcomm/rfc_port_if.cc
+++ b/system/stack/rfcomm/rfc_port_if.cc
@@ -33,7 +33,6 @@
#include "stack/rfcomm/rfc_int.h"
tRFC_CB rfc_cb;
-std::unordered_map<uint32_t, uint16_t> rfcomm_security_records;
std::unordered_map<uint16_t /* sci */, tRFC_MCB*> rfc_lcid_mcb;
/*******************************************************************************
diff --git a/system/stack/test/rfcomm/stack_rfcomm_test.cc b/system/stack/test/rfcomm/stack_rfcomm_test.cc
index 8501674..f0812ce 100644
--- a/system/stack/test/rfcomm/stack_rfcomm_test.cc
+++ b/system/stack/test/rfcomm/stack_rfcomm_test.cc
@@ -135,8 +135,9 @@
tPORT_CALLBACK* event_callback,
uint16_t* server_handle) {
VLOG(1) << "Step 1";
- ASSERT_EQ(RFCOMM_CreateConnection(uuid, scn, true, mtu, RawAddress::kAny,
- server_handle, management_callback),
+ ASSERT_EQ(RFCOMM_CreateConnectionWithSecurity(
+ uuid, scn, true, mtu, RawAddress::kAny, server_handle,
+ management_callback, 0),
PORT_SUCCESS);
ASSERT_EQ(PORT_SetEventMask(*server_handle, PORT_EV_RXCHAR), PORT_SUCCESS);
ASSERT_EQ(PORT_SetEventCallback(*server_handle, event_callback),
@@ -280,8 +281,9 @@
DataWrite(lcid, BtHdrEqual(uih_pn_channel_3)))
.WillOnce(Return(L2CAP_DW_SUCCESS));
}
- ASSERT_EQ(RFCOMM_CreateConnection(uuid, scn, false, mtu, peer_bd_addr,
- client_handle, management_callback),
+ ASSERT_EQ(RFCOMM_CreateConnectionWithSecurity(uuid, scn, false, mtu,
+ peer_bd_addr, client_handle,
+ management_callback, 0),
PORT_SUCCESS);
ASSERT_EQ(PORT_SetEventMask(*client_handle, PORT_EV_RXCHAR), PORT_SUCCESS);
ASSERT_EQ(PORT_SetEventCallback(*client_handle, event_callback),
@@ -724,9 +726,9 @@
uint16_t server_handle = 0;
VLOG(1) << "Step 1";
// Prepare a server port
- int status = RFCOMM_CreateConnection(test_uuid, test_server_scn, true,
- test_mtu, RawAddress::kAny,
- &server_handle, port_mgmt_cback_0);
+ int status = RFCOMM_CreateConnectionWithSecurity(
+ test_uuid, test_server_scn, true, test_mtu, RawAddress::kAny,
+ &server_handle, port_mgmt_cback_0, 0);
ASSERT_EQ(status, PORT_SUCCESS);
status = PORT_SetEventMask(server_handle, PORT_EV_RXCHAR);
ASSERT_EQ(status, PORT_SUCCESS);
@@ -739,9 +741,9 @@
EXPECT_CALL(l2cap_interface_, ConnectRequest(BT_PSM_RFCOMM, test_address))
.Times(1)
.WillOnce(Return(old_lcid));
- status = RFCOMM_CreateConnection(test_uuid, test_peer_scn, false, test_mtu,
- test_address, &client_handle_1,
- port_mgmt_cback_1);
+ status = RFCOMM_CreateConnectionWithSecurity(
+ test_uuid, test_peer_scn, false, test_mtu, test_address, &client_handle_1,
+ port_mgmt_cback_1, 0);
ASSERT_EQ(status, PORT_SUCCESS);
status = PORT_SetEventMask(client_handle_1, PORT_EV_RXCHAR);
ASSERT_EQ(status, PORT_SUCCESS);
diff --git a/system/test/mock/mock_stack_rfcomm_port_api.cc b/system/test/mock/mock_stack_rfcomm_port_api.cc
index ba070c4..ddc169a 100644
--- a/system/test/mock/mock_stack_rfcomm_port_api.cc
+++ b/system/test/mock/mock_stack_rfcomm_port_api.cc
@@ -98,12 +98,6 @@
mock_function_count_map[__func__]++;
return 0;
}
-int RFCOMM_CreateConnection(uint16_t uuid, uint8_t scn, bool is_server,
- uint16_t mtu, const RawAddress& bd_addr,
- uint16_t* p_handle, tPORT_CALLBACK* p_mgmt_cb) {
- mock_function_count_map[__func__]++;
- return 0;
-}
int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn,
bool is_server, uint16_t mtu,
const RawAddress& bd_addr,
@@ -125,7 +119,8 @@
mock_function_count_map[__func__]++;
return 0;
}
-void RFCOMM_ClearSecurityRecord(uint32_t scn) {
+int PORT_GetSecurityMask(uint16_t handle, uint16_t* sec_mask) {
mock_function_count_map[__func__]++;
+ return 0;
}
void RFCOMM_Init(void) { mock_function_count_map[__func__]++; }