1212#include " chunk.h"
1313#include " common.h"
1414#include " list.h"
15+ #include " mem_map.h"
1516#include " memtag.h"
1617#include " mutex.h"
1718#include " options.h"
@@ -37,9 +38,7 @@ struct alignas(Max<uptr>(archSupportsMemoryTagging()
3738 LargeBlock::Header *Next;
3839 uptr CommitBase;
3940 uptr CommitSize;
40- uptr MapBase;
41- uptr MapSize;
42- [[no_unique_address]] MapPlatformData Data;
41+ MemMapT MemMap;
4342};
4443
4544static_assert (sizeof (Header) % (1U << SCUDO_MIN_ALIGNMENT_LOG) == 0 , " " );
@@ -66,8 +65,11 @@ template <typename Config> static Header *getHeader(const void *Ptr) {
6665} // namespace LargeBlock
6766
6867static void unmap (LargeBlock::Header *H) {
69- MapPlatformData Data = H->Data ;
70- unmap (reinterpret_cast <void *>(H->MapBase ), H->MapSize , UNMAP_ALL, &Data);
68+ // Note that the `H->MapMap` is stored on the pages managed by itself. Take
69+ // over the ownership before unmap() so that any operation along with unmap()
70+ // won't touch inaccessible pages.
71+ MemMapT MemMap = H->MemMap ;
72+ MemMap.unmap (MemMap.getBase (), MemMap.getCapacity ());
7173}
7274
7375class MapAllocatorNoCache {
@@ -97,20 +99,19 @@ static const uptr MaxUnusedCachePages = 4U;
9799
98100template <typename Config>
99101void mapSecondary (Options Options, uptr CommitBase, uptr CommitSize,
100- uptr AllocPos, uptr Flags, MapPlatformData *Data ) {
102+ uptr AllocPos, uptr Flags, MemMapT &MemMap ) {
101103 const uptr MaxUnusedCacheBytes = MaxUnusedCachePages * getPageSizeCached ();
102104 if (useMemoryTagging<Config>(Options) && CommitSize > MaxUnusedCacheBytes) {
103105 const uptr UntaggedPos = Max (AllocPos, CommitBase + MaxUnusedCacheBytes);
104- map (reinterpret_cast <void *>(CommitBase), UntaggedPos - CommitBase,
105- " scudo:secondary" , MAP_RESIZABLE | MAP_MEMTAG | Flags, Data);
106- map (reinterpret_cast <void *>(UntaggedPos),
107- CommitBase + CommitSize - UntaggedPos, " scudo:secondary" ,
108- MAP_RESIZABLE | Flags, Data);
106+ MemMap.remap (CommitBase, UntaggedPos - CommitBase, " scudo:secondary" ,
107+ MAP_RESIZABLE | MAP_MEMTAG | Flags);
108+ MemMap.remap (UntaggedPos, CommitBase + CommitSize - UntaggedPos,
109+ " scudo:secondary" , MAP_RESIZABLE | Flags);
109110 } else {
110- map ( reinterpret_cast < void *>(CommitBase), CommitSize, " scudo:secondary " ,
111+ const uptr RemapFlags =
111112 MAP_RESIZABLE | (useMemoryTagging<Config>(Options) ? MAP_MEMTAG : 0 ) |
112- Flags,
113- Data );
113+ Flags;
114+ MemMap. remap (CommitBase, CommitSize, " scudo:secondary " , RemapFlags );
114115 }
115116}
116117
@@ -155,10 +156,8 @@ template <typename Config> class MapAllocatorCache {
155156 CachedBlock Entry;
156157 Entry.CommitBase = H->CommitBase ;
157158 Entry.CommitSize = H->CommitSize ;
158- Entry.MapBase = H->MapBase ;
159- Entry.MapSize = H->MapSize ;
160159 Entry.BlockBegin = reinterpret_cast <uptr>(H + 1 );
161- Entry.Data = H->Data ;
160+ Entry.MemMap = H->MemMap ;
162161 Entry.Time = Time;
163162 if (useMemoryTagging<Config>(Options)) {
164163 if (Interval == 0 && !SCUDO_FUCHSIA) {
@@ -168,13 +167,13 @@ template <typename Config> class MapAllocatorCache {
168167 // on top so we just do the two syscalls there.
169168 Entry.Time = 0 ;
170169 mapSecondary<Config>(Options, Entry.CommitBase , Entry.CommitSize ,
171- Entry.CommitBase , MAP_NOACCESS, & Entry.Data );
170+ Entry.CommitBase , MAP_NOACCESS, Entry.MemMap );
172171 } else {
173- setMemoryPermission (Entry.CommitBase , Entry.CommitSize , MAP_NOACCESS ,
174- &Entry. Data );
172+ Entry. MemMap . setMemoryPermission (Entry.CommitBase , Entry.CommitSize ,
173+ MAP_NOACCESS );
175174 }
176175 } else if (Interval == 0 ) {
177- releasePagesToOS (Entry.CommitBase , 0 , Entry.CommitSize , &Entry. Data );
176+ Entry. MemMap . releasePagesToOS (Entry.CommitBase , Entry.CommitSize );
178177 Entry.Time = 0 ;
179178 }
180179 do {
@@ -223,8 +222,7 @@ template <typename Config> class MapAllocatorCache {
223222 else if (Interval >= 0 )
224223 releaseOlderThan (Time - static_cast <u64 >(Interval) * 1000000 );
225224 if (!EntryCached)
226- unmap (reinterpret_cast <void *>(Entry.MapBase ), Entry.MapSize , UNMAP_ALL,
227- &Entry.Data );
225+ Entry.MemMap .unmap (Entry.MemMap .getBase (), Entry.MemMap .getCapacity ());
228226 }
229227
230228 bool retrieve (Options Options, uptr Size, uptr Alignment,
@@ -267,7 +265,7 @@ template <typename Config> class MapAllocatorCache {
267265 LargeBlock::addHeaderTag<Config>(HeaderPos));
268266 *Zeroed = Entry.Time == 0 ;
269267 if (useMemoryTagging<Config>(Options))
270- setMemoryPermission (Entry.CommitBase , Entry.CommitSize , 0 , &Entry. Data );
268+ Entry. MemMap . setMemoryPermission (Entry.CommitBase , Entry.CommitSize , 0 );
271269 uptr NewBlockBegin = reinterpret_cast <uptr>(*H + 1 );
272270 if (useMemoryTagging<Config>(Options)) {
273271 if (*Zeroed) {
@@ -282,9 +280,7 @@ template <typename Config> class MapAllocatorCache {
282280 }
283281 (*H)->CommitBase = Entry.CommitBase ;
284282 (*H)->CommitSize = Entry.CommitSize ;
285- (*H)->MapBase = Entry.MapBase ;
286- (*H)->MapSize = Entry.MapSize ;
287- (*H)->Data = Entry.Data ;
283+ (*H)->MemMap = Entry.MemMap ;
288284 return true ;
289285 }
290286
@@ -323,16 +319,18 @@ template <typename Config> class MapAllocatorCache {
323319 ScopedLock L (Mutex);
324320 for (u32 I = 0 ; I != Config::SecondaryCacheQuarantineSize; ++I) {
325321 if (Quarantine[I].CommitBase ) {
326- unmap ( reinterpret_cast < void *>( Quarantine[I].MapBase ),
327- Quarantine[I]. MapSize , UNMAP_ALL, &Quarantine[I]. Data );
322+ MemMapT &MemMap = Quarantine[I].MemMap ;
323+ MemMap. unmap (MemMap. getBase (), MemMap. getCapacity () );
328324 Quarantine[I].CommitBase = 0 ;
329325 }
330326 }
331327 const u32 MaxCount = atomic_load_relaxed (&MaxEntriesCount);
332- for (u32 I = 0 ; I < MaxCount; I++)
333- if (Entries[I].CommitBase )
334- setMemoryPermission (Entries[I].CommitBase , Entries[I].CommitSize , 0 ,
335- &Entries[I].Data );
328+ for (u32 I = 0 ; I < MaxCount; I++) {
329+ if (Entries[I].CommitBase ) {
330+ Entries[I].MemMap .setMemoryPermission (Entries[I].CommitBase ,
331+ Entries[I].CommitSize , 0 );
332+ }
333+ }
336334 QuarantinePos = -1U ;
337335 }
338336
@@ -344,38 +342,31 @@ template <typename Config> class MapAllocatorCache {
344342
345343private:
346344 void empty () {
347- struct {
348- void *MapBase;
349- uptr MapSize;
350- MapPlatformData Data;
351- } MapInfo[Config::SecondaryCacheEntriesArraySize];
345+ MemMapT MapInfo[Config::SecondaryCacheEntriesArraySize];
352346 uptr N = 0 ;
353347 {
354348 ScopedLock L (Mutex);
355349 for (uptr I = 0 ; I < Config::SecondaryCacheEntriesArraySize; I++) {
356350 if (!Entries[I].CommitBase )
357351 continue ;
358- MapInfo[N].MapBase = reinterpret_cast <void *>(Entries[I].MapBase );
359- MapInfo[N].MapSize = Entries[I].MapSize ;
360- MapInfo[N].Data = Entries[I].Data ;
352+ MapInfo[N] = Entries[I].MemMap ;
361353 Entries[I].CommitBase = 0 ;
362354 N++;
363355 }
364356 EntriesCount = 0 ;
365357 IsFullEvents = 0 ;
366358 }
367- for (uptr I = 0 ; I < N; I++)
368- unmap (MapInfo[I].MapBase , MapInfo[I].MapSize , UNMAP_ALL,
369- &MapInfo[I].Data );
359+ for (uptr I = 0 ; I < N; I++) {
360+ MemMapT &MemMap = MapInfo[I];
361+ MemMap.unmap (MemMap.getBase (), MemMap.getCapacity ());
362+ }
370363 }
371364
372365 struct CachedBlock {
373366 uptr CommitBase;
374367 uptr CommitSize;
375- uptr MapBase;
376- uptr MapSize;
377368 uptr BlockBegin;
378- [[no_unique_address]] MapPlatformData Data ;
369+ MemMapT MemMap ;
379370 u64 Time;
380371 };
381372
@@ -387,7 +378,7 @@ template <typename Config> class MapAllocatorCache {
387378 OldestTime = Entry.Time ;
388379 return ;
389380 }
390- releasePagesToOS (Entry.CommitBase , 0 , Entry.CommitSize , &Entry. Data );
381+ Entry. MemMap . releasePagesToOS (Entry.CommitBase , Entry.CommitSize );
391382 Entry.Time = 0 ;
392383 }
393384
@@ -538,16 +529,20 @@ void *MapAllocator<Config>::allocate(Options Options, uptr Size, uptr Alignment,
538529 AllocatedBytes += BlockSize;
539530 NumberOfAllocs++;
540531 Stats.add (StatAllocated, BlockSize);
541- Stats.add (StatMapped, H->MapSize );
532+ Stats.add (StatMapped, H->MemMap . getCapacity () );
542533 }
543534 return Ptr;
544535 }
545536 }
546537
547- MapPlatformData Data = {} ;
538+ ReservedMemoryT ReservedMemory ;
548539 const uptr MapSize = RoundedSize + 2 * PageSize;
549- uptr MapBase = reinterpret_cast <uptr>(
550- map (nullptr , MapSize, nullptr , MAP_NOACCESS | MAP_ALLOWNOMEM, &Data));
540+ ReservedMemory.create (/* Addr=*/ 0U , MapSize, nullptr , MAP_ALLOWNOMEM);
541+
542+ // Take the entire ownership of reserved region.
543+ MemMapT MemMap = ReservedMemory.dispatch (ReservedMemory.getBase (),
544+ ReservedMemory.getCapacity ());
545+ uptr MapBase = MemMap.getBase ();
551546 if (UNLIKELY (!MapBase))
552547 return nullptr ;
553548 uptr CommitBase = MapBase + PageSize;
@@ -565,33 +560,31 @@ void *MapAllocator<Config>::allocate(Options Options, uptr Size, uptr Alignment,
565560 // We only trim the extra memory on 32-bit platforms: 64-bit platforms
566561 // are less constrained memory wise, and that saves us two syscalls.
567562 if (SCUDO_WORDSIZE == 32U && NewMapBase != MapBase) {
568- unmap (reinterpret_cast < void *>( MapBase) , NewMapBase - MapBase, 0 , &Data );
563+ MemMap. unmap (MapBase, NewMapBase - MapBase);
569564 MapBase = NewMapBase;
570565 }
571566 const uptr NewMapEnd =
572567 CommitBase + PageSize + roundUp (Size, PageSize) + PageSize;
573568 DCHECK_LE (NewMapEnd, MapEnd);
574569 if (SCUDO_WORDSIZE == 32U && NewMapEnd != MapEnd) {
575- unmap (reinterpret_cast < void *>( NewMapEnd) , MapEnd - NewMapEnd, 0 , &Data );
570+ MemMap. unmap (NewMapEnd, MapEnd - NewMapEnd);
576571 MapEnd = NewMapEnd;
577572 }
578573 }
579574
580575 const uptr CommitSize = MapEnd - PageSize - CommitBase;
581576 const uptr AllocPos = roundDown (CommitBase + CommitSize - Size, Alignment);
582- mapSecondary<Config>(Options, CommitBase, CommitSize, AllocPos, 0 , &Data );
577+ mapSecondary<Config>(Options, CommitBase, CommitSize, AllocPos, 0 , MemMap );
583578 const uptr HeaderPos =
584579 AllocPos - Chunk::getHeaderSize () - LargeBlock::getHeaderSize ();
585580 LargeBlock::Header *H = reinterpret_cast <LargeBlock::Header *>(
586581 LargeBlock::addHeaderTag<Config>(HeaderPos));
587582 if (useMemoryTagging<Config>(Options))
588583 storeTags (LargeBlock::addHeaderTag<Config>(CommitBase),
589584 reinterpret_cast <uptr>(H + 1 ));
590- H->MapBase = MapBase;
591- H->MapSize = MapEnd - MapBase;
592585 H->CommitBase = CommitBase;
593586 H->CommitSize = CommitSize;
594- H->Data = Data ;
587+ H->MemMap = MemMap ;
595588 if (BlockEndPtr)
596589 *BlockEndPtr = CommitBase + CommitSize;
597590 {
@@ -602,7 +595,7 @@ void *MapAllocator<Config>::allocate(Options Options, uptr Size, uptr Alignment,
602595 LargestSize = CommitSize;
603596 NumberOfAllocs++;
604597 Stats.add (StatAllocated, CommitSize);
605- Stats.add (StatMapped, H->MapSize );
598+ Stats.add (StatMapped, H->MemMap . getCapacity () );
606599 }
607600 return reinterpret_cast <void *>(HeaderPos + LargeBlock::getHeaderSize ());
608601}
@@ -618,7 +611,7 @@ void MapAllocator<Config>::deallocate(Options Options, void *Ptr)
618611 FreedBytes += CommitSize;
619612 NumberOfFrees++;
620613 Stats.sub (StatAllocated, CommitSize);
621- Stats.sub (StatMapped, H->MapSize );
614+ Stats.sub (StatMapped, H->MemMap . getCapacity () );
622615 }
623616 Cache.store (Options, H);
624617}
0 commit comments