[compiler-rt] 682d635 - tsan: add kBrokenAliasedMetas condition and test
Thurston Dang via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 11 10:24:00 PST 2023
Author: Thurston Dang
Date: 2023-01-11T18:15:04Z
New Revision: 682d635aa508860c306deae23766ca5e2575583a
URL: https://github.com/llvm/llvm-project/commit/682d635aa508860c306deae23766ca5e2575583a
DIFF: https://github.com/llvm/llvm-project/commit/682d635aa508860c306deae23766ca5e2575583a.diff
LOG: tsan: add kBrokenAliasedMetas condition and test
This fills in a gap in the tsan_shadow_test coverage:
it is possible that the meta regions are aliased
(e.g., the heap meta region overlaps the high app meta
region). Indeed, the Aarch64_39 mapping has been
silently broken in this way for quite some time.
This CL checks whether the individual meta regions
(for low/mid/high/heap) overlap. Note that
(!kBrokenAliasedMetas && !kBrokenLinearity) implies
that MemToMeta is invertible; we cannot directly
test MetaToMem because that function does not exist.
Differential Revision: https://reviews.llvm.org/D141445
Added:
Modified:
compiler-rt/lib/tsan/rtl/tsan_platform.h
compiler-rt/lib/tsan/tests/unit/tsan_shadow_test.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h
index 2d9cc883855c7..6527a885135b5 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h
@@ -34,6 +34,14 @@ enum {
// This is bad and can lead to unpredictable memory corruptions, etc
// because range access functions assume linearity.
kBrokenLinearity = 1 << 2,
+ // Meta for an app region overlaps with the meta of another app region.
+ // This is determined by recomputing the individual meta regions for
+ // each app region.
+ //
+ // N.B. There is no "kBrokenReverseMetaMapping" constant because there
+ // is no MetaToMem function. However, note that (!kBrokenLinearity
+ // && !kBrokenAliasedMetas) implies that MemToMeta is invertible.
+ kBrokenAliasedMetas = 1 << 3,
};
/*
@@ -159,6 +167,7 @@ C/C++ on linux/aarch64 (39-bit VMA)
7d00 0000 00 - 7fff ffff ff: modules and main thread stack
*/
struct MappingAarch64_39 {
+ static const uptr kBroken = kBrokenAliasedMetas;
static const uptr kLoAppMemBeg = 0x0000001000ull;
static const uptr kLoAppMemEnd = 0x0100000000ull;
static const uptr kShadowBeg = 0x0400000000ull;
@@ -191,7 +200,7 @@ C/C++ on linux/aarch64 (42-bit VMA)
3f000 0000 00 - 3ffff ffff ff: modules and main thread stack
*/
struct MappingAarch64_42 {
- static const uptr kBroken = kBrokenReverseMapping;
+ static const uptr kBroken = kBrokenReverseMapping | kBrokenAliasedMetas;
static const uptr kLoAppMemBeg = 0x00000001000ull;
static const uptr kLoAppMemEnd = 0x01000000000ull;
static const uptr kShadowBeg = 0x08000000000ull;
@@ -274,8 +283,8 @@ C/C++ on linux/powerpc64 (44-bit VMA)
0f60 0000 0000 - 1000 0000 0000: modules and main thread stack
*/
struct MappingPPC64_44 {
- static const uptr kBroken =
- kBrokenMapping | kBrokenReverseMapping | kBrokenLinearity;
+ static const uptr kBroken = kBrokenMapping | kBrokenReverseMapping |
+ kBrokenLinearity | kBrokenAliasedMetas;
static const uptr kMetaShadowBeg = 0x0b0000000000ull;
static const uptr kMetaShadowEnd = 0x0d0000000000ull;
static const uptr kShadowBeg = 0x000100000000ull;
@@ -286,6 +295,7 @@ struct MappingPPC64_44 {
static const uptr kHeapMemEnd = 0x0f5000000000ull;
static const uptr kHiAppMemBeg = 0x0f6000000000ull;
static const uptr kHiAppMemEnd = 0x100000000000ull; // 44 bits
+
static const uptr kShadowMsk = 0x0f0000000000ull;
static const uptr kShadowXor = 0x002100000000ull;
static const uptr kShadowAdd = 0x000000000000ull;
diff --git a/compiler-rt/lib/tsan/tests/unit/tsan_shadow_test.cpp b/compiler-rt/lib/tsan/tests/unit/tsan_shadow_test.cpp
index ba49df7deda3c..78398acc253a6 100644
--- a/compiler-rt/lib/tsan/tests/unit/tsan_shadow_test.cpp
+++ b/compiler-rt/lib/tsan/tests/unit/tsan_shadow_test.cpp
@@ -15,6 +15,11 @@
namespace __tsan {
+struct Region {
+ uptr start;
+ uptr end;
+};
+
void CheckShadow(const Shadow *s, Sid sid, Epoch epoch, uptr addr, uptr size,
AccessType typ) {
uptr addr1 = 0;
@@ -126,6 +131,30 @@ bool broken(uptr what, typename Has<Mapping::kBroken>::Result = false) {
return Mapping::kBroken & what;
}
+static int CompareRegion(const void *region_a, const void *region_b) {
+ uptr start_a = ((struct Region *)region_a)->start;
+ uptr start_b = ((struct Region *)region_b)->start;
+
+ if (start_a < start_b) {
+ return -1;
+ } else if (start_a > start_b) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+template <typename Mapping>
+static void AddMetaRegion(struct Region *shadows, int *num_regions, uptr start,
+ uptr end) {
+ // If the app region is not empty, add its meta to the array.
+ if (start != end) {
+ shadows[*num_regions].start = (uptr)MemToMetaImpl::Apply<Mapping>(start);
+ shadows[*num_regions].end = (uptr)MemToMetaImpl::Apply<Mapping>(end - 1);
+ *num_regions = (*num_regions) + 1;
+ }
+}
+
struct MappingTest {
template <typename Mapping>
static void Apply() {
@@ -135,6 +164,11 @@ struct MappingTest {
TestRegion<Mapping>(Mapping::kMidAppMemBeg, Mapping::kMidAppMemEnd);
TestRegion<Mapping>(Mapping::kHiAppMemBeg, Mapping::kHiAppMemEnd);
TestRegion<Mapping>(Mapping::kHeapMemBeg, Mapping::kHeapMemEnd);
+
+ TestDisjointMetas<Mapping>();
+
+ // Not tested: the ordering of regions (low app vs. shadow vs. mid app
+ // etc.). That is enforced at runtime by CheckAndProtect.
}
template <typename Mapping>
@@ -172,6 +206,41 @@ struct MappingTest {
}
}
}
+
+ template <typename Mapping>
+ static void TestDisjointMetas() {
+ // Checks that the meta for each app region does not overlap with
+ // the meta for other app regions. For example, the meta for a high
+ // app pointer shouldn't be aliased to the meta of a mid app pointer.
+ // Notice that this is important even though there does not exist a
+ // MetaToMem function.
+ // (If a MetaToMem function did exist, we could simply
+ // check in the TestRegion function that it inverts MemToMeta.)
+ //
+ // We don't try to be clever by allowing the non-PIE (low app)
+ // and PIE (mid and high app) meta regions to overlap.
+ struct Region metas[4];
+ int num_regions = 0;
+ AddMetaRegion<Mapping>(metas, &num_regions, Mapping::kLoAppMemBeg,
+ Mapping::kLoAppMemEnd);
+ AddMetaRegion<Mapping>(metas, &num_regions, Mapping::kMidAppMemBeg,
+ Mapping::kMidAppMemEnd);
+ AddMetaRegion<Mapping>(metas, &num_regions, Mapping::kHiAppMemBeg,
+ Mapping::kHiAppMemEnd);
+ AddMetaRegion<Mapping>(metas, &num_regions, Mapping::kHeapMemBeg,
+ Mapping::kHeapMemEnd);
+
+ // It is not required that the low app shadow is below the mid app
+ // shadow etc., hence we sort the shadows.
+ qsort(metas, num_regions, sizeof(struct Region), CompareRegion);
+
+ for (int i = 0; i < num_regions; i++)
+ Printf("[0x%lu, 0x%lu]\n", metas[i].start, metas[i].end);
+
+ if (!broken<Mapping>(kBrokenAliasedMetas))
+ for (int i = 1; i < num_regions; i++)
+ CHECK(metas[i - 1].end <= metas[i].start);
+ }
};
TEST(Shadow, AllMappings) { ForEachMapping<MappingTest>(); }
More information about the llvm-commits
mailing list