Программное прерывание
Программное прерывание является явным вызовом к подфункции (обычно работает функция системы). Это не имеет ничего общего с прерыванием (асинхронным прерыванием), хотя часто используется тот же распределитель переходов (таблица прерываний). Распространенные мнемоники:
- INT xxh ( прерывание с Intel 8086 )
- SC xxh ( системный вызов для Zilog Z8000 )
- TRAP xh ( Ловушка с Motorola 68000 )
- CALL 0005h ( CP / M-80 , Intel 8080 / Zilog Z80 не имеет специальной команды для этого)
Такие вызовы функций вызываются программами с помощью специальных архитектурно-зависимых команд. Для этого необходимо знать номер требуемой подфункции. Этот номер используется в качестве индекса в таблице переходов (в основном таблице векторов прерываний), которая содержит начальный адрес подпрограммы.
фоны
Первоначально использовался только в качестве удобного и переносного распределителя переходов ( 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