Index: sys/netgraph/bluetooth/hci/ng_hci_main.c =================================================================== --- sys/netgraph/bluetooth/hci/ng_hci_main.c +++ sys/netgraph/bluetooth/hci/ng_hci_main.c @@ -781,6 +781,43 @@ return (error); } /* ng_hci_drv_rcvdata */ +static int +ng_hci_validate_acl_data(ng_hci_unit_p unit, struct mbuf *m, u_int16_t *con_handle) +{ + int size; + NG_HCI_BUFF_ACL_SIZE(unit->buffer, size); + + if (m->m_pkthdr.len < sizeof(ng_hci_acldata_pkt_t) || + m->m_pkthdr.len > sizeof(ng_hci_acldata_pkt_t) + size) { + NG_HCI_ALERT( +"%s: %s - invalid HCI ACL data packet, len=%d, mtu=%d\n", + __func__, NG_NODE_NAME(unit->node), + m->m_pkthdr.len, size); + + return (EMSGSIZE); + } + + NG_HCI_M_PULLUP(m, sizeof(ng_hci_acldata_pkt_t)); + if (m == NULL) { + return (ENOBUFS); + } + + *con_handle = NG_HCI_CON_HANDLE(le16toh( + mtod(m, ng_hci_acldata_pkt_t *)->con_handle)); + size = le16toh(mtod(m, ng_hci_acldata_pkt_t *)->length); + + if (m->m_pkthdr.len != sizeof(ng_hci_acldata_pkt_t) + size) { + NG_HCI_ALERT( +"%s: %s - invalid HCI ACL data packet size, len=%d, length=%d\n", + __func__, NG_NODE_NAME(unit->node), + m->m_pkthdr.len, size); + + return (EMSGSIZE); + } + + return (0); +} /* ng_hci_validate_acl_data */ + /* * Process data packet from ACL upstream hook. * We expect valid HCI ACL data packets. @@ -793,9 +830,8 @@ struct mbuf *m = NULL; ng_hci_unit_con_p con = NULL; u_int16_t con_handle; - int size, error = 0; + int error = 0; - NG_HCI_BUFF_ACL_SIZE(unit->buffer, size); /* Check packet */ NGI_GET_M(item, m); @@ -808,34 +844,9 @@ error = EINVAL; goto drop; } - if (m->m_pkthdr.len < sizeof(ng_hci_acldata_pkt_t) || - m->m_pkthdr.len > sizeof(ng_hci_acldata_pkt_t) + size) { - NG_HCI_ALERT( -"%s: %s - invalid HCI ACL data packet, len=%d, mtu=%d\n", - __func__, NG_NODE_NAME(unit->node), - m->m_pkthdr.len, size); - error = EMSGSIZE; - goto drop; - } - - NG_HCI_M_PULLUP(m, sizeof(ng_hci_acldata_pkt_t)); - if (m == NULL) { - error = ENOBUFS; - goto drop; - } - - con_handle = NG_HCI_CON_HANDLE(le16toh( - mtod(m, ng_hci_acldata_pkt_t *)->con_handle)); - size = le16toh(mtod(m, ng_hci_acldata_pkt_t *)->length); - - if (m->m_pkthdr.len != sizeof(ng_hci_acldata_pkt_t) + size) { - NG_HCI_ALERT( -"%s: %s - invalid HCI ACL data packet size, len=%d, length=%d\n", - __func__, NG_NODE_NAME(unit->node), - m->m_pkthdr.len, size); - - error = EMSGSIZE; + error = ng_hci_validate_acl_data(unit, m, &con_handle); + if (error != 0) { goto drop; } @@ -903,6 +914,43 @@ * We expect valid HCI SCO data packets */ +static int +ng_hci_validate_sco_data(ng_hci_unit_p unit, struct mbuf *m, u_int16_t *con_handle) +{ + int size; + NG_HCI_BUFF_SCO_SIZE(unit->buffer, size); + + if (m->m_pkthdr.len < sizeof(ng_hci_scodata_pkt_t) || + m->m_pkthdr.len > sizeof(ng_hci_scodata_pkt_t) + size) { + NG_HCI_ALERT( +"%s: %s - invalid HCI SCO data packet, len=%d, mtu=%d\n", + __func__, NG_NODE_NAME(unit->node), + m->m_pkthdr.len, size); + + return (EMSGSIZE); + } + + NG_HCI_M_PULLUP(m, sizeof(ng_hci_scodata_pkt_t)); + if (m == NULL) { + return (ENOBUFS); + } + + *con_handle = NG_HCI_CON_HANDLE(le16toh( + mtod(m, ng_hci_scodata_pkt_t *)->con_handle)); + size = mtod(m, ng_hci_scodata_pkt_t *)->length; + + if (m->m_pkthdr.len != sizeof(ng_hci_scodata_pkt_t) + size) { + NG_HCI_ALERT( +"%s: %s - invalid HCI SCO data packet size, len=%d, length=%d\n", + __func__, NG_NODE_NAME(unit->node), + m->m_pkthdr.len, size); + + return (EMSGSIZE); + } + + return (0); +} /* ng_hci_validate_sco_data */ + static int ng_hci_sco_rcvdata(hook_p hook, item_p item) { @@ -910,9 +958,7 @@ struct mbuf *m = NULL; ng_hci_unit_con_p con = NULL; u_int16_t con_handle; - int size, error = 0; - - NG_HCI_BUFF_SCO_SIZE(unit->buffer, size); + int error = 0; /* Check packet */ NGI_GET_M(item, m); @@ -927,34 +973,8 @@ goto drop; } - if (m->m_pkthdr.len < sizeof(ng_hci_scodata_pkt_t) || - m->m_pkthdr.len > sizeof(ng_hci_scodata_pkt_t) + size) { - NG_HCI_ALERT( -"%s: %s - invalid HCI SCO data packet, len=%d, mtu=%d\n", - __func__, NG_NODE_NAME(unit->node), - m->m_pkthdr.len, size); - - error = EMSGSIZE; - goto drop; - } - - NG_HCI_M_PULLUP(m, sizeof(ng_hci_scodata_pkt_t)); - if (m == NULL) { - error = ENOBUFS; - goto drop; - } - - con_handle = NG_HCI_CON_HANDLE(le16toh( - mtod(m, ng_hci_scodata_pkt_t *)->con_handle)); - size = mtod(m, ng_hci_scodata_pkt_t *)->length; - - if (m->m_pkthdr.len != sizeof(ng_hci_scodata_pkt_t) + size) { - NG_HCI_ALERT( -"%s: %s - invalid HCI SCO data packet size, len=%d, length=%d\n", - __func__, NG_NODE_NAME(unit->node), - m->m_pkthdr.len, size); - - error = EMSGSIZE; + error = ng_hci_validate_sco_data(unit, m, &con_handle); + if (error != 0) { goto drop; } @@ -1017,6 +1037,43 @@ return (error); } /* ng_hci_sco_rcvdata */ +static int +ng_hci_validate_command(ng_hci_unit_p unit, struct mbuf *m) +{ + if (m->m_pkthdr.len < sizeof(ng_hci_cmd_pkt_t)) { + NG_HCI_ALERT( +"%s: %s - invalid HCI command packet len=%d\n", + __func__, NG_NODE_NAME(unit->node), m->m_pkthdr.len); + + return (EMSGSIZE); + } + + NG_HCI_M_PULLUP(m, sizeof(ng_hci_cmd_pkt_t)); + if (m == NULL) { + return (ENOBUFS); + } + + if (m->m_pkthdr.len != + mtod(m, ng_hci_cmd_pkt_t *)->length + sizeof(ng_hci_cmd_pkt_t)) { + NG_HCI_ALERT( +"%s: %s - invalid HCI command packet size, len=%d, length=%d\n", + __func__, NG_NODE_NAME(unit->node), m->m_pkthdr.len, + mtod(m, ng_hci_cmd_pkt_t *)->length); + + return (EMSGSIZE); + } + + if (mtod(m, ng_hci_cmd_pkt_t *)->opcode == 0) { + NG_HCI_ALERT( +"%s: %s - invalid HCI command opcode\n", + __func__, NG_NODE_NAME(unit->node)); + + return (EINVAL); + } + + return (0); +} /* ng_hci_validate_command */ + /* * Process data packet from uptream RAW hook. * We expect valid HCI command packets. @@ -1028,59 +1085,40 @@ ng_hci_unit_p unit = (ng_hci_unit_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); struct mbuf *m = NULL; int error = 0; + u_int16_t con_handle; NGI_GET_M(item, m); NG_FREE_ITEM(item); + /* Check packet */ - if (*mtod(m, u_int8_t *) != NG_HCI_CMD_PKT) { + switch (*mtod(m, u_int8_t *)) { + case NG_HCI_CMD_PKT: + error = ng_hci_validate_command(unit, m); + break; + case NG_HCI_ACL_DATA_PKT: + error = ng_hci_validate_acl_data(unit, m, &con_handle); + break; + case NG_HCI_SCO_DATA_PKT: + error = ng_hci_validate_sco_data(unit, m, &con_handle); + break; + default: NG_HCI_ALERT( -"%s: %s - invalid HCI command packet type=%#x\n", +"%s: %s - got unexpected HCI packet type=%#x\n", __func__, NG_NODE_NAME(unit->node), *mtod(m, u_int8_t *)); error = EINVAL; - goto drop; + break; } - if (m->m_pkthdr.len < sizeof(ng_hci_cmd_pkt_t)) { - NG_HCI_ALERT( -"%s: %s - invalid HCI command packet len=%d\n", - __func__, NG_NODE_NAME(unit->node), m->m_pkthdr.len); - - error = EMSGSIZE; - goto drop; - } - - NG_HCI_M_PULLUP(m, sizeof(ng_hci_cmd_pkt_t)); - if (m == NULL) { - error = ENOBUFS; - goto drop; - } - - if (m->m_pkthdr.len != - mtod(m, ng_hci_cmd_pkt_t *)->length + sizeof(ng_hci_cmd_pkt_t)) { - NG_HCI_ALERT( -"%s: %s - invalid HCI command packet size, len=%d, length=%d\n", - __func__, NG_NODE_NAME(unit->node), m->m_pkthdr.len, - mtod(m, ng_hci_cmd_pkt_t *)->length); - - error = EMSGSIZE; - goto drop; - } - - if (mtod(m, ng_hci_cmd_pkt_t *)->opcode == 0) { - NG_HCI_ALERT( -"%s: %s - invalid HCI command opcode\n", - __func__, NG_NODE_NAME(unit->node)); - - error = EINVAL; + if (error != 0) { goto drop; } if (NG_BT_MBUFQ_FULL(&unit->cmdq)) { NG_HCI_ALERT( -"%s: %s - dropping HCI command packet, len=%d, queue_len=%d\n", +"%s: %s - dropping HCI packet, len=%d, queue_len=%d\n", __func__, NG_NODE_NAME(unit->node), m->m_pkthdr.len, NG_BT_MBUFQ_LEN(&unit->cmdq)); Index: sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c =================================================================== --- sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c +++ sys/netgraph/bluetooth/socket/ng_btsocket_hci_raw.c @@ -698,8 +698,7 @@ case NG_HCI_ACL_DATA_PKT: case NG_HCI_SCO_DATA_PKT: if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) || - !bit_test(pcb->filter.packet_mask, type - 1) || - !d) + (!bit_test(pcb->filter.packet_mask, type - 1) && !d)) return (EPERM); break; @@ -1580,6 +1579,7 @@ ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so); struct mbuf *nam = NULL; int error = 0; + u_int8_t pkt_typ = 0xff; if (ng_btsocket_hci_raw_node == NULL) { error = ENETDOWN; @@ -1606,7 +1606,10 @@ goto drop; } } - if (*mtod(m, u_int8_t *) != NG_HCI_CMD_PKT) { + pkt_typ = *mtod(m, u_int8_t *); + if (pkt_typ != NG_HCI_CMD_PKT && + pkt_typ != NG_HCI_ACL_DATA_PKT && + pkt_typ != NG_HCI_SCO_DATA_PKT) { error = ENOTSUP; goto drop; }