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

From EjudgeWiki
(Включение безопасного режима работы процесса)
Line 1: Line 1:
Навигация: [[Main Page|Главная страница]]/[[Система ejudge]]/[[Патч к ядру Linux]]/[[Патч к ядру Linux: использование|использование]]
+
Навигация: [[Main Page|Главная страница]]/[[Система ejudge]]/[[Патч к ядру Linux]]/[[Патч к ядру Linux: использование|Использование]]
  
 
В данном разделе описывается использование патча для ядер серии 2.6. Здесь описываются нискоуровневые интерфейсы, которые могут измениться (и изменяются) от версии к версии ядра. Поэтому рекомендуется использовать библиотеку reuse.
 
В данном разделе описывается использование патча для ядер серии 2.6. Здесь описываются нискоуровневые интерфейсы, которые могут измениться (и изменяются) от версии к версии ядра. Поэтому рекомендуется использовать библиотеку reuse.
Line 15: Line 15:
  
 
=== Установка ограничения времени работы процесса в миллисекундах ===
 
=== Установка ограничения времени работы процесса в миллисекундах ===
 +
 +
Для установки ограничения времени работы процесса в миллисекундах используется системный вызов 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 ===
 +
 +
По умолчанию даже в безопасном режиме диагностирование ошибки 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 ===
 
=== Контроль ошибки Security Violation ===

Revision as of 05:08, 22 August 2008

Навигация: Главная страница/Система 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