Switch from getrlimit(RLIMIT_AS) to android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES).
The RLIMIT_AS limit was introduced as a security mitigation, but it
isn't exactly what the media processes want to control. It is also
problematic under sanitizers which allocate large amounts of address
space as shadow memory, and is especially problematic under shadow
call stack, which requires 16MB of address space per thread. Instead,
use the newly introduced android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES)
to control the allocator's memory limit directly.
Also remove ASAN/HWASAN/CFI specific hacks; they are no longer
necessary because these tools consume address space using mmap and
not the allocator, and remove the 64-bit pointer check before calling
__scudo_set_rss_limit, since otherwise the limit would stop being
enforced in 32-bit mode with Scudo.
Bug: 118642754
Change-Id: Ie66128626976c0b04d5dafd455c375bbfdccc083
diff --git a/media/libmedia/MediaUtils.cpp b/media/libmedia/MediaUtils.cpp
index bcc7ebf..31972fa 100644
--- a/media/libmedia/MediaUtils.cpp
+++ b/media/libmedia/MediaUtils.cpp
@@ -22,23 +22,16 @@
#include <sys/resource.h>
#include <unistd.h>
+#include <bionic_malloc.h>
+
#include "MediaUtils.h"
-extern "C" size_t __cfi_shadow_size();
extern "C" void __scudo_set_rss_limit(size_t, int) __attribute__((weak));
namespace android {
-void limitProcessMemory(
- const char *property,
- size_t numberOfBytes,
- size_t percentageOfTotalMem) {
-
- if (running_with_asan()) {
- ALOGW("Running with (HW)ASan, skip enforcing memory limitations.");
- return;
- }
-
+void limitProcessMemory(const char *property, size_t numberOfBytes,
+ size_t percentageOfTotalMem) {
long pageSize = sysconf(_SC_PAGESIZE);
long numPages = sysconf(_SC_PHYS_PAGES);
size_t maxMem = SIZE_MAX;
@@ -66,38 +59,17 @@
maxMem = propVal;
}
- // If 64-bit Scudo is in use, enforce the hard RSS limit (in MB).
- if (maxMem != SIZE_MAX && sizeof(void *) == 8 &&
- &__scudo_set_rss_limit != 0) {
+ // If Scudo is in use, enforce the hard RSS limit (in MB).
+ if (maxMem != SIZE_MAX && &__scudo_set_rss_limit != 0) {
__scudo_set_rss_limit(maxMem >> 20, 1);
ALOGV("Scudo hard RSS limit set to %zu MB", maxMem >> 20);
return;
}
- // Increase by the size of the CFI shadow mapping. Most of the shadow is not
- // backed with physical pages, and it is possible for the result to be
- // higher than total physical memory. This is fine for RLIMIT_AS.
- size_t cfi_size = __cfi_shadow_size();
- if (cfi_size) {
- ALOGV("cfi shadow size: %zu", cfi_size);
- if (maxMem <= SIZE_MAX - cfi_size) {
- maxMem += cfi_size;
- } else {
- maxMem = SIZE_MAX;
- }
+ if (!android_mallopt(M_SET_ALLOCATION_LIMIT_BYTES, &maxMem,
+ sizeof(maxMem))) {
+ ALOGW("couldn't set allocation limit");
}
- ALOGV("actual limit: %zu", maxMem);
-
- struct rlimit limit;
- getrlimit(RLIMIT_AS, &limit);
- ALOGV("original limits: %lld/%lld", (long long)limit.rlim_cur, (long long)limit.rlim_max);
- limit.rlim_cur = maxMem;
- setrlimit(RLIMIT_AS, &limit);
- limit.rlim_cur = -1;
- limit.rlim_max = -1;
- getrlimit(RLIMIT_AS, &limit);
- ALOGV("new limits: %lld/%lld", (long long)limit.rlim_cur, (long long)limit.rlim_max);
-
}
} // namespace android