[PATCH] D87739: scudo: Add an API for disabling memory initialization per-thread.

Peter Collingbourne via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 16 19:26:33 PDT 2020


pcc added inline comments.


================
Comment at: compiler-rt/lib/scudo/standalone/combined.h:417
+            // therefore it needs to be zeroed now.
+            memset(TaggedPtr, 0, Min(Size, PrevEnd - TaggedUserPtr));
+          } else if (Size) {
----------------
pcc wrote:
> eugenis wrote:
> > eugenis wrote:
> > > resizeTaggedChunk does not zero memory. I think this  memset needs to cover the entire allocation?
> > Ah no, I misread. Ignore this.
> I think the problem is related to this line actually. `resizeTaggedChunk` rounds up to 16 before it starts zeroing, so the memset needs to stop at the rounded-up original bound, otherwise it can leave the end of the original last granule uninitialized. I am testing this diff:
> ```
> @@ -414,12 +424,18 @@ public:
>              // UAF tag. But if tagging was disabled per-thread when the memory
>              // was freed, it would not have been retagged and thus zeroed, and
>              // therefore it needs to be zeroed now.
> -            memset(TaggedPtr, 0, Min(Size, PrevEnd - TaggedUserPtr));
> +            memset(TaggedPtr, 0,
> +                   Min(Size, roundUpTo(PrevEnd - TaggedUserPtr,
> +                                       archMemoryTagGranuleSize())));
>            } else if (Size) {
>              // Clear any stack metadata that may have previously been stored in
>              // the chunk data.
> ```
Okay, this looks like this fixed the problem (stress tested on Android/FVP with a more rigorous version of my stress testing patch that verifies that calloc allocations are zeroed at allocation time). Also added a test case that fails with the previous version of my patch.


================
Comment at: compiler-rt/lib/scudo/standalone/combined.h:496
     if (Options.DeallocTypeMismatch) {
-      if (Header.Origin != Origin) {
+      if (Header.OriginOrWasZeroed != Origin) {
         // With the exception of memalign'd chunks, that can be still be free'd.
----------------
hctim wrote:
> pcc wrote:
> > hctim wrote:
> > > Isn't this now broken under `dealloc_type_mismatch` and MTE?
> > No, because the field is intended to only have the "was zeroed" meaning while the chunk is not allocated. Note that the field is read before the call to `quarantineOrDeallocateChunk` later in this function causes it to take the "was zeroed" meaning.
> I see - thanks for the clarification.  Maybe `OriginIfAliveOrWasZeroedIfDead`? A bit wordy (can't think of anything more concise right now), but otherwise it's a little hard to infer this which meaning applies at which time (especially given that `SizeOrUnusedBytes` has different semantics). Either that or a comment in the declaration explaining the semantics would probably suffice.
Added a comment in the declaration.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87739/new/

https://reviews.llvm.org/D87739



More information about the llvm-commits mailing list