Linux可执行文件.data节的默认行为在5.4和5.9之间更改? [英] Linux default behavior of executable .data section changed between 5.4 and 5.9?
问题描述
我不小心在 .data
部分中写了我的汇编代码.我编译并执行它.即使我未指定 execstack
之类的标志,该程序也可以在Linux 5.4.0-53-generic
下正常运行.
I accidentally wrote my Assembly code in the .data
section. I compiled it and executed it. The program ran normally under Linux 5.4.0-53-generic
even though I didn't specify a flag like execstack
.
之后,我在Linux 5.9.0-050900rc5-generic
下执行了该程序.该程序得到了 SIGSEGV
.我通过阅读/proc/$ pid/maps
检查了虚拟内存权限.原来,该部分不可执行.
After that, I executed the program under Linux 5.9.0-050900rc5-generic
. The program got SIGSEGV
. I inspected the virtual memory permission by reading /proc/$pid/maps
. It turned out that the section is not executable.
我认为Linux上有一个配置可以管理该权限.但是我不知道在哪里找到.
I think there is a configuration on Linux that manages that permission. But I don't know where to find.
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-generic]
运行(段错误)
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➤
objdump -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-
问题
- Linux上用于管理默认ELF节权限的配置在哪里?
- 我对权限的观察正确吗?
摘要
- Linux
5.4.0-53-generic
上.data
部分的默认权限是可执行的. - Linux
5.9.0-050900rc5-generic
上.data
部分的默认权限是 NOT 可执行文件. - Default permission for
.data
section on Linux5.4.0-53-generic
is executable. - Default permission for
.data
section on Linux5.9.0-050900rc5-generic
is NOT executable.
Summary
推荐答案
这只是一个猜测:我认为罪魁祸首是自动设置的 READ_IMPLIES_EXEC
个性在没有 PT_GNU_STACK
段的情况下.
This is only a guess: I think the culprit is the READ_IMPLIES_EXEC
personality that was being set automatically in the absence of a PT_GNU_STACK
segment.
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
的任何其他使用似乎都没有改变或与此问题相关.
That's the only thing that can transform an RW section into an RWX one. Any other use of PROC_EXEC
didn't seem to be changed or relevant to this question, to me.
executable_stack
设置为但是,如果不存在 PT_GNU_STACK
段,则该变量将保留
But if the PT_GNU_STACK
segment is not present, that variable retains its default value:
int executable_stack = EXSTACK_DEFAULT;
现在此工作流程在5.4和最新的内核源代码中都是相同的,更改的是 elf_read_implies_exec
的定义:
Now this workflow is identical in both 5.4 and the latest kernel source, what changed is the definition of elf_read_implies_exec
:
/*
* 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/20190418055759.GA3155@mellanox.com
*
*/
#define elf_read_implies_exec(ex, executable_stack) \
(mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
请注意,在5.4版本中,如果堆栈未显式标记为不可执行(通过 PT_GNU_STACK
段).
Note how in the 5.4 version the elf_read_implies_exec
returned a true value if the stack was not explicitly marked as not executable (via the PT_GNU_STACK
segment).
在最新消息中,此检查现在更具防御性:如果在以下位置未找到 PT_GNU_STACK
段,则 elf_read_implies_exec
仅在32位可执行文件上为trueELF二进制文件.
In the latest source, the check is now more defensive: the elf_read_implies_exec
is true only on 32-bit executable, in the case where no PT_GNU_STACK
segment was found in the ELF binary.
我汇编了程序,将其链接起来,没有找到 PT_GNU_STACK
段,因此可能是 的原因.
如果确实是问题所在,并且如果我正确地遵循了代码,那么如果您将堆栈设置为二进制可执行文件,则其数据部分将不再被映射为可执行文件(即使在Linux 5.4上也是如此).
I assembled your program, linked it, and found no PT_GNU_STACK
segment, so this may be the reason.
If this is indeed the issue and if I followed the code correctly, if you set the stack as not executable in the binary, its data section should not be mapped executable anymore (not even on Linux 5.4).
这篇关于Linux可执行文件.data节的默认行为在5.4和5.9之间更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!