Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 173824aa authored by Henri Chataing's avatar Henri Chataing Committed by Automerger Merge Worker
Browse files

Merge "RootCanal: Correctly handle HCI commands with invalid bd_addr or handle" am: 7475688f

parents 30df998b 7475688f
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -19,10 +19,14 @@ pub struct LinkManagerOps {
}
}


impl LinkManagerOps {
impl LinkManagerOps {
    pub(crate) fn get_address(&self, handle: u16) -> hci::Address {
    pub(crate) fn get_address(&self, handle: u16) -> Option<hci::Address> {
        let mut result = hci::EMPTY_ADDRESS;
        let mut result = hci::EMPTY_ADDRESS;
        unsafe { (self.get_address)(self.user_pointer, handle, &mut result.bytes as *mut _) };
        unsafe { (self.get_address)(self.user_pointer, handle, &mut result.bytes as *mut _) };
        result
        if result == hci::EMPTY_ADDRESS {
            None
        } else {
            Some(result)
        }
    }
    }


    pub(crate) fn get_handle(&self, addr: hci::Address) -> u16 {
    pub(crate) fn get_handle(&self, addr: hci::Address) -> u16 {
+143 −10
Original line number Original line Diff line number Diff line
@@ -117,19 +117,152 @@ impl LinkManager {
        Ok(())
        Ok(())
    }
    }


    /// Send a command complete or command status event
    /// with the specified error code.
    fn send_command_complete_event(
        &self,
        command: &hci::CommandPacket,
        status: hci::ErrorCode,
    ) -> Result<(), LinkManagerError> {
        use hci::ConnectionManagementCommandChild::*;
        use hci::SecurityCommandChild::*;
        #[allow(unused_imports)]
        use Option::None; // Overwrite `None` variant of `Child` enum

        let event: hci::EventPacket = match command.specialize() {
            hci::CommandChild::SecurityCommand(command) => match command.specialize() {
                LinkKeyRequestReply(packet) => hci::LinkKeyRequestReplyCompleteBuilder {
                    status,
                    bd_addr: packet.get_bd_addr(),
                    num_hci_command_packets,
                }
                .into(),
                LinkKeyRequestNegativeReply(packet) => {
                    hci::LinkKeyRequestNegativeReplyCompleteBuilder {
                        status,
                        bd_addr: packet.get_bd_addr(),
                        num_hci_command_packets,
                    }
                    .into()
                }
                PinCodeRequestReply(packet) => hci::PinCodeRequestReplyCompleteBuilder {
                    status,
                    bd_addr: packet.get_bd_addr(),
                    num_hci_command_packets,
                }
                .into(),
                PinCodeRequestNegativeReply(packet) => {
                    hci::PinCodeRequestNegativeReplyCompleteBuilder {
                        status,
                        bd_addr: packet.get_bd_addr(),
                        num_hci_command_packets,
                    }
                    .into()
                }
                IoCapabilityRequestReply(packet) => hci::IoCapabilityRequestReplyCompleteBuilder {
                    status,
                    bd_addr: packet.get_bd_addr(),
                    num_hci_command_packets,
                }
                .into(),
                IoCapabilityRequestNegativeReply(packet) => {
                    hci::IoCapabilityRequestNegativeReplyCompleteBuilder {
                        status,
                        bd_addr: packet.get_bd_addr(),
                        num_hci_command_packets,
                    }
                    .into()
                }
                UserConfirmationRequestReply(packet) => {
                    hci::UserConfirmationRequestReplyCompleteBuilder {
                        status,
                        bd_addr: packet.get_bd_addr(),
                        num_hci_command_packets,
                    }
                    .into()
                }
                UserConfirmationRequestNegativeReply(packet) => {
                    hci::UserConfirmationRequestNegativeReplyCompleteBuilder {
                        status,
                        bd_addr: packet.get_bd_addr(),
                        num_hci_command_packets,
                    }
                    .into()
                }
                UserPasskeyRequestReply(packet) => hci::UserPasskeyRequestReplyCompleteBuilder {
                    status,
                    bd_addr: packet.get_bd_addr(),
                    num_hci_command_packets,
                }
                .into(),
                UserPasskeyRequestNegativeReply(packet) => {
                    hci::UserPasskeyRequestNegativeReplyCompleteBuilder {
                        status,
                        bd_addr: packet.get_bd_addr(),
                        num_hci_command_packets,
                    }
                    .into()
                }
                RemoteOobDataRequestReply(packet) => {
                    hci::RemoteOobDataRequestReplyCompleteBuilder {
                        status,
                        bd_addr: packet.get_bd_addr(),
                        num_hci_command_packets,
                    }
                    .into()
                }
                RemoteOobDataRequestNegativeReply(packet) => {
                    hci::RemoteOobDataRequestNegativeReplyCompleteBuilder {
                        status,
                        bd_addr: packet.get_bd_addr(),
                        num_hci_command_packets,
                    }
                    .into()
                }
                SendKeypressNotification(packet) => hci::SendKeypressNotificationCompleteBuilder {
                    status,
                    bd_addr: packet.get_bd_addr(),
                    num_hci_command_packets,
                }
                .into(),
                _ => return Err(LinkManagerError::UnhandledHciPacket),
            },
            hci::CommandChild::AclCommand(command) => match command.specialize() {
                hci::AclCommandChild::ConnectionManagementCommand(command) => {
                    match command.specialize() {
                        AuthenticationRequested(_) => hci::AuthenticationRequestedStatusBuilder {
                            status,
                            num_hci_command_packets,
                        }
                        .into(),
                        SetConnectionEncryption(_) => hci::SetConnectionEncryptionStatusBuilder {
                            status,
                            num_hci_command_packets,
                        }
                        .into(),
                        _ => return Err(LinkManagerError::UnhandledHciPacket),
                    }
                }
                _ => return Err(LinkManagerError::UnhandledHciPacket),
            },
            _ => return Err(LinkManagerError::UnhandledHciPacket),
        };
        self.ops.send_hci_event(&event.to_vec());
        Ok(())
    }

    pub fn ingest_hci(&self, command: hci::CommandPacket) -> Result<(), LinkManagerError> {
    pub fn ingest_hci(&self, command: hci::CommandPacket) -> Result<(), LinkManagerError> {
        // Try to find the peer address from the command arguments
        // Try to find the matching link from the command arguments
        let peer = hci::command_connection_handle(&command)
        let link = hci::command_connection_handle(&command)
            .map(|handle| self.ops.get_address(handle))
            .and_then(|handle| self.ops.get_address(handle))
            .or_else(|| hci::command_remote_device_address(&command));
            .or_else(|| hci::command_remote_device_address(&command))
            .and_then(|peer| self.get_link(peer));


        if let Some(peer) = peer {
        if let Some(link) = link {
            if let Some(link) = self.get_link(peer) {
            link.ingest_hci(command);
            link.ingest_hci(command);
            };
            Ok(())
            Ok(())
        } else {
        } else {
            Err(LinkManagerError::UnhandledHciPacket)
            self.send_command_complete_event(&command, hci::ErrorCode::InvalidHciCommandParameters)
        }
        }
    }
    }


+6 −0
Original line number Original line Diff line number Diff line
@@ -200,6 +200,12 @@ AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const {
  return acl_connections_.at(handle).GetAddress();
  return acl_connections_.at(handle).GetAddress();
}
}


std::optional<AddressWithType> AclConnectionHandler::GetAddressSafe(
    uint16_t handle) const {
  return HasHandle(handle) ? acl_connections_.at(handle).GetAddress()
                           : std::optional<AddressWithType>();
}

Address AclConnectionHandler::GetScoAddress(uint16_t handle) const {
Address AclConnectionHandler::GetScoAddress(uint16_t handle) const {
  ASSERT_LOG(HasScoHandle(handle), "Unknown SCO handle %hd", handle);
  ASSERT_LOG(HasScoHandle(handle), "Unknown SCO handle %hd", handle);
  return sco_connections_.at(handle).GetAddress();
  return sco_connections_.at(handle).GetAddress();
+1 −0
Original line number Original line Diff line number Diff line
@@ -85,6 +85,7 @@ class AclConnectionHandler {
  uint16_t GetHandle(bluetooth::hci::AddressWithType addr) const;
  uint16_t GetHandle(bluetooth::hci::AddressWithType addr) const;
  uint16_t GetHandleOnlyAddress(bluetooth::hci::Address addr) const;
  uint16_t GetHandleOnlyAddress(bluetooth::hci::Address addr) const;
  bluetooth::hci::AddressWithType GetAddress(uint16_t handle) const;
  bluetooth::hci::AddressWithType GetAddress(uint16_t handle) const;
  std::optional<AddressWithType> GetAddressSafe(uint16_t handle) const;
  bluetooth::hci::Address GetScoAddress(uint16_t handle) const;
  bluetooth::hci::Address GetScoAddress(uint16_t handle) const;
  bluetooth::hci::AddressWithType GetOwnAddress(uint16_t handle) const;
  bluetooth::hci::AddressWithType GetOwnAddress(uint16_t handle) const;
  bluetooth::hci::AddressWithType GetResolvedAddress(uint16_t handle) const;
  bluetooth::hci::AddressWithType GetResolvedAddress(uint16_t handle) const;
+4 −2
Original line number Original line Diff line number Diff line
@@ -1365,8 +1365,10 @@ LinkLayerController::LinkLayerController(const Address& address,
          [](void* user, uint16_t handle, uint8_t(*result)[6]) {
          [](void* user, uint16_t handle, uint8_t(*result)[6]) {
            auto controller = static_cast<LinkLayerController*>(user);
            auto controller = static_cast<LinkLayerController*>(user);


            auto address =
            auto address_opt = controller->connections_.GetAddressSafe(handle);
                controller->connections_.GetAddress(handle).GetAddress();
            Address address = address_opt.has_value()
                                  ? address_opt.value().GetAddress()
                                  : Address::kEmpty;
            std::copy(address.data(), address.data() + 6,
            std::copy(address.data(), address.data() + 6,
                      reinterpret_cast<uint8_t*>(result));
                      reinterpret_cast<uint8_t*>(result));
          },
          },