This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: RFD - Support for memory tagging in GLIBC
- From: DJ Delorie <dj at redhat dot com>
- To: "Richard Earnshaw \(lists\)" <Richard dot Earnshaw at arm dot com>
- Cc: libc-alpha at sourceware dot org
- Date: Mon, 09 Sep 2019 15:11:27 -0400
- Subject: Re: RFD - Support for memory tagging in GLIBC
"Richard Earnshaw (lists)" <Richard.Earnshaw@arm.com> writes:
> I'm posting this now before the Cauldron so hopefully we can have some
> useful discussions on the matter during that.
Given the long list of glibc topics, perhaps we could grab an empty room
at some point for this one? It's a bit more focused than the glibc bof.
Else we're down to about 3 minutes per topic ;-)
> Unused bits in the top byte of a 64-bit address pointer
I wonder if we could generically abuse these bits on other architectures
as well, but as a no-op? It might require some platform-independent
kernel interface to say "I want my address space to ignore the top four
bits please". I don't know what source-level checks or optimizations we
could do here, but having a few more bits in the chunk header could be
useful.
> can then be set to describe the colour expected at that address and a
> protection fault can be raised if there is then a mismatch.
/me is looking forward to SIGPURPLE and SIGGREEN.
> Nomenclature: The AArch64 extension is called MTE. I've tried to use
> the term 'memory tagging' (mtag) in the generic code to keep the layers
> separate. Ideally mtag can be used on multiple architectures.
Just so I understand - the pointer's top four bits are compared to a
*hidden* set of four bits per-memory-qword. Setting the pointer's bits
is just math, but there's some arch-specific way to tag the memory
itself?
> - for realloc I've chosen to recolour all affected memory even if the
> same logical address is returned (the pointer will contain a different
> colour, ensuring that before-and-after pointers will not compare equal).
We could conditional this on one of the mcheck states.
> - free() recolours the memory; this is a run-time overhead but is useful
> for catching use-after-free accesses.
Likewise here.
> +/* When using tagged memory, we cannot share the end of the user block
> + with the header for the next chunk,
This is going to cause alarm; it's a HUGE relative overhead on the
common small allocations, and will likely bloat RSS use. Allocations up
to 24 bytes use the smallest (32-byte) span, if we have to bump it one
we'd have those go to 48-byte spans, a 50% increase in RSS, or limit
smallest allocations to 16 bytes.
Perhaps a free'd block could be recolored for internal use only, and the
end chunk recolored appropriately? That would retain our current
allocation sizes and also protect against some use-after-free cases.
It would also stop glibc from accessing not-freed memory as a chunk ptr.
> + ((mchunkptr)__libc_mtag_address_get_tag (((char*)(mem) - 2*SIZE_SZ)))
to me, "get tag" should return the 4-bit tag, not a pointer-thats-tagged
or a pointer-without-tag. Bikeshedding, but names are important for
future understanding.
> +#ifdef _LIBC_MTAG
> + /* Quickly check that the freed pointer matches the tag for the memory.
> + This gives a useful double-free detection. */
> + *(volatile char *)mem;
> +#endif
I worry about how gcc will diagnose this in the future...
> +/* Non-zero if memory obtained via morecore (sbrk) is not tagged. */
> +#define __MTAG_SBRK_UNTAGGED 0
Is one of the 16 colors reserved for "untagged" somehow?
> +/* Set the tags for a region of memory, which must have size and alignment
> + that are multiples of __MTAG_GRANULE_SIZE. Size cannot be zero.
> + void *__libc_mtag_tag_region (const void *, size_t) */
> +void *__libc_mtag_tag_region (void *, size_t);
Copies tag from pointer to memory
> +/* Optimized equivalent to __libc_mtag_tag_region followed by memset. */
> +void *__libc_mtag_memset_with_tag(void *, int, size_t);
Same, with memset.
> +/* Convert address P to a pointer that is tagged correctly for that
> + location.
> + void *__libc_mtag_address_get_tag (void*) */
> +void *__libc_mtag_address_get_tag(void *);
Copies tag from memory to pointer.
> +/* Assign a new (random) tag to a pointer P (does not adjust the tag on
> + the memory addressed).
> + void *__libc_mtag_new_tag (void*) */
> +void *__libc_mtag_new_tag(void *);
Create new tag. Does this have a way of skipping reserved colors?