Tamiz Uddin

Originally published on tamiz.pro.

はじめに

GhostLock脆弱性(CVE-2023-1228)は、2008年までさかのぼるLinuxカーネルにおけるスタックUse-After-Free(UAF)欠陥を明らかにしました。この15年前のバグは、メモリ安全性とカーネル開発における重大な課題を浮き彫りにします。そのメカニズムを理解することは、セキュアなシステムプログラミングにとって重要な教訓となります。

スタックUse-After-Freeとは?

Use-After-Freeとは、ソフトウェアが参照先のメモリが解放された後、そのメモリポインタを使い続けるときに発生します。スタック上では、これが特に危険になる理由は次のとおりです。

  1. スタックメモリはすぐに再利用される
  2. 関数リターンポインタが近くに存在することが多い
  3. 攻撃者は制御フロー構造を上書きできる
// Simplified UAF example
void vulnerable_function() {
    char *ptr = malloc(100);
    free(ptr);
    // Vulnerability window
    strcpy(ptr, "exploit"); // Use after free
}

Enter fullscreen mode Exit fullscreen mode

GhostLockの技術的分析

この脆弱性はLinuxのtty_ldisc構造体処理に存在していました。以下が攻撃の連鎖です。

  1. 初期化: TTSL_DEFAULTディシプリンでtty構造体を割り当てる
  2. 二重解放: tty_ldisc参照カウントの競合状態を誘発する
  3. スタックピボット: 解放されたスタックポインタ経由でリターンアドレスを上書きする
  4. 権限昇格: カーネル権限で任意のコードを実行する

メモリタイムライン

Stack Layout Before Free:
[refcount] -> 2
[tty_disc] -> TTY_LDISC

Race Window:
Thread 1: decrement refcount to 0
Thread 2: use_discipline()

Stack Layout After Free:
[refcount] -> 0 (freed)
[tty_disc] -> attacker-controlled data

Enter fullscreen mode Exit fullscreen mode

攻撃パターン

攻撃者はこの脆弱性を利用して以下を行いました。

  • カーネル制御構造を上書き
  • ユーザー空間とカーネル空間の競合状態を作成
  • ガジェットチェインによりSMEP/SMEP保護をバイパス
; x86_64 ROP gadget example
pop rdi; ret
mov eax, 1; int 0x80
; Used to bypass kernel protections

Enter fullscreen mode Exit fullscreen mode

緩和策

Linuxはこの脆弱性を以下により修正しました。

  1. 参照カウントの修正
// Before
ldisc_put(ldisc);

// After
atomic_dec_and_lock(&ldisc->users, &ldisc->lock);

Enter fullscreen mode Exit fullscreen mode

  1. スタックカナリアの改善(5.10カーネルで導入)
  2. KASAN(Kernel Address Sanitizer)によるランタイム検出

開発者への教訓

  1. カーネルモジュール開発では常に参照カウントを検証する
  2. ユーザースペースのテストではValgrindやAddressSanitizerなどのツールを使用する
  3. 競合状態に対する適切なロックメカニズムを実装する
  4. Linux Kernel Self Protection Project(LKSP)のガイドラインに従う

結論

GhostLockは、重要システムにおけるメモリ安全性問題の長期的なリスクを示しています。これらのパターンを研究することで、開発者はより強固な防御的プログラミングプラクティスを実装できます。静的解析ツール、ランタイム保護、徹底したコードレビューの組み合わせは、セキュアなカーネル開発に不可欠です。