17行のCコードでMacのシステム全体をフリーズさせられることが出来る不具合がmacOS High Sierraで確認されています。詳細は以下から。
先々週、「htopコマンドをmacOS High Sierraで利用すると、システム全体がフリーズしてしまう不具合がる」という記事を書きましたが、その後macOS 10.13.3がリリースされこの不具合が修正されているかを検証していたところ、この不具合がmacOS 10.13.3でも修正されていないことが確認でき、加えてhtopのissueを確認したところ、macOS High Sierraには潜在的な(kernel bug)が存在し、これがhtop実行時にシステム全体をフリーズさせているのではないかというコメントが追加されていたのでチェックしてみました。
Running as non root, yes! The OS is not completely frozen (I can still browse with Safari) but still fairly frozen.
17行のCコード
この不具合はRubyプロファイラ「rbspy」のissueで報告され、rbspyの開発者であるJulia Evansによると、適当なコマンド(例えば/usr/bin/true)をexec関数で実行した直後に”task_for_pid”でタスクのプロセスIDを取得しようとするとMac(High Sierra)がフリーズし操作できない状態になるそうで、
i think i found a mac kernel bug? https://t.co/mQ1W1omH9N
— 🔎Julia Evans🔍 (@b0rk) 2018年1月28日
A 17-line C program that freezes (parts of) my Mac
@parkr was incredibly helpful and managed to narrow down the problem to right before calling the task_for_pid Mach function. Since task_for_pid seemed to be the issue, I worked on reproducing the issue in a small C program.
Here’s the program that shows the bug. It runs in a loop because it’s a bit race-y and sometimes it needs to try 10 times before it’ll freeze.I think I found a Mac kernel bug? – Julia Evans
Evansさんが公開した17行のCコード(PoC)を利用し試してみましたが、実際に非rootユーザーでも以下の様に“freeze-mac.c”をコンパイルし実行するだけで、Macをフリーズさせることが可能でした。
git clone https://gist.github.com/16c1ea69352a81658d6d8e9c5a289f2a.git cd 16c1ea69352a81658d6d8e9c5a289f2a cc -o freeze-mac freeze-mac.c ./freeze-mac # try running `ps` / starting Activity Monitor, they don't work!
この不具合はHigh Sierra以前のmacOS 10.12.x Sierraなどでは再現できず、macOSのシステムがフリーズするだけで、10行のCコードでOS X 10.10 YosemiteやiOS 8をカーネルパニックにする事が出来る「KernelPanic-10LOC」以上に問題になることはないと思いますが、Evansさんは回避策としてexecの直後には”task_for_pid”を実行しないように警告しています。
#include <mach/mach_init.h> #include <mach/port.h> #include <sys/wait.h> #include <unistd.h> #include <stdio.h> int main() { for (;;) { pid_t pid = fork(); if (pid == 0) execv("/usr/bin/true", NULL); mach_port_name_t task = MACH_PORT_NULL; task_for_pid(mach_task_self(), pid, &task); printf("Ran task_for_pid\n"); int wait_status; wait(&wait_status); } }
I have a workaround!
This is weird and I don’t really understand the underlying kernel issue. Anyway, I have a workaround for this – don’t run task_for_pid on processes immediately after exec’ing them, instead sleep for a few milliseconds first. So hopefully with this new knowledge I can get rbspy to work on Mac without freezing users’ computers.I think I found a Mac kernel bug? – Julia Evans
- I think I found a Mac kernel bug? – Julia Evans
- Htop on macOS High Sierra · Issue #682 · hishamhm/htop – GitHub
コメント
もうHigh Sierra取り消してSierraからやり直そうぜ
macOS 10.13でObj-Cのforkとexecが変更されたことが関係あるんですかね?
ttp://sealiesoftware.com/blog/archive/2017/6/5/Objective-C_and_fork_in_macOS_1013.html
The rules for using Objective-C between fork() and exec() have changed in macOS 10.13. Incorrect code that happened to work most of the time in the past may now fail. Some workarounds are available.
どうしてそんなことが起きるの、ってバグはOS開発において稀によくある
printf(“\t\t\b\b\b\b\b\b”);
SierraにHEIF画像対応をバックポートしてくれたらHigh Sierra捨てられるのに。
無限ループに指定なしのwait。fork、execに失敗してる時の処理もないし。
普通に考えりゃ無限にプロセス起動させてればそりゃ死ぬよね。
for抜いてやってみるかな。
試してみたけど、El Capitanだとループしてキャパシティエラーでるけど、フリーズはしなかったし、High Sierra だとtask_for_pid直後にフリーズしてるから、forループはあまり関係ない気がするんですよね。
新年明けても止まらねぇなオイ!
HAHAHA