Implement a WHOAMI system call
Intuitive implementation of system calls + intuitive ideas ...
The user program calls WhoAmI, a string "Systemcall" is placed in the operating system (loaded at System boot), removed to print, what is the problem?
- Do not arbitrarily call the data, not random jmp.
- You can see the root password, you can modify it ...
- You can see the contents of someone else's word through video memory ...
address: |
Main () {WhoAmI ();} |
User program |
。。。 |
WhoAmI () { printf (100, 8); } |
Kernel, all in memory, this memory is not all I buy it ... |
100: |
"Systemcall" |
Kernel (user) state, kernel (user)
Isolate the kernel program from the user program !!!
Differentiate between kernel state and user state : One processor "Hardware Design"
- the kernel state can access any data, the user state cannot access the kernel data
- For the instruction jump is also the same implementation of the isolation ...
Hardware provides a "way to actively enter the kernel"
For Intel x86, that is the interrupt instruction int
- The int instruction will change the CPL in CS to 0, "into the kernel"(at this point, cpl=3 and Dpl=0)
- This is the only way that the user program initiates the call to kernel code
- The core of the system call:
(1) The user program contains a section of code that contains an int directive
(2) operating system write interrupt processing , get the number of the program you want to tune
(3) The operating system executes the corresponding code according to the number
Implementation of system calls
Finally expands into the code that contains the INT directive ...
#include <unistd.h> _syscall3 (int, write, int, FD, const char *BUF, off_t, Count) |
In the LINUX/LIB/WRITE.C |
#define _SYSCALL3 (type, name, ...) type name (...) \ {__asm__ ("int 0x80": "=a" (__res) ...} |
In the Linux/include/unistd.h |
Implementation details of Linux system calls!
Complete the story about write ...
In Linux/include/unistd.h, _syscall3 indicates that there are 3 parameters
#define _SYSCALL3 (type,name,atype,a,btype,b,ctype,c) \
Type name (Atype A, btype B, CType C) \
{Long __res;\
__asm__ volatile ("int 0x80": "=a" (__res): "" (__nr_# #name),
"B" ((long) (a)), "C" ((long) (b)), "D" ((long) (c))); if (__res>=0) return
(type) __res; Errno=-__res; return-1;}
Obviously, __nr_write is the system call number, placed in the EAX
In the Linux/include/unistd.h
#define __NR_WRITE 4 //A stack of consecutive positive integers (array subscript, function table index )
EAX also stores the return value, EBX, ECX, edx storage 3 parameters
int 0x80 Interrupt Handling
void Sched_init (void)
{ set_system_gate (0x80,&system_call); }
Obviously, Set_system_gate is used to set 0x80
In the Linux/include/asm/system.h
#define SET_SYSTEM_GATE (n, addr) \
_set_gate (&IDT[N],15,3,ADDR); IDT is the interrupt vector table base Address
#define _set_gate (gate_addr, type, DPL, addr) \
__asm__ ("MOVW%%dx,%%ax\n\t" "MOVW%0,%%dx\n\t" \
"movl%%eax,%1\n\t" "movl%%edx,%2": \
: "I" ((short) (0x8000+ (dpl<<13) +type<<8)), "O" (* (\ (\
char*) (GATE_ADDR)), "O" (* (4+ (char*) (GATE_ADDR))), \
"D" ((char*) (addr), "a" (0x00080000))
Interrupt handler: System_call
In Linux/kernel/system_call.s
nr_system_calls=72
. Globl _system_call
_system_call:cmpl $nr _system_calls-1,%eax //eax is the system call number stored in the
JA bad_sys_call
Push%ds push%es push%FS
PUSHL%edx pushl%ecx pushl%ebx //Parameters of the call
MOVL $0x10,%edx mov%dx,%ds mov%dx,%es//kernel data
MOVL $0x17,%edx mov%dx,%fs //fs can find user data
Call _sys_call_table (,%eax,4) //a (,%eax,4) =a+4*eax
PUSHL%eax//return value stack, reserved for Ret_from_sys_call
...//other code
Ret_from_sys_call: popl%eax, other pops, Iret
_sys_call_table+4*%eax is the corresponding system call handler function entry
_sys_call_table
Call _sys_call_table (,%eax,4) is call sys_write // eax=4, function entry address length is also 4
[NO000036] Operating system operating systems call implementation System_call