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

Commit a59b27de authored by Aritra Sen's avatar Aritra Sen
Browse files

Correct SCN allocation within bounds. Ensure Allocate SCN returns a value in...

Correct SCN allocation within bounds. Ensure Allocate SCN returns a value in [1, PORT_MAX_RFC_PORTS) or 0 if no port available.

Bug: 276240658
Test: atest BtmAllocateSCNTest
Tag: #stability
Change-Id: I1c6327a769aac57f1f9175b1d99e7bb99832d3d2
parent 53c2254a
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -125,10 +125,10 @@ cc_library_static {
        "bnep/bnep_api.cc",
        "bnep/bnep_main.cc",
        "bnep/bnep_utils.cc",
        "btm/hfp_msbc_decoder.cc",
        "btm/hfp_msbc_encoder.cc",
        "btm/hfp_lc3_decoder.cc",
        "btm/hfp_lc3_encoder.cc",
        "btm/hfp_msbc_decoder.cc",
        "btm/hfp_msbc_encoder.cc",
        "hid/hidd_api.cc",
        "hid/hidd_conn.cc",
        "hid/hidh_api.cc",
@@ -1417,16 +1417,17 @@ cc_test {
        "btm/btm_sco_hci.cc",
        "btm/btm_sco_hfp_hal.cc",
        "btm/btm_sec.cc",
        "btm/hfp_msbc_decoder.cc",
        "btm/hfp_msbc_encoder.cc",
        "btm/hfp_lc3_decoder.cc",
        "btm/hfp_lc3_encoder.cc",
        "btm/hfp_msbc_decoder.cc",
        "btm/hfp_msbc_encoder.cc",
        "metrics/stack_metrics_logging.cc",
        "test/btm/btm_scn_test.cc",
        "test/btm/peer_packet_types_test.cc",
        "test/btm/sco_hci_test.cc",
        "test/btm/sco_pkt_status_test.cc",
        "test/btm/stack_btm_regression_tests.cc",
        "test/btm/stack_btm_test.cc",
        "test/btm/sco_pkt_status_test.cc",
        "test/common/mock_eatt.cc",
        "test/stack_include_test.cc",
    ],
+10 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@
#ifndef BTM_INT_TYPES_H
#define BTM_INT_TYPES_H

#include <gtest/gtest_prod.h>

#include <cstdint>
#include <memory>
#include <string>
@@ -396,6 +398,14 @@ typedef struct tBTM_CB {
  friend bool BTM_FreeSCN(uint8_t scn);
  uint8_t btm_scn[BTM_MAX_SCN_];
  uint8_t btm_available_index;

  // give access to private method for test:
  friend class BtmAllocateSCNTest;
  FRIEND_TEST(BtmAllocateSCNTest, can_allocate_all_scns);
  FRIEND_TEST(BtmAllocateSCNTest, only_last_scn_available);
  FRIEND_TEST(BtmAllocateSCNTest, scn_available_after_available_index);
  FRIEND_TEST(BtmAllocateSCNTest, scn_available_before_available_index);
  FRIEND_TEST(BtmAllocateSCNTest, no_scn_available);
} tBTM_CB;

/* security action for L2CAP COC channels */
+8 −5
Original line number Diff line number Diff line
@@ -34,8 +34,11 @@ extern tBTM_CB btm_cb;
uint8_t BTM_AllocateSCN(void) {
  BTM_TRACE_DEBUG("BTM_AllocateSCN");

  // stack reserves scn 1 for HFP, HSP we still do the correct way
  for (uint8_t x = btm_cb.btm_available_index; x < PORT_MAX_RFC_PORTS; x++) {
  // stack reserves scn 1 for HFP, HSP we still do the correct way.
  // SCN can be allocated in the range of [1, PORT_MAX_RFC_PORTS). Since (x + 1)
  // is returned, we iterate to less than PORT_MAX_RFC_PORTS - 1.
  for (uint8_t x = btm_cb.btm_available_index; x < PORT_MAX_RFC_PORTS - 1;
       x++) {
    if (!btm_cb.btm_scn[x]) {
      btm_cb.btm_scn[x] = true;
      btm_cb.btm_available_index = (x + 1);
@@ -43,10 +46,10 @@ uint8_t BTM_AllocateSCN(void) {
    }
  }

  // In order to avoid OOB, btm_available_index must be less than or equal to
  // PORT_MAX_RFC_PORTS
  // In order to avoid OOB, btm_available_index must be less than
  // PORT_MAX_RFC_PORTS.
  btm_cb.btm_available_index =
      std::min(btm_cb.btm_available_index, (uint8_t)PORT_MAX_RFC_PORTS);
      std::min(btm_cb.btm_available_index, (uint8_t)(PORT_MAX_RFC_PORTS - 1));

  // If there's no empty SCN from _last_index to BTM_MAX_SCN.
  for (uint8_t y = 1; y < btm_cb.btm_available_index; y++) {
+1 −1
Original line number Diff line number Diff line
@@ -18,6 +18,6 @@

#include <cstdint>

uint8_t BTM_AllocateSCN(void);
bool BTM_FreeSCN(uint8_t scn);
bool BTM_TryAllocateSCN(uint8_t scn);
bool BTM_TryAllocateSCN(uint8_t scn);
+91 −0
Original line number Diff line number Diff line
/*
 *
 *  Copyright 2023 The Android Open Source Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

#include "stack/btm/btm_scn.h"

#include <gtest/gtest.h>

#include "stack/btm/btm_int_types.h"  // tBTM_CB
#include "stack/include/rfcdefs.h"    // PORT_MAX_RFC_PORTS

extern tBTM_CB btm_cb;

using testing::Test;

class BtmAllocateSCNTest : public Test {
 public:
 protected:
  void SetUp() override {
    btm_cb.btm_available_index = 1;
    for (int i = 0; i < PORT_MAX_RFC_PORTS; i++) {
      btm_cb.btm_scn[i] = false;
    }
  }

  void TearDown() override {}
};

TEST_F(BtmAllocateSCNTest, scn_available_after_available_index) {
  btm_cb.btm_available_index = 5;
  uint8_t occupied_idx[] = {1, 2, 3, 4, 5, 6, 7};
  for (uint8_t idx : occupied_idx) {
    btm_cb.btm_scn[idx] = true;
  }

  uint8_t scn = BTM_AllocateSCN();
  ASSERT_EQ(scn, 9);  // All indexes up to 7 are occupied; hence index 8 i.e.
                      // scn 9 should return
}

TEST_F(BtmAllocateSCNTest, scn_available_before_available_index) {
  btm_cb.btm_available_index = 28;
  uint8_t occupied_idx[] = {26, 27, 28, 29};
  for (uint8_t idx : occupied_idx) {
    btm_cb.btm_scn[idx] = true;
  }

  uint8_t scn = BTM_AllocateSCN();
  ASSERT_EQ(scn, 2);  // All SCN from available to 30 are occupied; hence cycle
                      // to beginning.
}

TEST_F(BtmAllocateSCNTest, can_allocate_all_scns) {
  for (uint8_t scn = 2; scn < PORT_MAX_RFC_PORTS; scn++) {
    EXPECT_EQ(BTM_AllocateSCN(), scn);
  }
}

TEST_F(BtmAllocateSCNTest, only_last_scn_available) {
  // Fill all relevants SCN except the last
  for (uint8_t scn = 2; scn < PORT_MAX_RFC_PORTS - 1; scn++) {
    btm_cb.btm_scn[scn - 1] = true;
  }

  EXPECT_EQ(BTM_AllocateSCN(), PORT_MAX_RFC_PORTS - 1);
}

TEST_F(BtmAllocateSCNTest, no_scn_available) {
  btm_cb.btm_available_index = 2;
  for (int i = 1; i < PORT_MAX_RFC_PORTS - 1;
       i++) {  // Fill all relevants SCN indexes (1 to 29)
    btm_cb.btm_scn[i] = true;
  }

  uint8_t scn = BTM_AllocateSCN();
  EXPECT_EQ(scn, 0) << "scn = " << scn << "and not 0";
}
 No newline at end of file