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

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

setrlimit(RLIMIT_DATA, r);

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

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

setrlimit(RLIMIT_AS, r)

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

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

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

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

Ответы [ 2 ]

5 голосов
/ 06 октября 2010

Основываясь на идее, используемой 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 во избежание проблем с безопасностью.


альтернативой использованию dlsym() будет использование опции компоновщика GNU --wrap symbol.

3 голосов
/ 06 октября 2010

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

#define malloc(bytes) limited_malloc(bytes)

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

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