Пользовательский macOS malloc / free с использованием DYLD_INSERT_LIBRARIES не загружен достаточно рано - PullRequest
1 голос
/ 14 апреля 2019

Я пытаюсь написать свои собственные malloc / free оболочки, чтобы перехватить переполнение буфера.Причина: Guard Malloc недостаточно агрессивен, потому что он не может поймать переполнения, если они не находятся вблизи границ страницы.Я не возражаю обнаруживать переполнение позже (когда память освобождается), но я делаю не возражаю против его обнаружения.

Я использовал вставку и DYLD_INSERT_LIBRARIES, чтобы внедрить мои реализацииMalloc и бесплатно.Проблема в том, что похоже, что есть вызовы malloc, которые выполняются до загрузки моей динамической библиотеки.Когда эти объекты освобождены, мой free() считает, что они повреждены, потому что пролог и эпилог, которые я хочу добавить, отсутствуют.

Мой код выглядит следующим образом:

#define DYLD_INTERPOSE(_replacment,_replacee) \
__attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \
__attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee };

static const char *premagic = "abcdefgh";
static const char *postmagic = "zyxwvuts";
static const size_t prologueLength = 16;
static const size_t sizeOffset = 8;
static const size_t preMagicOffset = 0;
static const size_t epilogueLength = 8;
static const size_t totalOverhead = prologueLength + epilogueLength;

static void WriteMetadata(void *p, size_t size) {
    memmove(p + preMagicOffset, premagic, 8);
    memmove(p + sizeOffset, &size, sizeof(size));
    memmove(p + prologueLength + size, postmagic, 8);
}

static void CheckMemory(void *ptr) {
    void *realP = ptr - prologueLength;

    // Get size
    size_t size;
    memmove(&size, realP + sizeOffset, sizeof(size_t));

    // Check premagic
    if (memcmp(realP + preMagicOffset, premagic, 8)) {
        while (1);
    }

    // Check postmagic
    void *post = ptr + size;
    if (memcmp(post, postmagic, 8)) {
        while (1);
    }
}

void *ITMalloc(size_t size) {
    void *p = malloc(size + totalOverhead);
    if (p == 0) {
        return p;
    }
    WriteMetadata(p, size);
    return p + prologueLength;
}
DYLD_INTERPOSE(ITMalloc, malloc);

void ITFree(void *ptr) {
    CheckMemory(ptr);

    void *realP = ptr - prologueLength;
    free(realP);
}
DYLD_INTERPOSE(ITFree, free);

... and more for calloc, realloc, etc. ...

Воткак я ее запускаю:

DYLD_INSERT_LIBRARIES=libitmalloc.dylib ./helloworld

Проблема в том, что моя ITFree функция вызывается с ptr, который никогда не был выделен ITMalloc.Используя MallocStackLogging, я вижу, что он был выделен частью динамического загрузчика во время загрузки.Вот трассировка стека первого такого распределения:

 0x10261d036 (dyld) _dyld_start 
 0x10261d503 (dyld) dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*) 
 0x102623709 (dyld) dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) 
 0x10261e71f (dyld) dyld::initializeMainExecutable() 
 0x10262ee05 (dyld) ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) 
 0x10262ed73 (dyld) ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&)
 0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x10262fbea (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x102634798 (dyld) ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) 
 0x102634592 (dyld) ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) 
 0x7fff76ad49c5 (libSystem.B.dylib) libSystem_initializer 
 0x7fff79cccad2 (libdispatch.dylib) libdispatch_init 
 0x7fff79cc0e36 (libdispatch.dylib) _os_object_init 
 0x7fff784ce234 (libobjc.A.dylib) _objc_init 
 0x7fff79cf9a27 (libdyld.dylib) _dyld_objc_notify_register 
 0x10262162e (dyld) dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) 
 0x10262147b (dyld) dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) 
 0x7fff784e1560 (libobjc.A.dylib) map_images 
 0x7fff784cea50 (libobjc.A.dylib) map_images_nolock 
 0x7fff784cfa92 (libobjc.A.dylib) _read_images 
 0x7fff784d0847 (libobjc.A.dylib) NXCreateMapTable 
 0x7fff784d089d (libobjc.A.dylib) NXCreateMapTableFromZone 
 0x7fff784d09c0 (libobjc.A.dylib) NXCreateHashTable 
 0x7fff784d0aff (libobjc.A.dylib) NXCreateHashTableFromZone 
 0x7fff784d0de4 (libobjc.A.dylib) NXHashInsert 
 0x7fff79ebb1b0 (libsystem_malloc.dylib) malloc_zone_calloc 

Могу ли я заключить, что единственное решение состоит в том, чтобы поддерживать вспомогательный стол «известных указателей», который, как я знаю, имеет мой пролог / эпилог, и неполагаться на перехват malloc перед любыми другими пользователями этого?Или есть способ загрузить мой код ранее, который я не нашел?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...