Skip to content

Commit 7268189

Browse files
muhomorrthestinger
authored andcommitted
mte: use tag 0 for freed slots, stop reserving tag 15
1 parent 3c1f40a commit 7268189

File tree

4 files changed

+17
-19
lines changed

4 files changed

+17
-19
lines changed

README.md

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -724,26 +724,24 @@ freeing as there would be if the kernel supported these features directly.
724724

725725
## Memory tagging
726726

727-
Random tags are set for all slab allocations when allocated, with 5 excluded values:
727+
Random tags are set for all slab allocations when allocated, with 4 excluded values:
728728

729-
1. the default `0` tag
730-
2. a statically *reserved free tag*
731-
3. the previous tag used for the slot
732-
4. the current (or previous) tag used for the slot to the left
733-
5. the current (or previous) tag used for the slot to the right
729+
1. the reserved `0` tag
730+
2. the previous tag used for the slot
731+
3. the current (or previous) tag used for the slot to the left
732+
4. the current (or previous) tag used for the slot to the right
734733

735-
When a slab allocation is freed, the *reserved free tag* is set for the slot.
734+
When a slab allocation is freed, the reserved `0` tag is set for the slot.
735+
Slab allocation slots are cleared before reuse when memory tagging is enabled.
736736

737737
This ensures the following properties:
738738

739739
- Linear overflows are deterministically detected.
740740
- Use-after-free are deterministically detected until the freed slot goes through
741741
both the random and FIFO quarantines, gets allocated again, goes through both
742742
quarantines again and then finally gets allocated again for a 2nd time.
743-
Since the default `0` tag isn't used, untagged memory can't access malloc allocations
744-
and vice versa, although it may make sense to reuse the default tag for free
745-
data to avoid reducing the possible random tags from 15 to 14, since freed
746-
data is always zeroed anyway.
743+
- Since the default `0` tag is reserved, untagged pointers can't access slab
744+
allocations and vice versa.
747745

748746
Slab allocations are done in a statically reserved region for each size class
749747
and all metadata is in a statically reserved region, so interactions between

androidtest/memtag/memtag_test.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ void *set_pointer_tag(void *ptr, u8 tag) {
4747
// This test checks that slab slot allocation uses tag that is distint from tags of its neighbors
4848
// and from the tag of the previous allocation that used the same slot
4949
void tag_distinctness() {
50-
// 0 and 15 are reserved
50+
// tag 0 is reserved
5151
const int min_tag = 1;
52-
const int max_tag = 14;
52+
const int max_tag = 0xf;
5353

5454
struct SizeClass {
5555
int size;
@@ -148,8 +148,8 @@ void tag_distinctness() {
148148
}
149149
}
150150

151-
// check that all of the tags were used, except reserved ones
152-
assert(seen_tags == (0xffff & ~(1 << 0 | 1 << 15)));
151+
// check that all of the tags were used, except for the reserved tag 0
152+
assert(seen_tags == (0xffff & ~(1 << 0)));
153153

154154
printf("size_class\t%i\t" "tdc_left %i\t" "tdc_right %i\t" "tdc_prev_alloc %i\n",
155155
sc.size, left_neighbor_tdc_cnt, right_neighbor_tdc_cnt, prev_alloc_tdc_cnt);

h_malloc.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,9 +574,8 @@ static void *tag_and_clear_slab_slot(struct slab_metadata *metadata, void *slot_
574574
// is constructed.
575575
u8 *slot_tags = metadata->arm_mte_tags;
576576

577-
// Tag exclusion mask. 0 tag is always excluded to detect accesses to slab memory via untagged
578-
// pointers. Moreover, 0 tag is excluded in bionic via PR_MTE_TAG_MASK prctl
579-
u64 tem = (1 << 0) | (1 << RESERVED_TAG);
577+
// tag exclusion mask
578+
u64 tem = (1 << RESERVED_TAG);
580579

581580
// current or previous tag of left neighbor or 0 if there's no left neighbor or if it was never used
582581
tem |= (1 << u4_arr_get(slot_tags, slot_idx));

memtag.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
#ifdef HAS_ARM_MTE
77
#include "arm_mte.h"
88
#define MEMTAG 1
9-
#define RESERVED_TAG 15
9+
// Note that bionic libc always reserves tag 0 via PR_MTE_TAG_MASK prctl
10+
#define RESERVED_TAG 0
1011
#define TAG_WIDTH 4
1112
#endif
1213

0 commit comments

Comments
 (0)