web-dev-qa-db-ja.com

アセンブリファイルがプロジェクトに含まれている場合のmmapからの予期しない実行権限

これで頭を壁にぶつけています。

私のプロジェクトでは、mmapでメモリを割り当てているときに、マッピング(/proc/self/maps)が読み取り可能で実行可能な領域であることを示していますにもかかわらず読み取り可能なメモリのみを要求しました。

Strace(見栄えがよかった)と他のデバッグを調べた後、この奇妙な問題を回避しているように見える唯一のものを特定することができました:プロジェクトからアセンブリファイルを削除し、純粋なCのみを残します(何?!)

ここに私の奇妙な例が​​あります。Ubunbtu19.04とデフォルトのgccで作業しています。

ASMファイル(空)を使用してターゲット実行可能ファイルをコンパイルすると、mmapは読み取り可能で実行可能な領域を返します。それなしでビルドすると、正しく動作します。例に埋め込んだ/proc/self/mapsの出力を参照してください。

example.c

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>

int main()
{
    void* p;
    p = mmap(NULL, 8192,PROT_READ,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);

    {
        FILE *f;
        char line[512], s_search[17];
        snprintf(s_search,16,"%lx",(long)p);
        f = fopen("/proc/self/maps","r");
        while (fgets(line,512,f))
        {
            if (strstr(line,s_search)) fputs(line,stderr);
        }

        fclose(f);
    }

    return 0;
}

example.s:空のファイルです!

出力

ASM付属バージョン

VirtualBox:~/mechanics/build$ gcc example.c example.s -o example && ./example
7f78d6e08000-7f78d6e0a000 r-xp 00000000 00:00 0 

ASM付属バージョンなし

VirtualBox:~/mechanics/build$ gcc example.c -o example && ./example
7f1569296000-7f1569298000 r--p 00000000 00:00 0 
94
Ben Hirschberg

LinuxにはREAD_IMPLIES_EXECと呼ばれる 実行ドメイン があり、PROT_READで割り当てられたすべてのページにPROT_EXECも与えられます。 。このプログラムは、それが有効になっているかどうかを示します。

#include <stdio.h>
#include <sys/personality.h>

int main(void) {
    printf("Read-implies-exec is %s\n", personality(0xffffffff) & READ_IMPLIES_EXEC ? "true" : "false");
    return 0;
}

空の.sファイルと一緒にコンパイルすると、有効になっていることがわかりますが、ファイルがない場合は無効になります。この の初期値は、バイナリ のELFメタ情報から取得されます。 readelf -Wl exampleを実行します。空の.sファイルなしでコンパイルすると、次の行が表示されます。

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10

ただし、これをコンパイルすると、次のようになります。

  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RWE 0x10

RWEの代わりにRWに注意してください。これは、リンカは、アセンブリファイルにread-implies-execが必要であると明示的に指示されていない限り、アセンブリファイルにread-implies-execが必要であると想定しているためです。 。 GCCがコンパイルするAssemblyファイルは、次の行を使用して、これを必要としないことを示しています(-Sでコンパイルすると、これが表示されます)。

        .section        .note.GNU-stack,"",@progbits

その行をexample.sに入れると、リンカにそれも必要ないことを伝え、プログラムは期待どおりに動作します。

GNU固有のセクションディレクティブバリアントを使用してアセンブリファイルを変更する代わりに、アセンブリファイルをビルドするためのコマンドラインに-Wa,--noexecstackを追加できます。たとえば、muslのconfigureでどのように実行するかを参照してください。

https://git.musl-libc.org/cgit/musl/commit/configure?id=adefe830dd376be386df5650a09c313c483adf1a

少なくとも統合アセンブラを備えたclangのいくつかのバージョンでは、--noexecstack-Waなし)として渡す必要があるため、configureスクリプトはおそらく両方をチェックし、どちらが受け入れられるかを確認する必要があります。

リンク時に(LDFLAGSで)-Wl,-z,noexecstackを使用して同じ結果を取得することもできます。これの欠点は、プロジェクトが他のソフトウェアで使用するときに静的(.a)ライブラリファイルを生成しても助けにならないことです。これは、他のプログラムで使用するときにリンク時オプションを制御しないためです。