Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

177
Views
¿El comportamiento predeterminado de Linux de la sección .data ejecutable cambió entre 5.4 y 5.9?

Historia

Caso 1

Accidentalmente escribí mi código de ensamblaje en la sección .data . Lo compilé y lo ejecuté. El programa se ejecutó normalmente en Linux 5.4.0-53-generic aunque no especifiqué un indicador como execstack .

Caso 2:

Después de eso, ejecuté el programa bajo Linux 5.9.0-050900rc5-generic . El programa obtuvo SIGSEGV . Inspeccioné el permiso de memoria virtual leyendo /proc/$pid/maps . Resultó que la sección no es ejecutable.

Creo que hay una configuración en Linux que gestiona ese permiso. Pero no se donde encontrar.

Código

[Linux 5.4.0-53-genérico]

Ejecutar (normal)

 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$

Verifique el permiso (00400000-00402000 rwxp), para que sea ejecutable.

 ## 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-genérico]

Ejecutar (fallo de segmento)

 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#

Comprobar Permiso (00400000-00402000 rw-p), por lo que NO es ejecutable.

 ## 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-

Preguntas

  1. ¿Dónde está la configuración en Linux que administra el permiso de secciones ELF predeterminado?
  2. ¿Son correctas mis observaciones sobre los permisos?

Resumen

  • El permiso predeterminado para la sección .data en Linux 5.4.0-53-generic es ejecutable.
  • El permiso predeterminado para la sección .data en Linux 5.9.0-050900rc5-generic NO es ejecutable.
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

A su binario le falta PT_GNU_STACK . Como tal, este cambio parece haber sido causado por la confirmación 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.hb/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

Esto estuvo presente por primera vez en la serie 5.8. Consulte también Permiso de ejecución inesperado de mmap cuando se incluyen archivos ensamblados en el proyecto .

over 4 years ago · Santiago Trujillo Report

0

Esto es solo una suposición : creo que el culpable es la personalidad READ_IMPLIES_EXEC que se configuraba automáticamente en ausencia de un segmento PT_GNU_STACK .

En la fuente del kernel 5.4 podemos encontrar este fragmento de código :

 SET_PERSONALITY2(loc->elf_ex, &arch_state); if (elf_read_implies_exec(loc->elf_ex, executable_stack)) current->personality |= READ_IMPLIES_EXEC;

Eso es lo único que puede transformar una sección RW en una RWX. Cualquier otro uso de PROC_EXEC no parecía haber cambiado o no era relevante para esta pregunta, para mí.

El executable_stack se establece aquí :

 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;

Pero si el segmento PT_GNU_STACK no está presente, esa variable conserva su valor predeterminado :

 int executable_stack = EXSTACK_DEFAULT;

Ahora este flujo de trabajo es idéntico tanto en 5.4 como en la última fuente del kernel, lo que cambió es la definición de 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 más reciente :

 /* * 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)

Tenga en cuenta cómo en la versión 5.4, elf_read_implies_exec devolvía un valor verdadero si la pila no se marcaba explícitamente como no ejecutable (a través del segmento PT_GNU_STACK ).

En la fuente más reciente, la verificación ahora es más defensiva: elf_read_implies_exec es verdadero solo en el ejecutable de 32 bits, en el caso de que no se haya encontrado ningún segmento PT_GNU_STACK en el binario ELF.

Ensamblé su programa, lo vinculé y no encontré ningún segmento PT_GNU_STACK , por lo que esta puede ser la razón.
Si este es realmente el problema y si seguí el código correctamente, si configura la pila como no ejecutable en el binario, su sección de datos ya no debería ser mapeada como ejecutable (ni siquiera en Linux 5.4).

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!