[解決済み] プロジェクトにアセンブリファイルが含まれている場合、mmapから予期しない実行許可が出ることがあります。
質問
この件で壁に頭を打ち付けています。
私のプロジェクトでは、メモリ割り当てを
mmap
でメモリを確保する場合、マッピング (
/proc/self/maps
) は、それが読み取り可能で実行可能な領域であることを示しています。
とはいえ
読み出し可能なメモリのみを要求しました。
strace (これは良さそうでした) と他のデバッグを調べた後、この奇妙な問題を回避できそうな唯一のものを特定できました。プロジェクトからアセンブリ ファイルを削除して、純粋な C のみを残すことです (何だと!?)。
私は Ubunbtu 19.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;
}
例 : 空のファイルです!
出力
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
どのように解決するのですか?
Linuxでは
実行領域
と呼ばれる
READ_IMPLIES_EXEC
で割り当てられたすべてのページが
PROT_READ
で割り当てられたすべてのページにも
PROT_EXEC
. 古い Linux カーネル
はこれを使用していました。
と同じものを使っていた実行ファイルに対して
gcc -z execstack
. このプログラムは、それが自分自身で有効になっているかどうかを表示します。
#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がコンパイルするアセンブリファイルは、この行で、これが不要であることを伝えます(これは
-S
):
.section .note.GNU-stack,"",@progbits
デフォルトのセクションパーミッションには、e
x
ec が含まれます。 ELF の部分を参照してください。
.section
ドキュメント
は、"flags" と @attributes の意味についてです。
(のような別のセクションに切り替えることを忘れないでください。
.text
または
.data
その後に
.section
ディレクティブの後、もしあなたの
.s
に依存していたのであれば
.text
に依存していたからです)。
その行を
example.s
(そして他のすべての
.s
ファイル)。 その存在は
.note.GNU-stack
セクションの存在は、このオブジェクトファイルが実行可能なスタックに依存しないことをリンカーに伝える役割を果たします。
RW
の代わりに
RWE
の上に
GNU_STACK
を追加すると、プログラムは期待通りに動作します。
同様に
はNASMの
, a
section
ディレクティブで、 実行不可能なスタックを指定します。
5.4 から 5.8 までの最近の Linux カーネルでは、動作が変更されています。
を変更しました。x86-64 では、何も
READ_IMPLIES_EXEC
をオンにするものはもうありません。 せいぜい(RWEで
GNU_STACK
によって追加された
ld
によって追加された場合)、すべての読み取り可能なページではなく、スタックそのものが実行可能であることがわかります。 (
この回答
は5.8での最後の変更をカバーしていますが、その質問が
.data
x86-64 Linux 5.4上で)。
exec-all
(
READ_IMPLIES_EXEC
) が発生するのは、リンカがレガシー 32 ビット実行ファイルに
GNU_STACK
のようなヘッダーエントリーが全くない。 しかし、ここに示すように、現代の
ld
が入力されたときでさえも、常に何らかの設定でそれを追加します。
.o
ファイルにノートがない場合でもです。
それでもこの
.note
セクションを使うべきです。 しかし、もしあなたが自己修正コードを
.data
の中で自己修正するコードをテストしたり、古いチュートリアルに沿って
シェルコードのテスト
のような古いチュートリアルに従うこともできますが、これは最近のカーネルではオプションではありません。
関連
-
未定義の `__isoc99_sscanf' への参照
-
[解決済み] MIPSのネストされたForループと配列の使用
-
[解決済み] mallocで文字列を確保する
-
[解決済み] ⑭と⑯は何のためにあるのですか?
-
[解決済み] C言語における「static」の意味とは?
-
[解決済み] プログラム終了前にmallocの後にfreeをしないと本当に何が起こるのか?
-
[解決済み] C言語でオブジェクト指向のコードを書くとしたら、どのようにすればよいのでしょうか?[クローズド]
-
[解決済み] なぜC言語では構造体を頻繁にtypedefする必要があるのですか?
-
[解決済み] C 言語の配列へのポインタ/ポインタの配列の曖昧さ解消
-
[解決済み] LD_PRELOADのトリックとは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Cエラー [エラー] 代入_Ashesの左オペランドにlvalueが必要です-プログラマーズ・シークレット
-
#137: 式は変更可能なlvalueでなければならない問題 // 文字列配列の代入問題
-
関数 'malloc' の暗黙の宣言に対する解決策
-
[解決済み] 初期化でポインタ対象の型から修飾語を捨てる
-
[解決済み] munmap_chunk(): 無効なポインタ
-
[解決済み] ソケットアクセプト - "開かれているファイルが多すぎる"
-
[解決済み] mallocの結果はキャストするのですか?
-
[解決済み] printfにおけるdoubleの正しい書式指定子
-
[解決済み] ストラクチャーとユニオンの違い
-
[解決済み] FortranはC言語よりも重い計算を最適化しやすいですか?