Патч к ядру Linux: использование

From EjudgeWiki
Revision as of 05:08, 22 August 2008 by Cher (talk | contribs)

Навигация: Главная страница/Система ejudge/Патч к ядру Linux/Использование

В данном разделе описывается использование патча для ядер серии 2.6. Здесь описываются нискоуровневые интерфейсы, которые могут измениться (и изменяются) от версии к версии ядра. Поэтому рекомендуется использовать библиотеку reuse.

Включение безопасного режима работы процесса

Для включения безопасного режима работы используется системный вызов ptrace:

ptrace(0x4281, 0, 0, 0)

Здесь 0x4281 — «магическое» число - код запроса. Безопасный режим включается у текущего процесса. После включения безопасного режима процесс имеет право выполнить один системный вызов execve, то есть запустить на выполнение другую программу. Запускаемая программа будет работать в безопасном режиме, но уже не будет иметь право выполнять системный вызов exec.

При успешном завершении (то есть когда патч установлен в работающее ядро) системный вызов ptrace возвращает значение 0. Если патч не установлен, ptrace вернет значение -1, а переменная errno будет содержать код ошибки EINVAL.

Установка ограничения времени работы процесса в миллисекундах

Для установки ограничения времени работы процесса в миллисекундах используется системный вызов setrlimit со специальным кодом ресурса.

struct rlimit lim;
lim.rlim_cur = mtime; // устанавливаем ограничение mtime миллисекунд
lim.rlim_max = mtime; // устанавливаем ограничение mtime миллисекунд
setrlimit(RLIMIT_MCPU, &lim);

Константа RLIMIT_MCPU определена в заголовочных файлах исходных кодов ядра Linux после применения патча. Однако, эта константа не определена в пользовательских заголовочных файлах стандартной библиотеки. Поэтому вместо нее необходимо использовать численное значение, которое разное для разных версий ядра. Так, для ядер серии 2.4 RLIMIT_CPU равен 11, для ядер серии 2.6 до версии 2.6.25 RLIMIT_CPU равен 15, а начиная с версии 2.6.25 — 19.

Проверку версии ядра лучше всего проводить на этапе работы программы, проанализировав информацию, возвращаемую системным вызовом uname.

Контроль ошибки Memory Limit Exceeded

По умолчанию даже в безопасном режиме диагностирование ошибки Memory Limit Exceeded отключено. Поведение системы в ситуации превышения лимита памяти процессом не отличается от стандартного, то есть:

  • если лимит памяти превышен при запуске программы (например, слишком большая область глобальных переменных), процесс снимается с выполнения посылкой ему сигнала SIGKILL (для непривилегированного участника это отображается как Run-time Error);
  • если лимит памяти превышен при работе со стеком (например, вследствии слишком глубокой рекурсии или слишком большой области локальных переменных), процесс снимается с выполнения посылкой ему сигнала SIGSEGV (для непривилегированного участника это отображается как Run-time Error);
  • если лимит памяти превыщен при выполнении системного вызова выделения памяти, такого как sbrk или mmap, системный вызов завершается с соответствующим кодом ошибки, и дальнейшая обработка ошибки возлагается на работающую программу.

Для включения диагностики ошибки Memory Limit Exceeded требуется выполнить системный вызов ptrace:

ptrace(0x4280, 0, 0, 0)

Здесь 0x4280 — «магическое» число - код запроса. После включения режима диагностики ошибки Memory Limit Exceeded в ситуации превышения лимита памяти процессом в любой из трех ситуаций ему посылается сигнал SIGKILL, и устанавливается специальный флаг. Это значит, что при включенной диагностике ошибки Memory Limit Exceeded программа не имеет возможность отреагировать на исчерпание памяти в куче.

Значение флага ошибки Memory Limit Exceeded можно получить с помощью системных вызовов семейства wait*. В слове состояния процесса (параметр status) устанавливается бит 0x10000, проверить который можно следующим образом:

wait(&status);
if ((status & 0x10000)) {
  // Memory Limit Exceeded
  status &= 0xffff;
}


Контроль ошибки Security Violation