ptrace
ptrace(2)システムコール。あるプロセス(トレーサー)が別のプロセス(トレーシー)のメモリ・レジスタを観察・変更し、シグナル配送のたびに実行を止めて制御を奪えるようにする仕組み。gdbのようなデバッガやstraceのようなシステムコールトレーサーの基盤になっている。 #linux #unix #security
基本的な使い方
トレーシー側が自らPTRACE_TRACEMEを呼んでからトレーサーにexecされるか、トレーサー側が既存のプロセスにPTRACE_ATTACH/PTRACE_SEIZEでアタッチするかの2通りで開始する。トレース中、トレーシーはシグナルを受け取るたびに停止し、トレーサーはwaitpid(2)でそれを検知して、レジスタ・メモリの読み書き(PTRACE_PEEKTEXT/PTRACE_GETREGSなど)や、シグナルの差し替え・システムコールの結果改変を行える。
アクセス制御
PTRACE_ATTACHにはCAP_SYS_PTRACEか、対象プロセスへシグナルを送れる権限(≒同一ユーザーであること)が必要。加えて多くのLinuxディストリビューションではYama LSMのptrace_scopeによって、デフォルトでも「親子関係にあるプロセスのみアタッチ可能」のようにさらに制限されている。
setuid/setgidとの非交差設計
ptraceとsetuid/setgidは、意図的に交わらないよう設計されている。
- トレースされているプロセスが
execve(2)でsetuid/setgidプログラムを実行しても、実効UID/GIDの昇格は行われない(詳細と実験での観察はptraceされているプロセスはsetuidの昇格が無効化される) - 逆に、いったんsetuid/setgidで昇格したプロセスはptraceの対象にできない
これは、トレーサー側がトレーシーのメモリ・実行状態を自由に操作できるというptraceの強力さゆえの制約。もし昇格後もトレース可能だったり、トレース中に昇格できてしまうと、非特権プロセスがptrace経由でroot権限のプロセスを乗っ取れてしまい、setuidによる権限分離が意味を失う。
Linuxの権限分離・権限昇格の仕組みの中での位置づけ
setuid / setgidとの非交差設計の具体的な観測はptraceされているプロセスはsetuidの昇格が無効化される、ptrace自体をさらに制限するYama LSMもあわせて参照。
出典
man 2 ptraceman 2 execve