Программное прерывание

Программное прерывание является явным вызовом к подфункции (обычно работает функция системы). Это не имеет ничего общего с прерыванием (асинхронным прерыванием), хотя часто используется тот же распределитель переходов (таблица прерываний). Распространенные мнемоники:

Такие вызовы функций вызываются программами с помощью специальных архитектурно-зависимых команд. Для этого необходимо знать номер требуемой подфункции. Этот номер используется в качестве индекса в таблице переходов (в основном таблице векторов прерываний), которая содержит начальный адрес подпрограммы.

фоны

Первоначально использовался только в качестве удобного и переносного распределителя переходов ( MS-DOS ) - это позволяет избежать записи, зависящей от версии, непосредственно в код операционной системы (например JSR $EDB9) - этим вызовам функций в современных операционных системах были предоставлены дополнительные функции. С помощью этих команд возможны изменения контекста и задачи, которые нельзя (намеренно) реализовать с помощью классических команд. Таким образом, это можно INT 21hсмоделировать в MS-DOS с помощью классических команд (примерно 20), но уже не INT 80hтой, которая используется для вызова функций операционной системы в двоичных файлах Unix .

Эта технология позволяет использовать только защищенные операционные системы, поскольку изменение контекста операционной системы может происходить только в точно определенных точках.

Пример звонка (Unix, Intel i386)

Функция чтения POSIX (чтение данных из дескриптора файла в память) должна быть реализована:

    read ( int FileHandle, void* Buffer, unsigned int BufferLength ) ;

(Минимальная) реализация (в libc) выглядит так:

    read  proc
          push ebx
          push ecx
          push edx
          mov  ebx, [esp+16]    ; FileHandle
          mov  ecx, [esp+20]    ; Buffer
          mov  edx, [esp+24]    ; BufferLength
          mov  eax, 0003h       ; Funktionnummer für read
          int  80h
          pop  edx
          pop  ecx
          pop  ebx
          cmp  eax, -124        ; Werte von 0...0FFFFFF84h sind Rückgabewerte, -123...-1 sind (negierte) Fehlernummern
          jbe  .noError
          neg  eax              ; Aus Rückgabewerten -1...-123 werden die Fehlernummern 1...123
          mov  __errno, eax     ; Fehler in errno abspeichern
          mov  eax, -1
    .noError:
          ret
          end  proc

Лечение процессора и операционной системы

Команда INT 80hделает следующее:

  • Поскольку переход проходит через шлюз вызова, уровень приоритета изменяется с 3 (пользователь) на 0 ( ядро ),
  • затем процессор переключается со стека пространства пользователя на стек пространства ядра,
  • затем сохранил регистр флагов и
  • Наконец, происходит переход к адресу, хранящемуся в операционной системе.

Первое действие в ядре - сохранить и проверить аргументы:

  • Может ли процесс выполнять запись в область памяти между Buffer и Buffer + BufferLength-1?
    • если нет ⇒ EFAULT
  • Подходит ли FileHandle для этого процесса?
    • если нет ⇒ EBADF
  • Находится ли область памяти между Buffer и Buffer + BufferLength-1 в основной памяти?
  • ...

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

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

  • Получить адрес возврата из стека
  • Восстановить регистр флагов
  • Вернуться к стеку пользовательского пространства
  • Установите уровень приоритета обратно на 3

Смотри тоже