System Calls: Difference between revisions

m
Bot: Replace deprecated source tag with syntaxhighlight
[unchecked revision][unchecked revision]
m (Reverted edits by Kb (talk) to last revision by Mrvn)
m (Bot: Replace deprecated source tag with syntaxhighlight)
 
(2 intermediate revisions by 2 users not shown)
Line 10:
For example, on i386, the Linux kernel gets its arguments in <code>eax, ebx, ecx, edx, esi, edi, and ebp</code> in that order. The ABI however places all arguments in reverse order on the stack. Linux proceeds to construct a <code>pt_regs</code> structure on the stack and passes a pointer to it to a C function to handle the call itself. This can be simplified into something like this:
 
<sourcesyntaxhighlight lang="asm">
Int128Handler:
; already on stack: ss, sp, flags, cs, ip.
Line 37:
add esp, 4
iretd
</syntaxhighlight>
</source>
 
Many protected mode OSes use EAX to hold the function code. DOS uses the AX register to store the function code — AH for the service and AL for functions of the service, or AH for the functions if there are no services. For example, let's say you have read() and write(). The codes are 1 for read() and 2 for write() from the interrupt 0A9h (an arbitrary choice, possibly wrong). You can write
<sourcesyntaxhighlight lang="asm">
IntA9Handler:
CMP AH, 1
Line 55:
.done:
IRETD
</syntaxhighlight>
</source>
 
However, if all function codes are small contiguous numbers, a better option might be a function table, such as:
 
<sourcesyntaxhighlight lang="asm">
dispatch_syscall:
cmp eax, NR_syscalls
Line 67:
mov eax, -ENOSYS
ret
</syntaxhighlight>
</source>
 
Note that this assumes the syscall table to be NULL free. If there is a hole in the table, fill it with a pointer to a function returning an error code!
Line 98:
To use the gate, user-space code must use a far-call instruction. The offset will be ignored. Assuming the gate is the first entry in the GDT, segment 0x0b will have to be requested (offset 8 and RPL 3):
 
<sourcesyntaxhighlight lang="asm">
call far 0x0b:0
</syntaxhighlight>
</source>
 
In 64-bit mode, the descriptor size is doubled, with the high half of the handler address directly after the rest of the descriptor described above. Also, the argument count has to be zero, and the second DWORD of the second descriptor has to be all zeros. Otherwise, no changes.
Line 138:
 
==Security/safety implications==
Since the kernel is running at higher privilege than the user mode code calling it, it is imperative to check everything. This is not merely paranoia for fear of malicious programs, but also to protect your kernel from broken applications. It is therefore necessary to check all arguments for being in range, and all pointers for being actual user land pointers (note that Linux apparently fails to do this). The kernel can write anywhere, but you would not want a specially crafted <code>read()</code> system call to overwrite the credentials of some process with zeroes (thus giving it root access).
 
As for making sure that pointers are in range, checking if they point to user or kernel memory can be difficult to do efficiently unless you are writing a [[Higher Half Kernel]]. For checking all user space accesses for being valid, you can either check with your [[Page Frame Allocation|Virtual Memory Manager]] to see if the requested bytes are mapped, or else you can just access them and handle the resulting page faults. Linux switched to doing the latter from version 2.6 onwards.
Line 164:
* [http://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/x86-system-calls.html FreeBSD Developers' Handbook - System Calls] - Discusses System Calls in FreeBSD from the usermode perspective.
 
[[Category:System Calls]]
[[Category:OS theory]]