Home | Notifications | New Note | Local | Federated | Search | Logout

Fadis@fadis@mstdn.jp

組み込みからHPCまで、計算機が好きだ。
コンピュータグラフィクス本書いてます: https://techbookfest.org/organization/5465190594248704
bluesky : https://fadis0.bsky.social/
X: https://x.com/fadis_
mixi2: @fadis
発表とか : https://speakerdeck.com/fadis
動画とか : https://www.youtube.com/@fadis_
ほしい物リスト: https://www.amazon.co.jp/hz/wishlist/ls/2H9VDVP96XBXV/ Joined: 2026-10-10 22:06:35 5 notes, 0 following, 0 followers

Fadis@fadis@mstdn.jp (2026-10-10 22:06:34) 関数の型情報をハッシュにした物をターゲットの命令列を生成するバックエンドまで持ってこないといけない為、変更はフロントエンド、RTL、バックエンドの3層全てにおよび、テスト込みで6600行程度の変更になったらしい。このkcfiの実装はx86_64、aarch64、arm、risc-vをサポートしている

Fadis@fadis@mstdn.jp (2026-10-10 22:06:24) CFIにはいくつかの実現方法があるが、Linuxカーネルのような低レイヤーで使いやすいように作られたのがclangのkcfi。kcfiは関数の先頭の命令の前に関数の型のハッシュ値を埋め込む。間接関数呼び出し時は呼び出す関数の型のハッシュ値と、ジャンプ先の前に書かれたハッシュ値が一致するかを確認する。
これは意図しない関数の呼び出しを完全に防ぐ物ではないが、関数の型は多様なので呼べる関数の種類はごく僅かになる。Linuxカーネルは以前からclangでビルドする場合に限りkcfiを仕込んでビルドする事ができた。何故clang限定だったかというとgccにはkcfiの実装が無かったから。
そこでKees Cook氏はclangのkcfiと同じように機能するkcfiをgccにも実装して、gccでビルドするLinuxでもcfiを使えるようにした。clangでビルドしたバイナリとgccでビルドしたバイナリが互いの関数を呼べるようにgccのkcfiにはgccに実装があり、clangでもkcfiのハッシュに指定可能なFNV-1aが選ばれた

Fadis@fadis@mstdn.jp (2026-10-10 22:06:03) これでリターンアドレスの書き換えで任意のコードを実行する事はできなくなるが、スタックやヒープ上に関数ポインタが置かれていて、それが特定の条件で呼び出される場合(間接関数呼び出し)、攻撃者は関数ポインタのアドレスを書き換える事でROPと同じようにCall-oriented programming(COP)ができる。
そこでIntel Control-Flow Enforcement Technology(略してCET)では関数の先頭にendbr命令を置く。endbr自体は何もしない命令だが、callやjmpで飛んだ先の最初の命令がendbrでない場合、CPUは例外を発生させる。これによって関数は必ず先頭から実行しなければならなくなり、COPが難しくなる。
CETでCOPは難しくなるが、攻撃者が欲しい関数そのものが実行可能バイナリの中に転がっている場合、攻撃者は間接関数呼び出しでその関数を呼ばせるだけで攻撃が成立する。そこで間接関数呼び出しにもう一段階縛りを設けて攻撃を困難にするのがCFI

Fadis@fadis@mstdn.jp (2026-10-10 22:05:40) 太古の昔、攻撃者はスタックを壊せるバグを起点としてメモリ上に実行したいコードを置いてスタック上のリターンアドレスを書き換える事でそのコードを実行させる事で任意のコードを実行していた。こうした攻撃を防ぐために現代のOSの下では殆どのメモリは「書けるけど実行できない」か「実行できるけど書けない」設定がなされる。
こうした設定がなされていても、リターンアドレスを既存のコードの好きな位置に書き換える事は出来るため、既存の実行可能バイナリの一部を継ぎ接ぎして任意のコードを実行するReturn-oriented programming(略してROP)が行われるようになった。
ROPを防ぐために現代のx86_64 CPUにはShadow Stackが備わっている。Shadow Stackは関数呼び出し時にスタックに積んだリターンアドレスを書き換え不能な別のスタックにも積んでおき、return時に2つのスタックの値が一致しているかをチェックする。

Fadis@fadis@mstdn.jp (2026-10-10 22:05:15) Adding kernel control-flow-integrity checking to GCC : gccでkcfiを使えるようにしたKees Cook氏によるgccのkcfiについての発表のまとめ記事。Control-flow integrity略してCFIは間接関数呼び出しに細工をして意図しない関数の呼び出しを防ぐ為の仕組み https://lwn.net/Articles/1098670/