@@ -917,6 +917,8 @@ add_vm_area(vm_area_vector_t *v, app_pc start, app_pc end, uint vm_flags, uint f
917
917
void *data _IF_DEBUG(const char *comment))
918
918
{
919
919
int i, j, diff;
920
+ start = STRIP_MEMORY_TAG(start);
921
+ end = STRIP_MEMORY_TAG(end);
920
922
/* if we have overlap, we extend an existing area -- else we add a new area */
921
923
int overlap_start = -1, overlap_end = -1;
922
924
DEBUG_DECLARE(uint flagignore;)
@@ -1331,6 +1333,8 @@ remove_vm_area(vm_area_vector_t *v, app_pc start, app_pc end, bool restore_prot)
1331
1333
* custom.frags and not custom.client
1332
1334
*/
1333
1335
bool official_coarse_vector = (v == executable_areas);
1336
+ start = STRIP_MEMORY_TAG(start);
1337
+ end = STRIP_MEMORY_TAG(end);
1334
1338
1335
1339
ASSERT_VMAREA_VECTOR_PROTECTED(v, WRITE);
1336
1340
LOG(GLOBAL, LOG_VMAREAS, 4, "in remove_vm_area " PFX " " PFX "\n", start, end);
@@ -1503,6 +1507,8 @@ static bool
1503
1507
binary_search(vm_area_vector_t *v, app_pc start, app_pc end, vm_area_t **area /*OUT*/,
1504
1508
int *index /*OUT*/, bool first)
1505
1509
{
1510
+ start = STRIP_MEMORY_TAG(start);
1511
+ end = STRIP_MEMORY_TAG(end);
1506
1512
/* BINARY SEARCH -- assumes the vector is kept sorted by add & remove! */
1507
1513
int min = 0;
1508
1514
int max = v->length - 1;
@@ -1579,6 +1585,8 @@ lookup_addr(vm_area_vector_t *v, app_pc addr, vm_area_t **area)
1579
1585
static bool
1580
1586
vm_area_overlap(vm_area_vector_t *v, app_pc start, app_pc end)
1581
1587
{
1588
+ start = STRIP_MEMORY_TAG(start);
1589
+ end = STRIP_MEMORY_TAG(end);
1582
1590
/* binary search asserts v is protected */
1583
1591
return binary_search(v, start, end, NULL, NULL, false);
1584
1592
}
@@ -1936,6 +1944,9 @@ vmvector_add_replace(vm_area_vector_t *v, app_pc start, app_pc end, void *data)
1936
1944
void *old_data = NULL;
1937
1945
bool release_lock; /* 'true' means this routine needs to unlock */
1938
1946
1947
+ start = STRIP_MEMORY_TAG(start);
1948
+ end = STRIP_MEMORY_TAG(end);
1949
+
1939
1950
LOCK_VECTOR(v, release_lock, write);
1940
1951
ASSERT_OWN_WRITE_LOCK(SHOULD_LOCK_VECTOR(v), &v->lock);
1941
1952
overlap = lookup_addr(v, start, &area);
@@ -2098,6 +2109,8 @@ vmvector_modify_data(vm_area_vector_t *v, app_pc start, app_pc end, void *data)
2098
2109
bool overlap;
2099
2110
vm_area_t *area = NULL;
2100
2111
bool release_lock; /* 'true' means this routine needs to unlock */
2112
+ start = STRIP_MEMORY_TAG(start);
2113
+ end = STRIP_MEMORY_TAG(end);
2101
2114
2102
2115
LOCK_VECTOR(v, release_lock, write);
2103
2116
ASSERT_OWN_WRITE_LOCK(SHOULD_LOCK_VECTOR(v), &v->lock);
@@ -11658,6 +11671,164 @@ aslr_report_violation(app_pc execution_fault_pc, security_option_t handling_poli
11658
11671
#ifdef STANDALONE_UNIT_TEST
11659
11672
# define INT_TO_PC(x) ((app_pc)(ptr_uint_t)(x))
11660
11673
11674
+ # if defined(AARCH64)
11675
+ # define TAG_INT_TO_PC(tag, addr) \
11676
+ INT_TO_PC(((ptr_uint_t)tag) << 56 | ((ptr_uint_t)addr))
11677
+ # endif
11678
+
11679
+ /* Test vmvector behaviour with tagged pointers.
11680
+ * vmvector_tagged_pointer_tests() takes two pairs of app_pc values:
11681
+ * create_start, create_end are used to create an area,
11682
+ * lookup_start, lookup_end are used to look up the area after it has been created.
11683
+ * The *_start values should have the same address and the two *_end values should have
11684
+ * the same address but they can have different tag values.
11685
+ * We call vmvector_tagged_pointer_tests() several times with different combinations of
11686
+ * tagged and untagged pointers to test different scenarios (create tagged and lookup
11687
+ * untagged, create untagged and lookup tagged, etc).
11688
+ */
11689
+ void
11690
+ vmvector_tagged_pointer_tests(app_pc create_start, app_pc create_end, app_pc lookup_start,
11691
+ app_pc lookup_end)
11692
+ {
11693
+ /* Sanity check to make sure the test function is being used correctly. */
11694
+ EXPECT(STRIP_MEMORY_TAG(create_start), STRIP_MEMORY_TAG(lookup_start));
11695
+ EXPECT(STRIP_MEMORY_TAG(create_end), STRIP_MEMORY_TAG(lookup_end));
11696
+
11697
+ vm_area_vector_t v = { 0, 0, 0, VECTOR_SHARED | VECTOR_NEVER_MERGE,
11698
+ INIT_READWRITE_LOCK(thread_vm_areas) };
11699
+ uint data1 = 0;
11700
+ uint data2 = 0;
11701
+
11702
+ vmvector_add(&v, create_start, create_end, &data1);
11703
+
11704
+ {
11705
+ bool res = vmvector_overlap(&v, lookup_start, lookup_end);
11706
+ EXPECT(res, true);
11707
+ }
11708
+
11709
+ {
11710
+ void *returned_data = vmvector_add_replace(&v, lookup_start, lookup_end, &data2);
11711
+ EXPECT(returned_data, &data1);
11712
+ }
11713
+
11714
+ {
11715
+ void *returned_data = vmvector_lookup(&v, lookup_start);
11716
+ EXPECT(returned_data, &data2);
11717
+ }
11718
+
11719
+ {
11720
+ bool res = vmvector_overlap(&v, lookup_start, lookup_end);
11721
+ EXPECT(res, true);
11722
+ }
11723
+
11724
+ {
11725
+ app_pc start = NULL;
11726
+ app_pc end = NULL;
11727
+ void *returned_data = NULL;
11728
+
11729
+ bool res = vmvector_lookup_data(&v, lookup_start, &start, &end, &returned_data);
11730
+
11731
+ EXPECT(res, true);
11732
+ EXPECT(start, STRIP_MEMORY_TAG(create_start));
11733
+ EXPECT(end, STRIP_MEMORY_TAG(create_end));
11734
+ EXPECT(returned_data, &data2);
11735
+ }
11736
+
11737
+ {
11738
+ bool res = vmvector_modify_data(&v, lookup_start, lookup_end, &data1);
11739
+ EXPECT(res, true);
11740
+
11741
+ app_pc start = NULL;
11742
+ app_pc end = NULL;
11743
+ void *returned_data = NULL;
11744
+ res = vmvector_lookup_data(&v, lookup_start, &start, &end, &returned_data);
11745
+
11746
+ EXPECT(res, true);
11747
+ EXPECT(returned_data, &data1);
11748
+ }
11749
+
11750
+ {
11751
+ vmvector_iterator_t vmvi;
11752
+ vmvector_iterator_start(&v, &vmvi);
11753
+
11754
+ app_pc start = NULL;
11755
+ app_pc end = NULL;
11756
+ void *returned_data = vmvector_iterator_peek(&vmvi, &start, &end);
11757
+
11758
+ EXPECT(returned_data, &data1);
11759
+ EXPECT(start, STRIP_MEMORY_TAG(create_start));
11760
+ EXPECT(end, STRIP_MEMORY_TAG(create_end));
11761
+
11762
+ vmvector_iterator_stop(&vmvi);
11763
+ }
11764
+
11765
+ {
11766
+ vmvector_iterator_t vmvi;
11767
+ vmvector_iterator_start(&v, &vmvi);
11768
+
11769
+ app_pc start = NULL;
11770
+ app_pc end = NULL;
11771
+ void *returned_data = vmvector_iterator_next(&vmvi, &start, &end);
11772
+
11773
+ EXPECT(returned_data, &data1);
11774
+ EXPECT(start, STRIP_MEMORY_TAG(create_start));
11775
+ EXPECT(end, STRIP_MEMORY_TAG(create_end));
11776
+
11777
+ vmvector_iterator_stop(&vmvi);
11778
+ }
11779
+
11780
+ {
11781
+ bool res = vmvector_remove(&v, lookup_start, lookup_end);
11782
+ EXPECT(res, true);
11783
+
11784
+ res = vmvector_overlap(&v, create_start, create_end);
11785
+ EXPECT(res, false);
11786
+
11787
+ res = vmvector_overlap(&v, lookup_start, lookup_end);
11788
+ EXPECT(res, false);
11789
+ }
11790
+
11791
+ {
11792
+ vmvector_add(&v, create_start, create_end, &data1);
11793
+
11794
+ app_pc start = NULL;
11795
+ app_pc end = NULL;
11796
+ vmvector_remove_containing_area(&v, lookup_start, &start, &end);
11797
+ EXPECT(start, STRIP_MEMORY_TAG(create_start));
11798
+ EXPECT(end, STRIP_MEMORY_TAG(create_end));
11799
+ }
11800
+
11801
+ {
11802
+ # define ADD_PC(pc, increment) (app_pc)((ptr_uint_t)pc + increment)
11803
+ /* Create two regions with a gap between we can use to test
11804
+ * vmvector_lookup_prev_next()
11805
+ */
11806
+ vmvector_add(&v, create_start, create_end, &data1);
11807
+ vmvector_add(&v, ADD_PC(create_start, 0x200), ADD_PC(create_end, 0x200), &data1);
11808
+
11809
+ app_pc prev_start = NULL;
11810
+ app_pc prev_end = NULL;
11811
+ app_pc next_start = NULL;
11812
+ app_pc next_end = NULL;
11813
+ bool res = vmvector_lookup_prev_next(&v, ADD_PC(lookup_start, 0x101), &prev_start,
11814
+ &prev_end, &next_start, &next_end);
11815
+ EXPECT(res, true);
11816
+ EXPECT(prev_start, STRIP_MEMORY_TAG(create_start));
11817
+ EXPECT(prev_end, STRIP_MEMORY_TAG(create_end));
11818
+ EXPECT(next_start, STRIP_MEMORY_TAG(ADD_PC(create_start, 0x200)));
11819
+ EXPECT(next_end, STRIP_MEMORY_TAG(ADD_PC(create_end, 0x200)));
11820
+
11821
+ /* Fill the gap and lookup the address again. */
11822
+ vmvector_add(&v, ADD_PC(create_start, 0x100), ADD_PC(create_end, 0x100), &data1);
11823
+
11824
+ res = vmvector_lookup_prev_next(&v, ADD_PC(lookup_start, 0x101), &prev_start,
11825
+ &prev_end, &next_start, &next_end);
11826
+ EXPECT(res, false);
11827
+ }
11828
+
11829
+ DELETE_READWRITE_LOCK(v.lock);
11830
+ }
11831
+
11661
11832
static void
11662
11833
print_vector_msg(vm_area_vector_t *v, file_t f, const char *msg)
11663
11834
{
@@ -11715,6 +11886,27 @@ vmvector_tests()
11715
11886
vmvector_remove(&v, INT_TO_PC(0x20), INT_TO_PC(0x210)); /* truncation allowed? */
11716
11887
EXPECT(res, true);
11717
11888
vmvector_print(&v, STDERR);
11889
+
11890
+ DELETE_READWRITE_LOCK(v.lock);
11891
+
11892
+ # if defined(AARCH64)
11893
+ /* It is assumed that the untagged vs untagged case is covered by the tests above. */
11894
+ print_file(STDERR, "tagged pointers (untagged vs tagged)\n");
11895
+ vmvector_tagged_pointer_tests(INT_TO_PC(0x100), INT_TO_PC(0x1ff),
11896
+ TAG_INT_TO_PC(0x11, 0x100), TAG_INT_TO_PC(0x11, 0x1ff));
11897
+
11898
+ print_file(STDERR, "tagged pointers (tagged vs untagged)\n");
11899
+ vmvector_tagged_pointer_tests(TAG_INT_TO_PC(0x11, 0x100), TAG_INT_TO_PC(0x11, 0x1ff),
11900
+ INT_TO_PC(0x100), INT_TO_PC(0x1ff));
11901
+
11902
+ print_file(STDERR, "tagged pointers (tagged vs tagged)\n");
11903
+ vmvector_tagged_pointer_tests(TAG_INT_TO_PC(0x11, 0x100), TAG_INT_TO_PC(0x11, 0x1ff),
11904
+ TAG_INT_TO_PC(0x11, 0x100), TAG_INT_TO_PC(0x11, 0x1ff));
11905
+
11906
+ print_file(STDERR, "tagged pointers (tagged vs different tag)\n");
11907
+ vmvector_tagged_pointer_tests(TAG_INT_TO_PC(0x11, 0x100), TAG_INT_TO_PC(0x11, 0x1ff),
11908
+ TAG_INT_TO_PC(0x22, 0x100), TAG_INT_TO_PC(0x22, 0x1ff));
11909
+ # endif
11718
11910
}
11719
11911
11720
11912
/* initial vector tests
0 commit comments