forked from OSchip/llvm-project
[scudo] Add Scudo support for Trusty OS
trusty.cpp and trusty.h define Trusty implementations of map and other platform-specific functions. In addition to adding Trusty configurations in allocator_config.h and size_class_map.h, MapSizeIncrement and PrimaryEnableRandomOffset are added as configurable options in allocator_config.h. Background on Trusty: https://source.android.com/security/trusty Differential Revision: https://reviews.llvm.org/D103578
This commit is contained in:
parent
1a216fb15a
commit
2551053e8d
|
@ -40,6 +40,12 @@ namespace scudo {
|
|||
// // eg: Ptr = Base + (CompactPtr << Scale).
|
||||
// typedef u32 PrimaryCompactPtrT;
|
||||
// static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
|
||||
// // Indicates support for offsetting the start of a region by
|
||||
// // a random number of pages. Only used with primary64.
|
||||
// static const bool PrimaryEnableRandomOffset = true;
|
||||
// // Call map for user memory with at least this size. Only used with
|
||||
// // primary64.
|
||||
// static const uptr PrimaryMapSizeIncrement = 1UL << 18;
|
||||
// // Defines the minimal & maximal release interval that can be set.
|
||||
// static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
|
||||
// static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
|
||||
|
@ -61,6 +67,8 @@ struct DefaultConfig {
|
|||
static const uptr PrimaryRegionSizeLog = 32U;
|
||||
typedef uptr PrimaryCompactPtrT;
|
||||
static const uptr PrimaryCompactPtrScale = 0;
|
||||
static const bool PrimaryEnableRandomOffset = true;
|
||||
static const uptr PrimaryMapSizeIncrement = 1UL << 18;
|
||||
#else
|
||||
typedef SizeClassAllocator32<DefaultConfig> Primary;
|
||||
static const uptr PrimaryRegionSizeLog = 19U;
|
||||
|
@ -89,6 +97,8 @@ struct AndroidConfig {
|
|||
static const uptr PrimaryRegionSizeLog = 28U;
|
||||
typedef u32 PrimaryCompactPtrT;
|
||||
static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
|
||||
static const bool PrimaryEnableRandomOffset = true;
|
||||
static const uptr PrimaryMapSizeIncrement = 1UL << 18;
|
||||
#else
|
||||
typedef SizeClassAllocator32<AndroidConfig> Primary;
|
||||
static const uptr PrimaryRegionSizeLog = 18U;
|
||||
|
@ -118,6 +128,8 @@ struct AndroidSvelteConfig {
|
|||
static const uptr PrimaryRegionSizeLog = 27U;
|
||||
typedef u32 PrimaryCompactPtrT;
|
||||
static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
|
||||
static const bool PrimaryEnableRandomOffset = true;
|
||||
static const uptr PrimaryMapSizeIncrement = 1UL << 18;
|
||||
#else
|
||||
typedef SizeClassAllocator32<AndroidSvelteConfig> Primary;
|
||||
static const uptr PrimaryRegionSizeLog = 16U;
|
||||
|
@ -146,6 +158,8 @@ struct FuchsiaConfig {
|
|||
typedef SizeClassAllocator64<FuchsiaConfig> Primary;
|
||||
static const uptr PrimaryRegionSizeLog = 30U;
|
||||
typedef u32 PrimaryCompactPtrT;
|
||||
static const bool PrimaryEnableRandomOffset = true;
|
||||
static const uptr PrimaryMapSizeIncrement = 1UL << 18;
|
||||
static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
|
||||
static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
|
||||
static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
|
||||
|
@ -154,12 +168,34 @@ struct FuchsiaConfig {
|
|||
template <class A>
|
||||
using TSDRegistryT = TSDRegistrySharedT<A, 8U, 4U>; // Shared, max 8 TSDs.
|
||||
};
|
||||
|
||||
struct TrustyConfig {
|
||||
using SizeClassMap = TrustySizeClassMap;
|
||||
static const bool MaySupportMemoryTagging = false;
|
||||
|
||||
typedef SizeClassAllocator64<TrustyConfig> Primary;
|
||||
// Some apps have 1 page of heap total so small regions are necessary.
|
||||
static const uptr PrimaryRegionSizeLog = 10U;
|
||||
typedef u32 PrimaryCompactPtrT;
|
||||
static const bool PrimaryEnableRandomOffset = false;
|
||||
// Trusty is extremely memory-constrained so minimally round up map calls.
|
||||
static const uptr PrimaryMapSizeIncrement = 1UL << 4;
|
||||
static const uptr PrimaryCompactPtrScale = SCUDO_MIN_ALIGNMENT_LOG;
|
||||
static const s32 PrimaryMinReleaseToOsIntervalMs = INT32_MIN;
|
||||
static const s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
|
||||
|
||||
typedef MapAllocatorNoCache SecondaryCache;
|
||||
template <class A>
|
||||
using TSDRegistryT = TSDRegistrySharedT<A, 1U, 1U>; // Shared, max 1 TSD.
|
||||
};
|
||||
#endif
|
||||
|
||||
#if SCUDO_ANDROID
|
||||
typedef AndroidConfig Config;
|
||||
#elif SCUDO_FUCHSIA
|
||||
typedef FuchsiaConfig Config;
|
||||
#elif SCUDO_TRUSTY
|
||||
typedef TrustyConfig Config;
|
||||
#else
|
||||
typedef DefaultConfig Config;
|
||||
#endif
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "fuchsia.h"
|
||||
#include "linux.h"
|
||||
#include "trusty.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// Transitive includes of stdint.h specify some of the defines checked below.
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#if defined(__linux__) && !defined(__TRUSTY__)
|
||||
#define SCUDO_LINUX 1
|
||||
#else
|
||||
#define SCUDO_LINUX 0
|
||||
|
@ -31,6 +31,12 @@
|
|||
#define SCUDO_FUCHSIA 0
|
||||
#endif
|
||||
|
||||
#if defined(__TRUSTY__)
|
||||
#define SCUDO_TRUSTY 1
|
||||
#else
|
||||
#define SCUDO_TRUSTY 0
|
||||
#endif
|
||||
|
||||
#if __LP64__
|
||||
#define SCUDO_WORDSIZE 64U
|
||||
#else
|
||||
|
|
|
@ -64,6 +64,9 @@ public:
|
|||
if (SCUDO_FUCHSIA)
|
||||
reportError("SizeClassAllocator32 is not supported on Fuchsia");
|
||||
|
||||
if (SCUDO_TRUSTY)
|
||||
reportError("SizeClassAllocator32 is not supported on Trusty");
|
||||
|
||||
PossibleRegions.init();
|
||||
|
||||
u32 Seed;
|
||||
|
|
|
@ -25,8 +25,9 @@ namespace scudo {
|
|||
//
|
||||
// It starts by reserving NumClasses * 2^RegionSizeLog bytes, equally divided in
|
||||
// Regions, specific to each size class. Note that the base of that mapping is
|
||||
// random (based to the platform specific map() capabilities), and that each
|
||||
// Region actually starts at a random offset from its base.
|
||||
// random (based to the platform specific map() capabilities). If
|
||||
// PrimaryEnableRandomOffset is set, each Region actually starts at a random
|
||||
// offset from its base.
|
||||
//
|
||||
// Regions are mapped incrementally on demand to fulfill allocation requests,
|
||||
// those mappings being split into equally sized Blocks based on the size class
|
||||
|
@ -70,9 +71,12 @@ public:
|
|||
const uptr PageSize = getPageSizeCached();
|
||||
for (uptr I = 0; I < NumClasses; I++) {
|
||||
RegionInfo *Region = getRegionInfo(I);
|
||||
// The actual start of a region is offseted by a random number of pages.
|
||||
Region->RegionBeg =
|
||||
getRegionBaseByClassId(I) + (getRandomModN(&Seed, 16) + 1) * PageSize;
|
||||
// The actual start of a region is offset by a random number of pages
|
||||
// when PrimaryEnableRandomOffset is set.
|
||||
Region->RegionBeg = getRegionBaseByClassId(I) +
|
||||
(Config::PrimaryEnableRandomOffset
|
||||
? ((getRandomModN(&Seed, 16) + 1) * PageSize)
|
||||
: 0);
|
||||
Region->RandState = getRandomU32(&Seed);
|
||||
Region->ReleaseInfo.LastReleaseAtNs = Time;
|
||||
}
|
||||
|
@ -267,8 +271,7 @@ private:
|
|||
static const uptr NumClasses = SizeClassMap::NumClasses;
|
||||
static const uptr PrimarySize = RegionSize * NumClasses;
|
||||
|
||||
// Call map for user memory with at least this size.
|
||||
static const uptr MapSizeIncrement = 1UL << 18;
|
||||
static const uptr MapSizeIncrement = Config::PrimaryMapSizeIncrement;
|
||||
// Fill at most this number of batches from the newly map'd memory.
|
||||
static const u32 MaxNumBatches = SCUDO_ANDROID ? 4U : 8U;
|
||||
|
||||
|
|
|
@ -308,6 +308,20 @@ struct SvelteSizeClassConfig {
|
|||
|
||||
typedef FixedSizeClassMap<SvelteSizeClassConfig> SvelteSizeClassMap;
|
||||
|
||||
// Trusty is configured to only have one region containing blocks of size
|
||||
// 2^7 bytes.
|
||||
struct TrustySizeClassConfig {
|
||||
static const uptr NumBits = 1;
|
||||
static const uptr MinSizeLog = 7;
|
||||
static const uptr MidSizeLog = 7;
|
||||
static const uptr MaxSizeLog = 7;
|
||||
static const u32 MaxNumCachedHint = 8;
|
||||
static const uptr MaxBytesCachedLog = 10;
|
||||
static const uptr SizeDelta = 0;
|
||||
};
|
||||
|
||||
typedef FixedSizeClassMap<TrustySizeClassConfig> TrustySizeClassMap;
|
||||
|
||||
template <typename SCMap> inline void printMap() {
|
||||
ScopedString Buffer;
|
||||
uptr PrevS = 0;
|
||||
|
|
|
@ -521,6 +521,8 @@ struct DeathConfig {
|
|||
static const scudo::s32 PrimaryMaxReleaseToOsIntervalMs = INT32_MAX;
|
||||
typedef scudo::uptr PrimaryCompactPtrT;
|
||||
static const scudo::uptr PrimaryCompactPtrScale = 0;
|
||||
static const bool PrimaryEnableRandomOffset = true;
|
||||
static const scudo::uptr PrimaryMapSizeIncrement = 1UL << 18;
|
||||
|
||||
typedef scudo::MapAllocatorNoCache SecondaryCache;
|
||||
template <class A> using TSDRegistryT = scudo::TSDRegistrySharedT<A, 1U, 1U>;
|
||||
|
|
|
@ -29,6 +29,8 @@ struct TestConfig1 {
|
|||
static const bool MaySupportMemoryTagging = false;
|
||||
typedef scudo::uptr PrimaryCompactPtrT;
|
||||
static const scudo::uptr PrimaryCompactPtrScale = 0;
|
||||
static const bool PrimaryEnableRandomOffset = true;
|
||||
static const scudo::uptr PrimaryMapSizeIncrement = 1UL << 18;
|
||||
};
|
||||
|
||||
struct TestConfig2 {
|
||||
|
@ -43,6 +45,8 @@ struct TestConfig2 {
|
|||
static const bool MaySupportMemoryTagging = false;
|
||||
typedef scudo::uptr PrimaryCompactPtrT;
|
||||
static const scudo::uptr PrimaryCompactPtrScale = 0;
|
||||
static const bool PrimaryEnableRandomOffset = true;
|
||||
static const scudo::uptr PrimaryMapSizeIncrement = 1UL << 18;
|
||||
};
|
||||
|
||||
struct TestConfig3 {
|
||||
|
@ -57,6 +61,8 @@ struct TestConfig3 {
|
|||
static const bool MaySupportMemoryTagging = true;
|
||||
typedef scudo::uptr PrimaryCompactPtrT;
|
||||
static const scudo::uptr PrimaryCompactPtrScale = 0;
|
||||
static const bool PrimaryEnableRandomOffset = true;
|
||||
static const scudo::uptr PrimaryMapSizeIncrement = 1UL << 18;
|
||||
};
|
||||
|
||||
template <typename BaseConfig, typename SizeClassMapT>
|
||||
|
@ -145,6 +151,8 @@ struct SmallRegionsConfig {
|
|||
static const bool MaySupportMemoryTagging = false;
|
||||
typedef scudo::uptr PrimaryCompactPtrT;
|
||||
static const scudo::uptr PrimaryCompactPtrScale = 0;
|
||||
static const bool PrimaryEnableRandomOffset = true;
|
||||
static const scudo::uptr PrimaryMapSizeIncrement = 1UL << 18;
|
||||
};
|
||||
|
||||
// The 64-bit SizeClassAllocator can be easily OOM'd with small region sizes.
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
//===-- trusty.cpp ---------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#if SCUDO_TRUSTY
|
||||
|
||||
#include "common.h"
|
||||
#include "mutex.h"
|
||||
#include "string_utils.h"
|
||||
#include "trusty.h"
|
||||
|
||||
#include <errno.h> // for errno
|
||||
#include <stdio.h> // for printf()
|
||||
#include <stdlib.h> // for getenv()
|
||||
#include <sys/auxv.h> // for getauxval()
|
||||
#include <time.h> // for clock_gettime()
|
||||
#include <trusty_syscalls.h> // for _trusty_brk()
|
||||
|
||||
#define SBRK_ALIGN 32
|
||||
|
||||
namespace scudo {
|
||||
|
||||
uptr getPageSize() { return getauxval(AT_PAGESZ); }
|
||||
|
||||
void NORETURN die() { abort(); }
|
||||
|
||||
void *map(UNUSED void *Addr, uptr Size, UNUSED const char *Name, uptr Flags,
|
||||
UNUSED MapPlatformData *Data) {
|
||||
// Calling _trusty_brk(0) returns the current program break.
|
||||
uptr ProgramBreak = reinterpret_cast<uptr>(_trusty_brk(0));
|
||||
uptr Start;
|
||||
uptr End;
|
||||
|
||||
Start = roundUpTo(ProgramBreak, SBRK_ALIGN);
|
||||
// Don't actually extend the heap if MAP_NOACCESS flag is set since this is
|
||||
// the case where Scudo tries to reserve a memory region without mapping
|
||||
// physical pages.
|
||||
if (Flags & MAP_NOACCESS)
|
||||
return reinterpret_cast<void *>(Start);
|
||||
|
||||
// Attempt to extend the heap by Size bytes using _trusty_brk.
|
||||
End = roundUpTo(Start + Size, SBRK_ALIGN);
|
||||
ProgramBreak =
|
||||
reinterpret_cast<uptr>(_trusty_brk(reinterpret_cast<void *>(End)));
|
||||
if (ProgramBreak < End) {
|
||||
errno = ENOMEM;
|
||||
dieOnMapUnmapError(Size);
|
||||
return nullptr;
|
||||
}
|
||||
return reinterpret_cast<void *>(Start); // Base of new reserved region.
|
||||
}
|
||||
|
||||
// Unmap is a no-op since Trusty uses sbrk instead of memory mapping.
|
||||
void unmap(UNUSED void *Addr, UNUSED uptr Size, UNUSED uptr Flags,
|
||||
UNUSED MapPlatformData *Data) {}
|
||||
|
||||
void setMemoryPermission(UNUSED uptr Addr, UNUSED uptr Size, UNUSED uptr Flags,
|
||||
UNUSED MapPlatformData *Data) {}
|
||||
|
||||
void releasePagesToOS(UNUSED uptr BaseAddress, UNUSED uptr Offset,
|
||||
UNUSED uptr Size, UNUSED MapPlatformData *Data) {}
|
||||
|
||||
const char *getEnv(const char *Name) { return getenv(Name); }
|
||||
|
||||
// All mutex operations are a no-op since Trusty doesn't currently support
|
||||
// threads.
|
||||
bool HybridMutex::tryLock() { return true; }
|
||||
|
||||
void HybridMutex::lockSlow() {}
|
||||
|
||||
void HybridMutex::unlock() {}
|
||||
|
||||
u64 getMonotonicTime() {
|
||||
timespec TS;
|
||||
clock_gettime(CLOCK_MONOTONIC, &TS);
|
||||
return static_cast<u64>(TS.tv_sec) * (1000ULL * 1000 * 1000) +
|
||||
static_cast<u64>(TS.tv_nsec);
|
||||
}
|
||||
|
||||
u32 getNumberOfCPUs() { return 0; }
|
||||
|
||||
u32 getThreadID() { return 0; }
|
||||
|
||||
bool getRandom(UNUSED void *Buffer, UNUSED uptr Length, UNUSED bool Blocking) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void outputRaw(const char *Buffer) { printf("%s", Buffer); }
|
||||
|
||||
void setAbortMessage(UNUSED const char *Message) {}
|
||||
|
||||
} // namespace scudo
|
||||
|
||||
#endif // SCUDO_TRUSTY
|
|
@ -0,0 +1,24 @@
|
|||
//===-- trusty.h -----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SCUDO_TRUSTY_H_
|
||||
#define SCUDO_TRUSTY_H_
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
#if SCUDO_TRUSTY
|
||||
|
||||
namespace scudo {
|
||||
// MapPlatformData is unused on Trusty, define it as a minimially sized
|
||||
// structure.
|
||||
struct MapPlatformData {};
|
||||
} // namespace scudo
|
||||
|
||||
#endif // SCUDO_TRUSTY
|
||||
|
||||
#endif // SCUDO_TRUSTY_H_
|
Loading…
Reference in New Issue