"ユーザー空間で見えているものは、すべて幻想である。現実は、割り込み命令とカーネルの向こうにある。"
現代のプログラミングでは、ファイル操作も画面出力も、すべて「ライブラリ」や「API」を通じて行われている。
しかし、その奥にある本質的な操作は、すべて
カーネルに対する「システムコール(System Call)」という儀式を経て実現されている。
この章では、アセンブリを用いて、
Linuxにおける「手書きシステムコール」実装の実例を通し、
人間とカーネルの最も根源的な接点を明らかにする。
システムコールとは何か?
ユーザー空間のプロセスは、
直接ハードウェアやリソースにアクセスすることはできない。
代わりに、OSカーネルに対して特権操作の“依頼”を行う。
これが、**システムコール(syscall)**である。
例:
write(fd, buffer, size)
open(path, flags)
exit(status)
これらは、実際には以下のようなフローで処理される:
- ユーザー空間でレジスタに引数をセット
- 特定の割り込みや命令(
int 0x80
,syscall
)を発行 - カーネル空間へ制御移譲
- カーネルが処理し、結果を返す
x86_64におけるシステムコール規約
Linuxの64bit環境では、syscall
命令と特定レジスタへの引数配置が必要。
引数位置 | 使用レジスタ |
---|---|
syscall番号 | rax |
第1引数 | rdi |
第2引数 | rsi |
第3引数 | rdx |
第4引数 | r10 |
第5引数 | r8 |
第6引数 | r9 |
戻り値 | rax |
このルールを知っていれば、ライブラリなしでも直接システムコールを発行できる。
例:write(1, message, 13) を手書きで行う
section .data
msg db "Hello, syscalls", 0xA
len equ $ - msg
section .text
global _start
_start:
mov rax, 1 ; syscall番号 1 = write
mov rdi, 1 ; fd = stdout
mov rsi, msg ; バッファのアドレス
mov rdx, len ; バイト数
syscall ; カーネルに呼び出し
; exit(0)
mov rax, 60 ; syscall番号 60 = exit
xor rdi, rdi ; exit code = 0
syscall
ビルドと実行:
nasm -f elf64 syscall.asm -o syscall.o
ld syscall.o -o syscall_demo
./syscall_demo
このプログラムは、Cライブラリなしでwrite()
を直叩きしている。
つまり、OSに最も近いレイヤーで「Hello, syscalls」と叫んでいる。
なぜ手書きするのか?
1. ランタイムの理解
普段呼んでいる関数が、
どのようにOSと対話しているかを正確に理解できる。
2. リンクレスなバイナリを作れる
libc
不要の超小型プログラムが構築できる。
これは、静的解析・攻撃回避・OS自作などに有効。
3. セキュリティ/逆アセンブル観点で必須の知識
マルウェア、シェルコード、ROPチェーンなどは、
この「手書きsyscall」で実装される。
つまり、最も純粋な形式の“設計”でもある。
他の代表的なシステムコール番号(x86_64)
機能 | syscall番号 |
---|---|
read |
0 |
write |
1 |
open |
2 |
close |
3 |
exit |
60 |
getpid |
39 |
execve |
59 |
ソース:/usr/include/x86_64-linux-gnu/asm/unistd_64.h
これらの知識があると、
任意のプログラムをシステムレベルで「再構築」できる。
syscall命令の裏側:なぜそれで「切り替わる」のか?
syscall
命令は:
- カーネルが用意した**MSR(Model-Specific Registers)**に従い
- CPUリングレベル(ユーザー: Ring 3 → カーネル: Ring 0)を移行
-
CS
,SS
,RSP
などが強制的に切り替わる
つまり、これは単なる関数呼び出しではなく、CPU特権の変更=世界の境界線なのだ。
結語:システムコールは設計者の祈りである
手書きのシステムコールは、
一見してプリミティブで、時代遅れに見えるかもしれない。
だがそこには:
- 制御を委ねるという信頼
- 知識で抽象を貫く力
- 世界に“直接”語りかける設計者の声
が宿っている。
"高級言語は世界を隠すが、システムコールは世界の境界を指し示す。設計者が世界を知ろうとするなら、最初の一声は、このsyscallであるべきだ。"