Подтвердить что ты не робот

Как я могу ограничить память, полученную с помощью `malloc()` без ограничения стека?

Я пытаюсь заставить код студента работать с распределением и перетащить мою тестовую машину на остановку. Я пробовал

setrlimit(RLIMIT_DATA, r);

где r - структура, удерживающая пределы. Но, к сожалению, хотя этот предел останавливает выделение brk и sbrk, библиотека C просто терпит неудачу до mmap и сохраняет право на выделение.

Я также пробовал

setrlimit(RLIMIT_AS, r)

и это останавливает процесс на своих дорожках, но это средство слишком тяжелое: невозможно восстановить процесс из ошибки ENOMEM, потому что нет места стека для вызовов, которые код создает при встрече с NULL значение, возвращаемое из malloc().

У меня ограниченный контроль над двоичными файлами, поэтому, если это возможно сделать с системным вызовом, я бы предпочел это. Но мне нужно какое-то средство укупорки, не разрушая способность процесса к восстановлению. У кого-нибудь есть предложения?

ОБНОВЛЕНИЕ. Я нашел что-то под названием failmalloc, но он не очень сложный, и хотя я могу вызвать с ним сбой, Я всегда получаю segfault, который gdb не может диагностировать.

ДАЛЬНЕЙШЕЕ ОБНОВЛЕНИЕ. Я обнаружил, что setrlimit(RLIMIT_AS, r), похоже, выполняет задание, которое я хочу, по крайней мере, в некоторых случаях: segfaults, которые произошли после этого, были вызваны ошибкой в ​​несвязанном модуле. Если кто-то не придумает что-то интересное (или повод оставить вопрос), я, вероятно, удалю вопрос.

4b9b3361

Ответ 1

Основываясь на идее, используемой failmalloc, вы можете использовать LD_PRELOAD * переменная среды и интерполяция функций, чтобы создать обертку вокруг malloc() и наложить там какие-либо ограничения.

Вам нужно будет динамически загрузить указатель на исходный malloc() с помощью dlsym(). Вы не можете напрямую вызывать исходный malloc() из оболочки, потому что он будет интерпретироваться как рекурсивный вызов самой оболочки.

#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>

void * malloc(size_t size)
{
   static void * (*func)(size_t) = NULL;
   void * ret;

   if (!func)
   {
      /* get reference to original (libc provided) malloc */
      func = (void *(*)(size_t)) dlsym(RTLD_NEXT, "malloc");
   }

   /* impose any necessary restrictions before calling malloc */
   ...

   /* call original malloc */
   ret = func(size);

   /* impose any necessary restrictions after calling malloc */
   ...

   return ret;
}

* Обратите внимание, что LD_PRELOAD должен указывать полный путь к библиотеке промежуточных элементов, а этот интерполятор библиотеки отключен для программ setuid, чтобы предотвратить проблемы безопасности.


An альтернатива для использования dlsym() будет использовать GNU linker --wrap symbol.

Ответ 2

Можете ли вы наложить макрос на ничего не подозревающих студентов?: -)

#define malloc(bytes) limited_malloc(bytes)

а также определение для limited_malloc, которое ограничивает то, что можно сделать.