バスエラーとは?

現在、x86 でバス エラーが発生することはまれであり、プロセッサが要求されたメモリ アクセスを試みることさえできない場合に発生します。通常は次のようになります。

  • アラインメント要件を満たさないアドレスを持つプロセッサ命令を使用する

セグメンテーション違反は、プロセスに属していないメモリにアクセスするときに発生します。これは非常に一般的であり、通常は次の結果です:

  • 割り当て解除されたものへのポインタを使用する
  • 初期化されていないため偽のポインタを使用しています。
  • null ポインターを使用する。
  • バッファのオーバーフロー。

PS:より正確に言うと、これは問題を引き起こすポインター自体を操作することではなく、ポインターが指すメモリーにアクセスすること (逆参照) です。


segfault は、アクセスが許可されていないメモリにアクセスしています。読み取り専用、権限がないなど...

バス エラーが、おそらく存在しないメモリにアクセスしようとしています。システムにとって意味のないアドレスを使用したか、その操作に対して間違った種類のアドレスを使用しました。


mmap 最小限の POSIX 7 の例

カーネルが SIGBUS を送信すると、「バス エラー」が発生します。

ftruncate が原因で生成される最小限の例 忘れていました:

#include <fcntl.h> /* O_ constants */
#include <unistd.h> /* ftruncate */
#include <sys/mman.h> /* mmap */

int main() {
    int fd;
    int *map;
    int size = sizeof(int);
    char *name = "/a";

    shm_unlink(name);
    fd = shm_open(name, O_RDWR | O_CREAT, (mode_t)0600);
    /* THIS is the cause of the problem. */
    /*ftruncate(fd, size);*/
    map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    /* This is what generates the SIGBUS. */
    *map = 0;
}

実行:

gcc -std=c99 main.c -lrt
./a.out

Ubuntu 14.04 でテスト済み。

POSIX は SIGBUS を記述しています として:

mmap 仕様には次のように記載されています:

そして shm_open サイズ0のオブジェクトを生成すると言っています:

*map = 0 で 割り当てられたオブジェクトの終わりを超えて触れています。

ARMv8 aarch64 でのアラインされていないスタック メモリ アクセス

これについては、バス エラーとは何ですか? で言及されています。ただし、ここではより再現性の高い例を提供します。

必要なのは、独立した aarch64 プログラムだけです:

.global _start
_start:
asm_main_after_prologue:
    /* misalign the stack out of 16-bit boundary */
    add sp, sp, #-4
    /* access the stack */
    ldr w0, [sp]

    /* exit syscall in case SIGBUS does not happen */
    mov x0, 0
    mov x8, 93
    svc 0

そのプログラムは、ThunderX2 サーバー マシンの Ubuntu 18.04 aarch64、Linux カーネル 4.15.0 で SIGBUS を発生させます。

残念ながら、QEMU v4.0.0 ユーザー モードでは再現できません。理由はわかりません。

この障害はオプションであり、SCTLR_ELx.SA によって制御されているようです。 そして SCTLR_EL1.SA0