Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: syzygy/agent/asan/heap_managers/block_heap_manager_unittest.cc

Issue 2383793003: [SyzyAsan] More careful handling when freeing corrupt blocks. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « syzygy/agent/asan/heap_managers/block_heap_manager.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 Google Inc. All Rights Reserved. 1 // Copyright 2014 Google Inc. All Rights Reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 private: 207 private:
208 DISALLOW_COPY_AND_ASSIGN(TestZebraBlockHeap); 208 DISALLOW_COPY_AND_ASSIGN(TestZebraBlockHeap);
209 }; 209 };
210 210
211 // A derived class to expose protected members for unit-testing. 211 // A derived class to expose protected members for unit-testing.
212 class TestBlockHeapManager : public BlockHeapManager { 212 class TestBlockHeapManager : public BlockHeapManager {
213 public: 213 public:
214 using BlockHeapManager::HeapQuarantinePair; 214 using BlockHeapManager::HeapQuarantinePair;
215 215
216 using BlockHeapManager::FreePotentiallyCorruptBlock; 216 using BlockHeapManager::FreePotentiallyCorruptBlock;
217 using BlockHeapManager::GetCorruptBlockHeapId;
217 using BlockHeapManager::GetHeapId; 218 using BlockHeapManager::GetHeapId;
218 using BlockHeapManager::GetHeapFromId; 219 using BlockHeapManager::GetHeapFromId;
219 using BlockHeapManager::GetHeapTypeUnlocked; 220 using BlockHeapManager::GetHeapTypeUnlocked;
220 using BlockHeapManager::GetQuarantineFromId; 221 using BlockHeapManager::GetQuarantineFromId;
221 using BlockHeapManager::HeapMetadata; 222 using BlockHeapManager::HeapMetadata;
222 using BlockHeapManager::HeapQuarantineMap; 223 using BlockHeapManager::HeapQuarantineMap;
223 using BlockHeapManager::IsValidHeapIdUnlocked; 224 using BlockHeapManager::IsValidHeapIdUnlocked;
224 using BlockHeapManager::SetHeapErrorCallback; 225 using BlockHeapManager::SetHeapErrorCallback;
225 using BlockHeapManager::ShardedBlockQuarantine; 226 using BlockHeapManager::ShardedBlockQuarantine;
226 using BlockHeapManager::TrimQuarantine; 227 using BlockHeapManager::TrimQuarantine;
227 228
228 using BlockHeapManager::allocation_filter_flag_tls_; 229 using BlockHeapManager::allocation_filter_flag_tls_;
230 using BlockHeapManager::corrupt_block_registry_cache_;
231 using BlockHeapManager::enable_page_protections_;
229 using BlockHeapManager::heaps_; 232 using BlockHeapManager::heaps_;
230 using BlockHeapManager::large_block_heap_id_; 233 using BlockHeapManager::large_block_heap_id_;
231 using BlockHeapManager::locked_heaps_; 234 using BlockHeapManager::locked_heaps_;
232 using BlockHeapManager::parameters_; 235 using BlockHeapManager::parameters_;
236 using BlockHeapManager::shadow_;
233 using BlockHeapManager::shared_quarantine_; 237 using BlockHeapManager::shared_quarantine_;
234 using BlockHeapManager::zebra_block_heap_; 238 using BlockHeapManager::zebra_block_heap_;
235 using BlockHeapManager::zebra_block_heap_id_; 239 using BlockHeapManager::zebra_block_heap_id_;
236 240
237 // A derived class to expose protected members for unit-testing. This has to 241 // A derived class to expose protected members for unit-testing. This has to
238 // be nested into this one because ShardedBlockQuarantine accesses some 242 // be nested into this one because ShardedBlockQuarantine accesses some
239 // protected fields of BlockHeapManager. 243 // protected fields of BlockHeapManager.
240 // 244 //
241 // This class should only expose some members or expose new functions, no new 245 // This class should only expose some members or expose new functions, no new
242 // member should be added. 246 // member should be added.
(...skipping 1511 matching lines...) Expand 10 before | Expand all | Expand 10 after
1754 current_size = heap_manager_->shared_quarantine_.GetSizeForTesting(); 1758 current_size = heap_manager_->shared_quarantine_.GetSizeForTesting();
1755 EXPECT_EQ(GREEN, 1759 EXPECT_EQ(GREEN,
1756 heap_manager_->shared_quarantine_.GetQuarantineColor(current_size)); 1760 heap_manager_->shared_quarantine_.GetQuarantineColor(current_size));
1757 1761
1758 heap_manager_->DisableDeferredFreeThread(); 1762 heap_manager_->DisableDeferredFreeThread();
1759 EXPECT_FALSE(heap_manager_->IsDeferredFreeThreadRunning()); 1763 EXPECT_FALSE(heap_manager_->IsDeferredFreeThreadRunning());
1760 } 1764 }
1761 1765
1762 namespace { 1766 namespace {
1763 1767
1764 bool ShadowIsConsistentPostAlloc( 1768 // Helper function for extracting the two default heaps.
1765 Shadow* shadow, const void* alloc, size_t size) { 1769 void GetHeapIds(TestBlockHeapManager* heap_manager,
1766 uintptr_t index = reinterpret_cast<uintptr_t>(alloc); 1770 HeapId* large_block_heap,
1767 index >>= kShadowRatioLog; 1771 HeapId* win_heap) {
1768 uintptr_t index_end = index + (size >> kShadowRatioLog); 1772 ASSERT_TRUE(heap_manager);
1769 for (size_t i = index; i < index_end; ++i) { 1773 ASSERT_TRUE(large_block_heap);
1770 if (shadow->shadow()[i] != ShadowMarker::kHeapAddressableMarker) 1774 ASSERT_TRUE(win_heap);
1771 return false; 1775 ASSERT_EQ(2u, heap_manager->heaps_.size());
1772 }
1773 return true;
1774 }
1775 1776
1776 bool ShadowIsConsistentPostFree( 1777 *large_block_heap = 0;
1777 Shadow* shadow, const void* alloc, size_t size) { 1778 *win_heap = 0;
1778 DCHECK_NE(static_cast<Shadow*>(nullptr), shadow);
1779 uintptr_t index = reinterpret_cast<uintptr_t>(alloc);
1780 index >>= kShadowRatioLog;
1781 uintptr_t index_end = index + (size >> kShadowRatioLog);
1782 1779
1783 uint8_t m = shadow->shadow()[index]; 1780 for (auto h = heap_manager->heaps_.begin();
1784 if (m != ShadowMarker::kHeapAddressableMarker && 1781 h != heap_manager->heaps_.end(); ++h) {
1785 m != ShadowMarker::kAsanReservedMarker && 1782 HeapId heap_id = heap_manager->GetHeapId(h);
1786 m != ShadowMarker::kHeapFreedMarker) { 1783 if (h->first->GetHeapType() == kWinHeap) {
1787 return false; 1784 *win_heap = heap_id;
1785 } else {
1786 ASSERT_EQ(kLargeBlockHeap, h->first->GetHeapType());
1787 *large_block_heap = heap_id;
1788 }
1788 } 1789 }
1789 1790
1790 // We expect green memory only for large allocations which are directly 1791 ASSERT_NE(0u, *large_block_heap);
1791 // mapped. Small allocations should be returned to a common pool and 1792 ASSERT_NE(0u, *win_heap);
1792 // marked as reserved.CtMalloc heap.
1793 if (m == ShadowMarker::kHeapAddressableMarker && size < 1 * 1024 * 1024)
1794 return false;
1795
1796 for (size_t i = index; i < index_end; ++i) {
1797 if (shadow->shadow()[index] != m)
1798 return false;
1799 }
1800 return true;
1801 } 1793 }
1802 1794
1803 class BlockHeapManagerIntegrationTest : public testing::Test {
1804 public:
1805 BlockHeapManagerIntegrationTest()
1806 : shadow_() {
1807 }
1808
1809 void SetUp() override {
1810 shadow_.SetUp();
1811 ASSERT_TRUE(shadow_.IsClean());
1812 }
1813
1814 void TearDown() override {
1815 ASSERT_TRUE(shadow_.IsClean());
1816 shadow_.TearDown();
1817 }
1818
1819 testing::DebugShadow shadow_;
1820 };
1821
1822 } // namespace 1795 } // namespace
1823 1796
1797 TEST_F(BlockHeapManagerTest, GetCorruptBlockHeapIdTrailerIsGood) {
1798 // Disable page protections so that the LBH allocated block can be
1799 // accessed.
1800 heap_manager_->enable_page_protections_ = false;
1801
1802 HeapId lbh = 0;
1803 HeapId wh = 0;
1804 GetHeapIds(heap_manager_, &lbh, &wh);
1805
1806 // Create a second win heap. This means that there are multiple heaps
1807 // not supporting IsAllocated.
1808 heap_manager_->CreateHeap();
1809
1810 void* alloc = heap_manager_->Allocate(lbh, 64 * 4096);
1811 BlockInfo bi = {};
1812 GetBlockInfo(
1813 heap_manager_->shadow_, reinterpret_cast<BlockBody*>(alloc), &bi);
1814
1815 // Test that the heap ID is correctly returned even in one of many
1816 // non-reporting heaps, given that the correct heap id is actually in the
1817 // trailer.
1818 EXPECT_EQ(lbh, heap_manager_->GetCorruptBlockHeapId(&bi));
1819 }
1820
1821 TEST_F(BlockHeapManagerTest, GetCorruptBlockHeapIdInReportingHeap) {
1822 // Disable page protections so that the LBH allocated block can be
1823 // accessed.
1824 heap_manager_->enable_page_protections_ = false;
1825
1826 HeapId lbh = 0;
1827 HeapId wh = 0;
1828 GetHeapIds(heap_manager_, &lbh, &wh);
1829
1830 // Create a second win heap. This means that there are multiple heaps
1831 // not supporting IsAllocated.
1832 heap_manager_->CreateHeap();
1833
1834 void* alloc = heap_manager_->Allocate(lbh, 32);
1835 BlockInfo bi = {};
1836 GetBlockInfo(
1837 heap_manager_->shadow_, reinterpret_cast<BlockBody*>(alloc), &bi);
1838 bi.trailer->heap_id = 0;
1839
1840 // Test the the correct heap is found, even though there are multiple
1841 // non-reporting heaps and the trailer is corrupt.
1842 EXPECT_EQ(lbh, heap_manager_->GetCorruptBlockHeapId(&bi));
1843 }
1844
1845 TEST_F(BlockHeapManagerTest, GetCorruptBlockHeapIdInSingleNonReportingHeap) {
1846 HeapId lbh = 0;
1847 HeapId wh = 0;
1848 GetHeapIds(heap_manager_, &lbh, &wh);
1849
1850 void* alloc = heap_manager_->Allocate(wh, 32);
1851 BlockInfo bi = {};
1852 GetBlockInfo(
1853 heap_manager_->shadow_, reinterpret_cast<BlockBody*>(alloc), &bi);
1854 bi.trailer->heap_id = 0;
1855
1856 // Test the the correct heap is found, even though its a non-reporting heap
1857 // and the trailer is corrupt.
1858 EXPECT_EQ(wh, heap_manager_->GetCorruptBlockHeapId(&bi));
1859 }
1860
1861 TEST_F(BlockHeapManagerTest, GetCorruptBlockHeapIdNotFound) {
1862 HeapId lbh = 0;
1863 HeapId wh = 0;
1864 GetHeapIds(heap_manager_, &lbh, &wh);
1865
1866 // Create a second win heap. This means that there are multiple heaps
1867 // not supporting IsAllocated.
1868 heap_manager_->CreateHeap();
1869
1870 void* alloc = heap_manager_->Allocate(wh, 32);
1871 BlockInfo bi = {};
1872 GetBlockInfo(
1873 heap_manager_->shadow_, reinterpret_cast<BlockBody*>(alloc), &bi);
1874 bi.trailer->heap_id = 0;
1875
1876 // Expect this to fail, as there are multiple non-reporting heaps and
1877 // the block trailer is corrupt.
1878 EXPECT_EQ(0u, heap_manager_->GetCorruptBlockHeapId(&bi));
1879 }
1880
1881 TEST_F(BlockHeapManagerTest, FreeCorruptedBlockWorks) {
1882 // Enable to registry filter.
1883 heap_manager_->parameters_.prevent_duplicate_corruption_crashes = true;
1884
1885 HeapId lbh = 0;
1886 HeapId wh = 0;
1887 GetHeapIds(heap_manager_, &lbh, &wh);
1888
1889 void* alloc = heap_manager_->Allocate(wh, 32);
1890 BlockInfo bi = {};
1891 GetBlockInfo(
1892 heap_manager_->shadow_, reinterpret_cast<BlockBody*>(alloc), &bi);
1893
1894 // Add the stack ID to the registry cache, so that it will decide not
1895 // to crash upon freeing.
1896 heap_manager_->corrupt_block_registry_cache_->AddOrUpdateStackId(
1897 bi.header->alloc_stack->relative_stack_id());
1898
1899 // Clear the heap ID and delete the block, expecting this to succeed.
1900 bi.trailer->heap_id = 0;
1901 EXPECT_TRUE(heap_manager_->Free(wh, alloc));
1902 }
1903
1824 } // namespace heap_managers 1904 } // namespace heap_managers
1825 } // namespace asan 1905 } // namespace asan
1826 } // namespace agent 1906 } // namespace agent
OLDNEW
« no previous file with comments | « syzygy/agent/asan/heap_managers/block_heap_manager.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698