Skip to content
__ukun edited this page Aug 7, 2017 · 4 revisions

Seccamp2017 D6 LSMから見た Linux カーネルのセキュリティ

ここは事前課題において一連の投稿をまとめたものになります。

すべて自分が後から参照しやすいように各章ごとに投稿をまとめてあります。

第1章:ユーザ空間でC言語プログラミングについて体験する。(1時間)

  1. ユーザ空間プログラムで Hello world. を実現する。
     →必要なパッケージのインストールができることを確認する。
      strace / ltrace で動作を追跡し、ライブラリ関数( printf fwrite )と
      システムコール( write )との差異を確認する。

  2. 無限ループやデッドロック状態を体験する。
     →マルチスレッド( pthread mutex )ではなくマルチプロセス( flock )を使用する。
      pidof でプロセスIDを確認し、 SIGKILL で強制終了できることを確認する。
       カーネル内はマルチスレッドなので本当はマルチスレッドの方がよい?
        でも、マルチスレッドな時点で苦労するのが目に見えているので、マルチプロセスで行く。

  3. NULL pointer deref でクラッシュさせる。
     →プロセスが終了するだけで済むことを確認する。

  4. 0除算でクラッシュさせる。
     →プロセスが終了するだけで済むことを確認する。
       この講義としては必須ではないが、簡単に確認できるので入れておく?

  5. スタック変数を大量に使う。
     →スタック変数を自由に使えることを知る。

  6. 連続したメモリを割り当てる。
     →連続したメモリを自由に割り当てられることを知る。

  7. メモリリークでクラッシュさせる。
     → OOM killer によりプロセスが強制終了するだけで済むことを確認する。

問題が起きたら SIGKILL で強制終了させることができるので、影響範囲を限定できる。
基本的にリソースはプロセスの終了により自動的に解放されるので、
リソースのリークが原因でシステム全体がダウンすることは無い。

第2章:カーネル空間ではいろいろと違うことを体験する。(2時間)

  1. カーネルモジュールで Hello world. を実現する。
     →必要なパッケージのインストールができることを確認する。
      module_init で printk() を呼ぶ。

  2. 無限ループや待ち状態を体験する。
     → SIGKILL で強制終了できないことを確認する。
      mutex_lock() と mutex_lock_killable() の差異について知る。
       module_init で double lock する?

  3. NULL pointer deref でクラッシュさせる。
     →システムがダウンしてしまうことを確認する。
       /proc/sys/kernel/panic_on_oops の設定に依存する。

  4. 0除算でクラッシュさせる。
     →システムがダウンしてしまうことを確認する。

  5. スタック変数を大量に使う。
     →スタック変数を自由に使えないことを知る。

  6. 連続したメモリを割り当てる。
     →連続したメモリを自由に割り当てられないことを知る。

  7. メモリリークでクラッシュさせる。
     →カーネル内でのメモリリークが危険なことを知る。
      ユーザ空間からカーネルメモリリーク攻撃される可能性の一例 keyctl OOM DoS
       多数の無実なプロセスを殺してしまう OOM killer 。

カーネルは究極のマルチスレッドプログラム。システムをシャットダウンまたは
再起動するまで動き続けるため、リソース管理が大変。いろいろな制約がある。
だから、ユーザ空間でできることはユーザ空間でやろう。ユーザ空間からの
攻撃とカーネル空間内のバグに注意しながら。

第3章: clamav を試す。(2時間)

  1. FUSE について知る。
     → clamfs を試す。 git からコンパイルする? tarball からコンパイルする?

  2. libclam のAPI呼び出しを使う。
     →APIを意識した練習をする。
      テンプレをベースに、ユーザ空間内でのやりとりの練習をする。

  3. 動作確認をする。
     →無害な検体を用意できると嬉しい。

準備完了。これからが本題です。

第4章:LSMから clamav を呼び出す。(5時間)

  1. AKARI について知る。
     →カーネルモジュールからLSMを呼び出すための方法。テンプレで済ませる。

  2. execve をフックする。
     →パス名の計算方法を知り、実行が要求されたプログラムのパス名を表示する。
      動的メモリ割り当てを使うには?

  3. 対話的に確認できるようにする。
     →ユーザ空間とのやり取りは結構面倒。時間がかかると思われる。

フックまでは事前学習で体験させておきたいので、ここまでを事前学習(10時間)で済ませる。
ここから先を当日の内容(4時間)として行う。

  1. LSMの歴史について知る。
     →LKM非対応化について。
      カーネルモジュールからLSMを使う AKARI の話。

  2. ユーザ空間のプログラムを書く。
     →カーネルからパス名を受け取り、API経由で clamd に渡し、
      結果を確認してからカーネルに返事をする。
       名前空間は扱わない。
      再帰呼び出しをどうする?
       execve だけなら気にしない?

  3. 動作確認をする。
     →無害な検体を用意できると嬉しい。

  4. 最新の話をする。
     ro_after_init の話について。
      vmsplice では SELinux を無効化できた。
     per task_struct blob の復活について。
     他のモジュールが提案されている話について。

  5. Q&A?