Difference between revisions of "Патч к ядру Linux: использование"
(→Включение безопасного режима работы процесса) |
|||
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.
Contents
Включение безопасного режима работы процесса
Для включения безопасного режима работы используется системный вызов 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; }