Skip to content

Commit 6b46ea3

Browse files
committed
Bluetooth: controller: Fix access to members of packed structs
Fix all instances in the controller of -Waddress-of-packed-member by casting through an intermediate variable and verifying the alignment with an assertion. Signed-off-by: Carles Cufi <[email protected]> Signed-off-by: Vinayak Kariappa Chettimada <[email protected]>
1 parent 944a02d commit 6b46ea3

File tree

4 files changed

+108
-16
lines changed

4 files changed

+108
-16
lines changed

subsys/bluetooth/controller/hci/hci.c

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3728,16 +3728,23 @@ static void le_cis_request(struct pdu_data *pdu_data,
37283728
{
37293729
struct bt_hci_evt_le_cis_req *sep;
37303730
struct node_rx_conn_iso_req *req;
3731+
void *node;
37313732

37323733
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
37333734
!(le_event_mask & BT_EVT_MASK_LE_CIS_REQ)) {
37343735
return;
37353736
}
37363737

3737-
req = (void *)pdu_data;
3738-
37393738
sep = meta_evt(buf, BT_HCI_EVT_LE_CIS_REQ, sizeof(*sep));
37403739
sep->acl_handle = sys_cpu_to_le16(node_rx->hdr.handle);
3740+
3741+
/* Check for pdu field being aligned before accessing CIS established
3742+
* event.
3743+
*/
3744+
node = pdu_data;
3745+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_conn_iso_estab));
3746+
3747+
req = node;
37413748
sep->cis_handle = sys_cpu_to_le16(req->cis_handle);
37423749
sep->cig_id = req->cig_id;
37433750
sep->cis_id = req->cis_id;
@@ -3757,6 +3764,7 @@ static void le_cis_established(struct pdu_data *pdu_data,
37573764
struct ll_conn_iso_stream *cis;
37583765
struct ll_conn_iso_group *cig;
37593766
bool is_central;
3767+
void *node;
37603768

37613769
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
37623770
!(le_event_mask & BT_EVT_MASK_LE_CIS_ESTABLISHED)) {
@@ -3769,10 +3777,16 @@ static void le_cis_established(struct pdu_data *pdu_data,
37693777
is_central = cig->lll.role == BT_CONN_ROLE_CENTRAL;
37703778
lll_cis_c = is_central ? &lll_cis->tx : &lll_cis->rx;
37713779
lll_cis_p = is_central ? &lll_cis->rx : &lll_cis->tx;
3772-
est = (void *)pdu_data;
37733780

37743781
sep = meta_evt(buf, BT_HCI_EVT_LE_CIS_ESTABLISHED, sizeof(*sep));
37753782

3783+
/* Check for pdu field being aligned before accessing CIS established
3784+
* event.
3785+
*/
3786+
node = pdu_data;
3787+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_conn_iso_estab));
3788+
3789+
est = node;
37763790
sep->status = est->status;
37773791
sep->conn_handle = sys_cpu_to_le16(est->cis_handle);
37783792
sys_put_le24(cig->sync_delay, sep->cig_sync_delay);
@@ -6063,6 +6077,7 @@ static void le_per_adv_sync_established(struct pdu_data *pdu_data,
60636077
struct bt_hci_evt_le_per_adv_sync_established *sep;
60646078
struct ll_scan_set *scan;
60656079
struct node_rx_sync *se;
6080+
void *node;
60666081

60676082
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
60686083
!(le_event_mask & BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED)) {
@@ -6072,7 +6087,13 @@ static void le_per_adv_sync_established(struct pdu_data *pdu_data,
60726087
sep = meta_evt(buf, BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED,
60736088
sizeof(*sep));
60746089

6075-
se = (void *)pdu_data;
6090+
/* Check for pdu field being aligned before accessing sync established
6091+
* event.
6092+
*/
6093+
node = pdu_data;
6094+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_sync));
6095+
6096+
se = node;
60766097
sep->status = se->status;
60776098

