ruby-trunk-changes r65551 - r65577

今日は MJIT のセキュリティ的考慮の強化や clang/gcc の Address Sanitizer/Memory Sanitizer 機能を利用するようにする変更などがありました。

nobu: r65551 2018-11-06 02:27:10 +0900

r65536 で環境変数 MJIT_SEARCH_BUILD_DIR で MJIT 用のヘッダ出力先ディレクトリの指定のチェックを厳格にしていましたが、相対パスだったり、ディレクトリでないパスなどそもそも指定が不正な時は単に警告を出して指定を無視してデフォルトのインストール先のパスを利用するようにして、MJIT 自体は有効にするようにしています。world writable なディレクトリなどセキュリティ的に問題のあるディレクトリが指定された時だけ MJIT 自体を無効にするようにしています。

svn: r65552 2018-11-06 02:27:12 +0900

version.h の日付更新。

normal: r65553 2018-11-06 07:56:57 +0900

rb_wait_for_single_fd() で ppoll(2) の前後で struct pollfd::revents を 0 クリアしていたところを消しています。うーんコミットログがよくわからないのですが ppoll(2) がクリアするはずなので不要ってことかな。

naruse: r65554 2018-11-06 08:06:50 +0900

Exception#cause に例外を capture する時に誤って throw などの例外以外の大域脱出? を捕捉すると SEGV する不具合を修正。 [ruby-core:89712] [Bug #15282]

svn: r65555 2018-11-06 08:06:58 +0900

r65554 のインデントのタブを空白に展開。

shyouhei: r65556 2018-11-06 10:36:20 +0900

.travis.yml の build matrix 用に YAML の alias 機能(っていうのかな)を使いシンプルに書くようにして、一部のテストは cron 型で trunk で1日1回だけ実行するようにしています。

shyouhei: r65557 2018-11-06 10:45:09 +0900

r65556 で allow_failure に -fsanitize=undefined を linker option につけたものを追加し忘れていたのを修正。

shyouhei: r65558 2018-11-06 11:57:28 +0900

gc.c で clang の静的解析によるメモリチェック機能を局所的に無効にするための attribute をつけるマクロ ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS を定義していたのを configure でチェックして定義するようにしています。

shyouhei: r65559 2018-11-06 12:06:33 +0900

.travis.yml に cron のみで起動するテストとして FIBER_USE_NATIVE=0 を指定してビルドするものを追加しています。

usa: r65560 2018-11-06 12:18:23 +0900

r65558 の ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS の定義でチェックが利用できない時の定義が古いままだったのを修正しています。

nobu: r65561 2018-11-06 12:32:57 +0900

darwin 環境では LDSHARED とは別に DLDSHARED というコマンドを指定する変数を定義して LIBRUBY_LDSHARED をこっちを使うようにしています。 LDSHARED は .bundle を作るもので DLDSHARED は .dylib を作るもの。これも MJIT 用かな?

nobu: r65562 2018-11-06 13:13:47 +0900

Makefile.in で mjit_config.h に MJIT_CC_COMMON を定義する時に MJIT_CC をそのままでなくフルパスに解決してから埋め込むようにして、PATH 上にコンパイラと同名のコマンドを差し込まれてもそっちを実行してしまわないようにしています。

nobu: r65563 2018-11-06 13:13:48 +0900

r65562 と類似で Makefile.in で MJIT 用ヘッダファイル生成時に MJIT_BUILD_DIR はマクロではなく変数として埋め込み、mjit.c では dlsym(3) を使ってアクセスするようにしています。これはなぜだろう……。static 変数だと攻撃しようとした時にいじりやすいとかかな。

shyouhei: r65564 2018-11-06 14:06:20 +0900

昔 r43047 で AddressSanitizer のチェックに gc.c の関数がひっかかるので導入してた NO_SANITIZE() というマクロを gc_mark_maybe() と is_pointer_to_heap() の宣言に利用しています。 [Bug #8680]

shyouhei: r65565 2018-11-06 14:07:54 +0900

r65564 の追加修正。コンパイラが対応していなかった時の NO_SANITIZE() の定義が空っぽになってしまっていたので、第2引数の宣言自体は残すようにしています。

nobu: r65566 2018-11-06 14:14:36 +0900

r65563 の MJIT_BUILD_DIR を変数にした変更を revert しています。

ko1: r65567 2018-11-06 15:36:51 +0900

RubyVM::InstructionSequence.load_from_binary で TracePoint のフックが有効な状態でバイナリフォーマットから ISeq をロードする時は、すぐに trace 有効版の命令に変更して TracePoint が有効になるようにしています。 [ruby-core:86626] [Bug #14702]

nobu: r65568 2018-11-06 16:03:24 +0900

r65562 の再修正。 MJIT_CC_COMMON の設定をフルパスに解決する時に MinGW では cygpath というコマンドを利用するようにしています。 cygpath は cygwinWindows のコマンドを shell から使う時のコマンドに変換するためのツールみたいです。

k0kubun: r65569 2018-11-06 16:22:25 +0900

r65275 で導入した inline cache や call cache を MJIT 用にコピーする機構で mjit_copy_job_handler() 等で job->finish_p を操作/参照する時に MJIT の mutex で排他かけるようにしています。 --jit つきのテスト時に SEGV が発生することがあったようです。

nobu: r65570 2018-11-06 16:28:11 +0900

r65562 や r65568 の続きで $MJIT_CC をフルパスに解決するのは cross compile 時は抑制するようにしています。あーなるほど。うーんしかし……。

k0kubun: r65571 2018-11-06 16:30:37 +0900

r65275 で導入した inline cache や call cache を MJIT 用にコピーする機構の copy_cache_from_main_thread() で main thread に実行させる遅延ジョブの登録を rb_postponed_job_register_one() を使ってたのを rb_postponed_job_register() を使うように変更しています。 rb_postponed_job_register_one() を使うことで重複してジョブが登録される可能性があって、どうも r65569 で修正しようとしていた SEGV はこれが原因だったっぽいですね。

k0kubun: r65572 2018-11-06 17:01:28 +0900

r65569 の続きで mjit_copy_job_handler() で job->finish_p を参照するための mutex の排他処理前に stop_worker_p のチェックを移動しています。こっちを先にチェックしないと mutex 自体も destroy されてるかもしれないからかな。

shyouhei: r65573 2018-11-06 19:06:07 +0900

sanitizer/asan_interface.h や sanitizer/msan_interface.h といった Address Sanitier, Memory Sanitizer のヘッダファイルがあれば導入して不正なメモリアクセスを検出するようにしています。 gc.c などでは普通じゃないメモリの触りかたをすることが多いので、poison_xxx() と unpoison_xxx() という関数群が導入されててこれで明示的にアドレスやメモリ領域を一時的に許可したりしています。

shyouhei: r65574 2018-11-06 19:19:55 +0900

rb_fiber_reset_root_local_storage() の引数を VALUE から rb_thread_t* に変更。呼び元で th->self を渡してたので単に th を渡すようにしています。

svn: r65575 2018-11-06 19:19:59 +0900

r65574 のインデントのタブを空白に展開。

shyouhei: r65576 2018-11-06 20:53:01 +0900

r65573 で導入した sanitizer のヘッダは MJIT の JIT コンパイル時には使わないように #ifndef MJIT_HEADER でくくっています。

nobu: r65577 2018-11-06 21:08:54 +0900

MJIT_CC のコンパイラコマンドをフルパスにするのは configure 時点でやっておくようにしています。