バイナリに PT_GNU_STACK
がありません .そのため、この変更はコミット 9fccc5c0c99f238aa1b0460fccbdb30a887e7036
によって引き起こされたようです :
From 9fccc5c0c99f238aa1b0460fccbdb30a887e7036 Mon Sep 17 00:00:00 2001
From: Kees Cook <[email protected]>
Date: Thu, 26 Mar 2020 23:48:17 -0700
Subject: x86/elf: Disable automatic READ_IMPLIES_EXEC on 64-bit
With modern x86 64-bit environments, there should never be a need for
automatic READ_IMPLIES_EXEC, as the architecture is intended to always
be execute-bit aware (as in, the default memory protection should be NX
unless a region explicitly requests to be executable).
There were very old x86_64 systems that lacked the NX bit, but for those,
the NX bit is, obviously, unenforceable, so these changes should have
no impact on them.
Suggested-by: Hector Marco-Gisbert <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: Borislav Petkov <[email protected]>
Reviewed-by: Jason Gunthorpe <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
---
arch/x86/include/asm/elf.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 397a1c74433ec..452beed7892bb 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -287,7 +287,7 @@ extern u32 elf_hwcap2;
* CPU: | lacks NX* | has NX, ia32 | has NX, x86_64 |
* ELF: | | | |
* ---------------------|------------|------------------|----------------|
- * missing PT_GNU_STACK | exec-all | exec-all | exec-all |
+ * missing PT_GNU_STACK | exec-all | exec-all | exec-none |
* PT_GNU_STACK == RWX | exec-stack | exec-stack | exec-stack |
* PT_GNU_STACK == RW | exec-none | exec-none | exec-none |
*
@@ -303,7 +303,7 @@ extern u32 elf_hwcap2;
*
*/
#define elf_read_implies_exec(ex, executable_stack) \
- (executable_stack == EXSTACK_DEFAULT)
+ (mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
struct task_struct;
--
cgit 1.2.3-1.el7
これは 5.8 シリーズで初めて登場しました。プロジェクトにアセンブリ ファイルが含まれている場合、mmap からの予期しない exec 権限も参照してください。
これは単なる推測です :犯人は READ_IMPLIES_EXEC
だと思います PT_GNU_STACK
がない場合に自動的に設定されていたパーソナリティ
5.4 カーネル ソースには、次のコードがあります:
SET_PERSONALITY2(loc->elf_ex, &arch_state);
if (elf_read_implies_exec(loc->elf_ex, executable_stack))
current->personality |= READ_IMPLIES_EXEC;
RW セクションを RWX セクションに変換できるのはこれだけです。 PROC_EXEC
のその他の使用 私には、変更されていないようにも、この質問に関連しているようにも見えませんでした.
executable_stack
ここで設定されます:
for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++)
switch (elf_ppnt->p_type) {
case PT_GNU_STACK:
if (elf_ppnt->p_flags & PF_X)
executable_stack = EXSTACK_ENABLE_X;
else
executable_stack = EXSTACK_DISABLE_X;
break;
PT_GNU_STACK
の場合 セグメントが存在しない場合、その変数はデフォルト値を保持します:
int executable_stack = EXSTACK_DEFAULT;
これで、このワークフローは同一になりました 5.4 と最新のカーネル ソースの両方で、変更されたのは elf_read_implies_exec
の定義です。 :
Linux 5.4:
/*
* An executable for which elf_read_implies_exec() returns TRUE will
* have the READ_IMPLIES_EXEC personality flag set automatically.
*/
#define elf_read_implies_exec(ex, executable_stack) \
(executable_stack != EXSTACK_DISABLE_X)
最新の Linux:
/*
* An executable for which elf_read_implies_exec() returns TRUE will
* have the READ_IMPLIES_EXEC personality flag set automatically.
*
* The decision process for determining the results are:
*
* CPU: | lacks NX* | has NX, ia32 | has NX, x86_64 |
* ELF: | | | |
* ---------------------|------------|------------------|----------------|
* missing PT_GNU_STACK | exec-all | exec-all | exec-none |
* PT_GNU_STACK == RWX | exec-stack | exec-stack | exec-stack |
* PT_GNU_STACK == RW | exec-none | exec-none | exec-none |
*
* exec-all : all PROT_READ user mappings are executable, except when
* backed by files on a noexec-filesystem.
* exec-none : only PROT_EXEC user mappings are executable.
* exec-stack: only the stack and PROT_EXEC user mappings are executable.
*
* *this column has no architectural effect: NX markings are ignored by
* hardware, but may have behavioral effects when "wants X" collides with
* "cannot be X" constraints in memory permission flags, as in
* https://lkml.kernel.org/r/[email protected]
*
*/
#define elf_read_implies_exec(ex, executable_stack) \
(mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
5.4 バージョンで elf_read_implies_exec
スタックが明示的でない場合に真の値を返しました 実行不可としてマークされます (PT_GNU_STACK
経由) セグメント)
最新のソースでは、チェックはより防御的になりました:elf_read_implies_exec
PT_GNU_STACK
がない場合、32 ビットの実行可能ファイルでのみ true です。 セグメントが ELF バイナリで見つかりました。
あなたのプログラムをアセンブルしてリンクしましたが、PT_GNU_STACK
が見つかりませんでした セグメントなので、これは 可能性があります 理由になります。
これが実際に問題であり、コードに正しく従った場合、スタックをバイナリで実行不可として設定すると、そのデータ セクションは実行可能にマップされなくなります (Linux 5.4 でも)。