Linux 5.4 和 5.9 之间可执行文件 .data 部分默认行为是否发生了变化?

2024-10-12 09:57:00
admin
原创
79
摘要:问题描述:故事案例 1我无意中在 部分中编写了我的汇编代码.data。我编译并执行了它。5.4.0-53-generic即使我没有指定 这样的标志,该程序在 Linux 下也能正常运行execstack。案例 2:之后我在Linux下执行了该程序5.9.0-050900rc5-generic,程序得到了SIG...

问题描述:

故事

案例 1

我无意中在 部分中编写了我的汇编代码.data。我编译并执行了它。5.4.0-53-generic即使我没有指定 这样的标志,该程序在 Linux 下也能正常运行execstack

案例 2:

之后我在Linux下执行了该程序5.9.0-050900rc5-generic,程序得到了SIGSEGV,我通过读取检查了虚拟内存权限/proc/$pid/maps,结果发现该部分不可执行。

我认为 Linux 上有一个配置可以管理该权限。但我不知道在哪里可以找到。

代码

[Linux 5.4.0-53-通用]

运行(正常)

ammarfaizi2@integral:/tmp$ uname -r
5.4.0-53-generic
ammarfaizi2@integral:/tmp$ cat test.asm
[section .data]
global _start
_start:
  mov eax, 60
  xor edi, edi
  syscall
ammarfaizi2@integral:/tmp$ nasm --version
NASM version 2.14.02
ammarfaizi2@integral:/tmp$ nasm -felf64 test.asm -o test.o
ammarfaizi2@integral:/tmp$ ld test.o -o test
ammarfaizi2@integral:/tmp$ ./test
ammarfaizi2@integral:/tmp$ echo $?
0
ammarfaizi2@integral:/tmp$ md5sum test
7ffff5fd44e6ff0a278e881732fba525  test
ammarfaizi2@integral:/tmp$ 

检查权限(00400000-00402000 rwxp),因此它是可执行的。

## Debug
gef➤  shell cat /proc/`pgrep test`/maps
00400000-00402000 rwxp 00000000 08:03 7471589                            /tmp/test
7ffff7ffb000-7ffff7ffe000 r--p 00000000 00:00 0                          [vvar]
7ffff7ffe000-7ffff7fff000 r-xp 00000000 00:00 0                          [vdso]
7ffffffde000-7ffffffff000 rwxp 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
gef➤

[Linux 5.9.0-050900rc5-通用]

运行(段错误)

root@esteh:/tmp# uname -r
5.9.0-050900rc5-generic
root@esteh:/tmp# cat test.asm
[section .data]
global _start
_start:
  mov eax, 60
  xor edi, edi
  syscall
root@esteh:/tmp# nasm --version
NASM version 2.14.02
root@esteh:/tmp# nasm -felf64 test.asm -o test.o
root@esteh:/tmp# ld test.o -o test
root@esteh:/tmp# ./test
Segmentation fault (core dumped)
root@esteh:/tmp# echo $?
139
root@esteh:/tmp# md5sum test
7ffff5fd44e6ff0a278e881732fba525  test
root@esteh:/tmp# 

检查权限(00400000-00402000 rw-p),因此它不可执行。

## Debug
gef➤  shell cat /proc/`pgrep test`/maps
00400000-00402000 rw-p 00000000 fc:01 2412                               /tmp/test
7ffff7ff9000-7ffff7ffd000 r--p 00000000 00:00 0                          [vvar]
7ffff7ffd000-7ffff7fff000 r-xp 00000000 00:00 0                          [vdso]
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
gef➤  

对象转储-p

root@esteh:/tmp# objdump -p test

test:     file format elf64-x86-64

Program Header:
    LOAD off    0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**12
         filesz 0x0000000000001009 memsz 0x0000000000001009 flags rw-

问题

  1. Linux 上管理默认 ELF 部分权限的配置在哪里?

  2. 我对权限的观察正确吗?

概括

  • .dataLinux 上该部分的默认权限5.4.0-53-generic是可执行。

  • .dataLinux 上部分的默认权限5.9.0-050900rc5-generic不可执行的。


解决方案 1:

您的二进制文件缺失PT_GNU_STACK。因此,此更改似乎是由提交9fccc5c0c99f238aa1b0460fccbdb30a887e7036引起的:

From 9fccc5c0c99f238aa1b0460fccbdb30a887e7036 Mon Sep 17 00:00:00 2001
From: Kees Cook <keescook@chromium.org>
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 <hecmargi@upv.es>
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Jason Gunthorpe <jgg@mellanox.com>
Link: https://lkml.kernel.org/r/20200327064820.12602-4-keescook@chromium.org
---
 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)    \n-   (executable_stack == EXSTACK_DEFAULT)
+   (mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
 
 struct task_struct;
 
-- 
cgit 1.2.3-1.el7

这是在 5.8 系列中首次出现的。另请参阅当项目中包含汇编文件时,mmap 的意外执行权限。

解决方案 2:

这只是一个猜测:我认为罪魁祸首是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) \n    (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/20190418055759.GA3155@mellanox.com
 *
 */
#define elf_read_implies_exec(ex, executable_stack) \n    (mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)

请注意,在 5.4 版本中,elf_read_implies_exec如果堆栈没有明确标记为不可执行(通过PT_GNU_STACK段),则返回真值。

在最新的源代码中,检查现在更具防御性:只有在ELF 二进制文件中未找到elf_read_implies_exec任何段的情况下,才对 32 位可执行文件成立。PT_GNU_STACK

我组装了您的程序,链接了它,但找不到任何PT_GNU_STACK段,所以这可能是原因。

如果这确实是问题所在,并且我正确地遵循了代码,如果您在二进制文件中将堆栈设置为不可执行,则其数据部分不应再映射为可执行(即使在 Linux 5.4 上也不应如此)。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用