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

Commit ce0f3201 authored by Sim Sun's avatar Sim Sun Committed by Christopher Ferris
Browse files

Fix dangling pointer issue in LocalUpdatbleMaps

Libunwindstack would remove duplicated items and update the `prev_map`
during reparsing `/proc/self/maps`. But we leave `prev_real_map`
pointing toward a MapInfo that will be deleted soon. It will cause a
dangling pointer issue.

Add new tests to cover this dangling pointer issue.

Bug: 155511785

Test: libunwindstack_test
Change-Id: I62e1b97bcb73f07e9349671f0b758f5ec9de16c0
(cherry picked from commit a7a194be)
parent 0b4313fe
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -159,6 +159,8 @@ bool LocalUpdatableMaps::Reparse() {
        search_map_idx = old_map_idx + 1;
        if (new_map_idx + 1 < maps_.size()) {
          maps_[new_map_idx + 1]->prev_map = info.get();
          maps_[new_map_idx + 1]->prev_real_map =
              info->IsBlank() ? info->prev_real_map : info.get();
        }
        maps_[new_map_idx] = nullptr;
        total_entries--;
+99 −0
Original line number Diff line number Diff line
@@ -271,4 +271,103 @@ TEST_F(LocalUpdatableMapsTest, all_new_maps) {
  EXPECT_TRUE(map_info->name.empty());
}

TEST_F(LocalUpdatableMapsTest, add_map_prev_name_updated) {
  TemporaryFile tf;
  ASSERT_TRUE(
      android::base::WriteStringToFile("3000-4000 rwxp 00000 00:00 0\n"
                                       "8000-9000 r-xp 00000 00:00 0\n"
                                       "9000-a000 r-xp 00000 00:00 0\n",
                                       tf.path));

  maps_.TestSetMapsFile(tf.path);
  ASSERT_TRUE(maps_.Reparse());
  ASSERT_EQ(3U, maps_.Total());

  MapInfo* map_info = maps_.Get(2);
  ASSERT_TRUE(map_info != nullptr);
  EXPECT_EQ(0x9000U, map_info->start);
  EXPECT_EQ(0xA000U, map_info->end);
  EXPECT_EQ(0U, map_info->offset);
  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
  EXPECT_TRUE(map_info->name.empty());
  EXPECT_EQ(maps_.Get(1), map_info->prev_map);
}

TEST_F(LocalUpdatableMapsTest, add_map_prev_real_name_updated) {
  TemporaryFile tf;
  ASSERT_TRUE(
      android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
                                       "4000-5000 ---p 00000 00:00 0\n"
                                       "7000-8000 r-xp 00000 00:00 0 /fake/lib1.so\n"
                                       "8000-9000 ---p 00000 00:00 0\n",
                                       tf.path));

  maps_.TestSetMapsFile(tf.path);
  ASSERT_TRUE(maps_.Reparse());
  ASSERT_EQ(4U, maps_.Total());

  MapInfo* map_info = maps_.Get(2);
  ASSERT_TRUE(map_info != nullptr);
  EXPECT_EQ(0x7000U, map_info->start);
  EXPECT_EQ(0x8000U, map_info->end);
  EXPECT_EQ(0U, map_info->offset);
  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
  EXPECT_EQ(maps_.Get(0), map_info->prev_real_map);
  EXPECT_EQ(maps_.Get(1), map_info->prev_map);
  EXPECT_EQ("/fake/lib1.so", map_info->name);

  map_info = maps_.Get(3);
  ASSERT_TRUE(map_info != nullptr);
  EXPECT_EQ(0x8000U, map_info->start);
  EXPECT_EQ(0x9000U, map_info->end);
  EXPECT_EQ(0U, map_info->offset);
  EXPECT_TRUE(map_info->IsBlank());
  EXPECT_EQ(maps_.Get(2), map_info->prev_real_map);
  EXPECT_EQ(maps_.Get(2), map_info->prev_map);
  EXPECT_TRUE(map_info->name.empty());

  ASSERT_TRUE(
      android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
                                       "4000-5000 ---p 00000 00:00 0\n"
                                       "7000-8000 r-xp 00000 00:00 0 /fake/lib1.so\n"
                                       "8000-9000 ---p 00000 00:00 0\n"
                                       "9000-a000 r-xp 00000 00:00 0 /fake/lib2.so\n"
                                       "a000-b000 r-xp 00000 00:00 0 /fake/lib3.so\n",
                                       tf.path));

  maps_.TestSetMapsFile(tf.path);
  ASSERT_TRUE(maps_.Reparse());
  ASSERT_EQ(6U, maps_.Total());

  map_info = maps_.Get(2);
  ASSERT_TRUE(map_info != nullptr);
  EXPECT_EQ(0x7000U, map_info->start);
  EXPECT_EQ(0x8000U, map_info->end);
  EXPECT_EQ(0U, map_info->offset);
  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
  EXPECT_EQ("/fake/lib1.so", map_info->name);
  EXPECT_EQ(maps_.Get(1), map_info->prev_map);
  EXPECT_EQ(maps_.Get(0), map_info->prev_real_map);

  map_info = maps_.Get(4);
  ASSERT_TRUE(map_info != nullptr);
  EXPECT_EQ(0x9000U, map_info->start);
  EXPECT_EQ(0xA000U, map_info->end);
  EXPECT_EQ(0U, map_info->offset);
  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
  EXPECT_EQ("/fake/lib2.so", map_info->name);
  EXPECT_EQ(maps_.Get(3), map_info->prev_map);
  EXPECT_EQ(maps_.Get(2), map_info->prev_real_map);

  map_info = maps_.Get(5);
  ASSERT_TRUE(map_info != nullptr);
  EXPECT_EQ(0xA000U, map_info->start);
  EXPECT_EQ(0xB000U, map_info->end);
  EXPECT_EQ(0U, map_info->offset);
  EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags);
  EXPECT_EQ("/fake/lib3.so", map_info->name);
  EXPECT_EQ(maps_.Get(4), map_info->prev_map);
  EXPECT_EQ(maps_.Get(4), map_info->prev_real_map);
}

}  // namespace unwindstack