pidからcr3レジスタの値を取得する
概要
Ubuntu 64bit において,あるプロセスのプロセス ID からそのプロセスの CR3 レジスタの値を取得するカーネルモジュールを作成する. x86 の Linux では,仮想メモリはプロセス毎に独立し,プロセス毎にページテーブルが用意されている. それぞれのプロセスにおけるページウォークは,そのプロセスに対応する pgd を起点として行われる. この時の pgd の物理アドレスが cr3 レジスタに格納されている. プロセスのコンテキストスイッチ時には,cr3 レジスタの値を切り替えることで,プロセスの仮想アドレス空間を切り替えることができる. cr3 レジスタの値は,pgd の物理アドレスであるので,プロセス ID のように一意の識別子になりうる.
実装
uintptr_t pid_to_cr3(pid_t pid)
{
struct pid *task_pid = find_vpid(pid);
struct task_struct *task;
if (!task_pid)
return 0;
task = pid_task(task_pid, PIDTYPE_PID);
/* Ignore anonymous processes */
if (!task->mm)
return 0;
if (task->active_mm == NULL)
return 0;
uintptr_t cr3 = __pa(task->active_mm->pgd);
printk("cr3: %p\n", cr3);
/* success */
return cr3;
}
第一引数にユーザ空間におけるプロセス ID を受け取り,対応する task_struct 構造体を取得する. そして,task_struct 構造体から取得した pgd の値を物理アドレスに変換することで,cr3 レジスタの値を取得している.
参考
find_task_by_vpid を追ってみる - Linux の備忘録とか・・・(目次へ)
[Linux] Process ID (PID) から CR3 値を得る自作システムコール: 開発