60786099
if (se->status == BT_HCI_ERR_OP_CANCELLED_BY_HOST) {
@@ -6403,6 +6424,7 @@ static void le_big_sync_established(struct pdu_data *pdu,
64036424
struct node_rx_sync_iso *se;
64046425
struct lll_sync_iso *lll;
64056426
size_t evt_size;
6427+
void *node;
64066428

64076429
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
64086430
!(le_event_mask & BT_EVT_MASK_LE_BIG_SYNC_ESTABLISHED)) {
@@ -6417,7 +6439,13 @@ static void le_big_sync_established(struct pdu_data *pdu,
64176439
sep = meta_evt(buf, BT_HCI_EVT_LE_BIG_SYNC_ESTABLISHED, evt_size);
64186440
sep->big_handle = sys_cpu_to_le16(node_rx->hdr.handle);
64196441

6420-
se = (void *)pdu;
6442+
/* Check for pdu field being aligned before accessing ISO sync
6443+
* established event.
6444+
*/
6445+
node = pdu;
6446+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_sync_iso));
6447+
6448+
se = node;
64216449
sep->status = se->status;
64226450
if (sep->status) {
64236451
return;
@@ -6612,9 +6640,19 @@ static void le_scan_req_received(struct pdu_data *pdu_data,
66126640
static void le_conn_complete(struct pdu_data *pdu_data, uint16_t handle,
66136641
struct net_buf *buf)
66146642
{
6615-
struct node_rx_cc *cc = (void *)pdu_data;
66166643
struct bt_hci_evt_le_conn_complete *lecc;
6617-
uint8_t status = cc->status;
6644+
struct node_rx_cc *cc;
6645+
uint8_t status;
6646+
void *node;
6647+
6648+
/* Check for pdu field being aligned before accessing connection
6649+
* complete event.
6650+
*/
6651+
node = pdu_data;
6652+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_cc));
6653+
6654+
cc = node;
6655+
status = cc->status;
66186656

66196657
#if defined(CONFIG_BT_CTLR_PRIVACY)
66206658
if (!status) {
@@ -6731,6 +6769,7 @@ static void le_conn_update_complete(struct pdu_data *pdu_data, uint16_t handle,
67316769
{
67326770
struct bt_hci_evt_le_conn_update_complete *sep;
67336771
struct node_rx_cu *cu;
6772+
void *node;
67346773

67356774
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
67366775
!(le_event_mask & BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE)) {
@@ -6739,7 +6778,13 @@ static void le_conn_update_complete(struct pdu_data *pdu_data, uint16_t handle,
67396778

67406779
sep = meta_evt(buf, BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE, sizeof(*sep));
67416780

6742-
cu = (void *)pdu_data;
6781+
/* Check for pdu field being aligned before accessing connection
6782+
* update complete event.
6783+
*/
6784+
node = pdu_data;
6785+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_cu));
6786+
6787+
cu = node;
67436788
sep->status = cu->status;
67446789
sep->handle = sys_cpu_to_le16(handle);
67456790
sep->interval = sys_cpu_to_le16(cu->interval);

subsys/bluetooth/controller/ll_sw/ull_central.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,7 @@ void ull_central_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr,
807807
struct ll_conn *conn;
808808
memq_link_t *link;
809809
uint8_t chan_sel;
810+
void *node;
810811

811812
/* Get reference to Tx-ed CONNECT_IND PDU */
812813
pdu_tx = (void *)((struct node_rx_pdu *)rx)->pdu;
@@ -820,8 +821,14 @@ void ull_central_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr,
820821
/* This is the chan sel bit from the received adv pdu */
821822
chan_sel = pdu_tx->chan_sel;
822823

824+
/* Check for pdu field being aligned before populating connection
825+
* complete event.
826+
*/
827+
node = pdu_tx;
828+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_cc));
829+
823830
/* Populate the fields required for connection complete event */
824-
cc = (void *)pdu_tx;
831+
cc = node;
825832
cc->status = 0U;
826833
cc->role = 0U;
827834

subsys/bluetooth/controller/ll_sw/ull_conn.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2852,6 +2852,7 @@ static inline void event_conn_upd_init(struct ll_conn *conn,
28522852

28532853
{
28542854
uint32_t retval;
2855+
void *win_offs;
28552856

28562857
/* calculate window offset that places the connection in the
28572858
* next available slot after existing centrals.
@@ -2870,8 +2871,12 @@ static inline void event_conn_upd_init(struct ll_conn *conn,
28702871
}
28712872
#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
28722873

2873-
conn->llcp.conn_upd.pdu_win_offset = (uint16_t *)
2874-
&pdu_ctrl_tx->llctrl.conn_update_ind.win_offset;
2874+
win_offs = &pdu_ctrl_tx->llctrl.conn_update_ind.win_offset;
2875+
/* No need to check alignment here since the pointer that gets
2876+
* stored is never derreferenced directly, only passed
2877+
* to memcpy().
2878+
*/
2879+
conn->llcp.conn_upd.pdu_win_offset = win_offs;
28752880

28762881
mfy_sched_offset->fp = fp_mfy_select_or_use;
28772882
mfy_sched_offset->param = (void *)conn;
@@ -3737,6 +3742,7 @@ static inline void event_conn_param_req(struct ll_conn *conn,
37373742
static struct mayfly s_mfy_sched_offset = {0, 0, &s_link, NULL,
37383743
ull_sched_mfy_free_win_offset_calc};
37393744
uint32_t retval;
3745+
void *win_offs;
37403746

37413747
conn->llcp_conn_param.ticks_ref = ticks_at_expire;
37423748

@@ -3752,7 +3758,12 @@ static inline void event_conn_param_req(struct ll_conn *conn,
37523758
}
37533759
#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
37543760

3755-
conn->llcp_conn_param.pdu_win_offset0 = (uint16_t *)&p->offset0;
3761+
win_offs = &p->offset0;
3762+
/* No need to check alignment here since the pointer that gets
3763+
* stored is never derreferenced directly, only passed
3764+
* to memcpy().
3765+
*/
3766+
conn->llcp_conn_param.pdu_win_offset0 = win_offs;
37563767

37573768
s_mfy_sched_offset.param = (void *)conn;
37583769

@@ -5177,6 +5188,7 @@ static inline int reject_ind_conn_upd_recv(struct ll_conn *conn,
51775188
struct pdu_data_llctrl_reject_ext_ind *rej_ext_ind;
51785189
struct node_rx_cu *cu;
51795190
struct lll_conn *lll;
5191+
void *node;
51805192

51815193
/* Unsupported remote feature */
51825194
lll = &conn->lll;
@@ -5228,8 +5240,14 @@ static inline int reject_ind_conn_upd_recv(struct ll_conn *conn,
52285240
/* generate conn update complete event with error code */
52295241
rx->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
52305242

5243+
/* check for pdu field being aligned before populating
5244+
* connection update complete event.
5245+
*/
5246+
node = pdu_rx;
5247+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_cu));
5248+
52315249
/* prepare connection update complete structure */
5232-
cu = (void *)pdu_rx;
5250+
cu = node;
52335251
cu->status = rej_ext_ind->error_code;
52345252
cu->interval = lll->interval;
52355253
cu->latency = lll->latency;
@@ -6006,6 +6024,7 @@ static uint8_t cis_req_recv(struct ll_conn *conn, memq_link_t *link,
60066024
struct node_rx_conn_iso_req *conn_iso_req;
60076025
uint16_t cis_handle;
60086026
uint8_t err;
6027+
void *node;
60096028

60106029
conn->llcp_cis.cig_id = req->cig_id;
60116030
conn->llcp_cis.framed = req->framed;
@@ -6028,7 +6047,13 @@ static uint8_t cis_req_recv(struct ll_conn *conn, memq_link_t *link,
60286047

60296048
(*rx)->hdr.type = NODE_RX_TYPE_CIS_REQUEST;
60306049

6031-
conn_iso_req = (void *)pdu;
6050+
/* check for pdu field being aligned before populating ISO
6051+
* connection request event.
6052+
*/
6053+
node = pdu;
6054+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_conn_iso_req));
6055+
6056+
conn_iso_req = node;
60326057
conn_iso_req->cig_id = req->cig_id;
60336058
conn_iso_req->cis_id = req->cis_id;
60346059
conn_iso_req->cis_handle = sys_le16_to_cpu(cis_handle);
@@ -7014,6 +7039,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
70147039
PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ)) {
70157040
struct lll_conn *lll = &conn->lll;
70167041
struct node_rx_cu *cu;
7042+
void *node;
70177043

70187044
/* Mark CPR as unsupported */
70197045
conn->llcp_conn_param.disabled = 1U;
@@ -7061,8 +7087,14 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
70617087
/* generate conn upd complete event with error code */
70627088
(*rx)->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
70637089

7090+
/* check for pdu field being aligned before populating
7091+
* connection update complete event.
7092+
*/
7093+
node = pdu_rx;
7094+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_cu));
7095+
70647096
/* prepare connection update complete structure */
7065-
cu = (void *)pdu_rx;
7097+
cu = node;
70667098
cu->status = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
70677099
cu->interval = lll->interval;
70687100
cu->latency = lll->latency;

subsys/bluetooth/controller/ll_sw/ull_peripheral.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ void ull_periph_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr,
8989
memq_link_t *link;
9090
uint16_t timeout;
9191
uint8_t chan_sel;
92+
void *node;
9293

9394
adv = ((struct lll_adv *)ftr->param)->hdr.parent;
9495
conn = lll->hdr.parent;
@@ -232,7 +233,14 @@ void ull_periph_setup(struct node_rx_hdr *rx, struct node_rx_ftr *ftr,
232233
chan_sel = pdu_adv->chan_sel;
233234
}
234235

235-
cc = (void *)pdu_adv;
236+
/* Check for pdu field being aligned before populating connection
237+
* complete event.
238+
*/
239+
node = pdu_adv;
240+
LL_ASSERT(IS_PTR_ALIGNED(node, struct node_rx_cc));
241+
242+
/* Populate the fields required for connection complete event */
243+
cc = node;
236244
cc->status = 0U;
237245
cc->role = 1U;
238246

0 commit comments

Comments
 (0)