Software interrupt

from Wikipedia, the free encyclopedia

A software interrupt is an explicit call to a sub-function (usually an operating system function). It has nothing to do with an interrupt (asynchronous interruption), although the same jump distributor (interrupt table) is often used. Common mnemonics are:

Such function calls are called by programs with the help of special architecture-dependent commands. To do this, the number for the required sub-function must be known. This number is used as an index in a jump table (mostly interrupt vector table) which contains the start address of the subroutine.

backgrounds

Originally only used as a convenient and portable jump distributor ( MS-DOS ) - this avoids version-dependent entries directly into the operating system code (e.g. JSR $EDB9) - these function calls have been given additional functions in modern operating systems. With these commands, context and task changes are possible that cannot (intentionally) be implemented with classic commands. So that can be INT 21hsimulated under MS-DOS using classic commands (approx. 20), but no longer INT 80hthe one used to call operating system functions in Unix binaries.

This technology only enables protected operating systems, since the change to the context of the operating system can only take place at precisely defined points.

Example for a call (Unix, Intel i386)

The POSIX function read (reading data from a filehandle into the memory) is to be implemented:

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

The (minimal) implementation (in libc) looks like this:

    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

Treatment of the processor and operating system

The command INT 80hdoes the following:

  • Since the jump goes through a call gate, the priority level changes from 3 (user) to 0 ( kernel ),
  • then the processor switches from the user space stack to the kernel space stack,
  • then saved the flag register and
  • Finally, there is a jump to an address stored by the operating system.

The first action in the kernel is to save and test the arguments:

  • Can the process write to the memory area between Buffer and Buffer + BufferLength-1?
    • if not ⇒ EFAULT
  • Is the FileHandle valid for this process?
    • if not ⇒ EBADF
  • Is the memory area between Buffer and Buffer + BufferLength-1 in main memory?
  • ...

An inadequate test of the arguments was still common in the early to mid-1990s. Calling system functions with purely random values ​​was enough to crash operating systems, the crashme test program was able to demonstrate this impressively. Nowadays, every operating system is orders of magnitude more resistant to such attacks. Attacks are no longer possible with random values; sophisticated scenarios are necessary for this.

In the end, the kernel has processed the function call and returns IRETcontrol to the program. The return is made again via a call gate.

  • Get return address from the stack
  • Reconstruct flag register
  • Switch back to the userspace stack
  • Set the priority level back to 3

See also