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;
}