17行のCコードでMacのシステム全体をフリーズさせられることが出来る不具合がmacOS High Sierraで確認される。

スポンサーリンク

 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実行時にシステム全体をフリーズさせているのではないかというコメントが追加されていたのでチェックしてみました。

macOS freeze 17行 Cコード

Running as non root, yes! The OS is not completely frozen (I can still browse with Safari) but still fairly frozen.

[mac-support] cargo test hangs · Issue #70 · rbspy/rbspy

スポンサーリンク

17行のCコード

 この不具合はRubyプロファイラrbspyのissueで報告され、rbspyの開発者であるJulia Evansによると、適当なコマンド(例えば/usr/bin/true)をexec関数で実行した直後に”task_for_pid”でタスクのプロセスIDを取得しようとするとMac(High Sierra)がフリーズし操作できない状態になるそうで、

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をフリーズさせることが可能でした。

High Sierraのtask_for_pidバグを利用しmacOSをフリーズさせたところ

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

コメント

  1. 匿名 より:

    もうHigh Sierra取り消してSierraからやり直そうぜ

  2. 匿名 より:

    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.

  3. 匿名 より:

    どうしてそんなことが起きるの、ってバグはOS開発において稀によくある
    printf(“\t\t\b\b\b\b\b\b”);

  4. 匿名 より:

    SierraにHEIF画像対応をバックポートしてくれたらHigh Sierra捨てられるのに。

  5. 匿名 より:

    無限ループに指定なしのwait。fork、execに失敗してる時の処理もないし。
    普通に考えりゃ無限にプロセス起動させてればそりゃ死ぬよね。

    for抜いてやってみるかな。

    • 匿名 より:

      試してみたけど、El Capitanだとループしてキャパシティエラーでるけど、フリーズはしなかったし、High Sierra だとtask_for_pid直後にフリーズしてるから、forループはあまり関係ない気がするんですよね。

  6. 匿名 より:

    新年明けても止まらねぇなオイ!
    HAHAHA