linux tuto Pourquoi le segment de pile est-il exécutable sur Raspberry Pi?



raspbian login (1)

J'ai un Raspberry Pi 3 avec le système d'exploitation Raspbian GNU / Linux 8 (Jessie).

J'ai écrit ce programme simple. Je l'ai compilé avec gcc -o hello hello.c .

#include <stdio.h>

void main(){
  printf("hello!\n");
}

De la sortie de lecture tout semble OK:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  EXIDX          0x0004cc 0x000104cc 0x000104cc 0x00008 0x00008 R   0x4
  PHDR           0x000034 0x00010034 0x00010034 0x00120 0x00120 R E 0x4
  INTERP         0x000154 0x00010154 0x00010154 0x00019 0x00019 R   0x1
      [Requesting program interpreter: /lib/ld-linux-armhf.so.3]
  LOAD           0x000000 0x00010000 0x00010000 0x004d8 0x004d8 R E 0x10000
  LOAD           0x000f0c 0x00020f0c 0x00020f0c 0x0011c 0x00120 RW  0x10000
  DYNAMIC        0x000f18 0x00020f18 0x00020f18 0x000e8 0x000e8 RW  0x4
  NOTE           0x000170 0x00010170 0x00010170 0x00044 0x00044 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
  GNU_RELRO      0x000f0c 0x00020f0c 0x00020f0c 0x000f4 0x000f4 R   0x1

Mais quand je lance le programme, la pile est exécutable:

0x7efdf000 0x7f000000 0x00000000 rwx [stack]

J'essaie de compiler aussi avec l'option -z noexecstack , mais rien ne change.

J'essaye aussi de télécharger la version de libarmmem.so qui a ce code:

#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

Mais rien ne change.

Pourquoi le segment de pile est-il exécutable sur Raspberry Pi?

Modifier J'ajoute la sortie de la commande LD_DEBUG = files ./hello

     23110: 
     23110: file=/usr/lib/arm-linux-gnueabihf/libarmmem.so [0];  needed by ./hello [0]
     23110: file=/usr/lib/arm-linux-gnueabihf/libarmmem.so [0];  generating link map
     23110:   dynamic: 0x76f273fc  base: 0x76f13000   size: 0x00014524
     23110:     entry: 0x76f13568  phdr: 0x76f13034  phnum:          6
     23110: 
     23110: 
     23110: file=libc.so.6 [0];  needed by ./hello [0]
     23110: file=libc.so.6 [0];  generating link map
     23110:   dynamic: 0x76f0ef20  base: 0x76dd4000   size: 0x0013e550
     23110:     entry: 0x76dea840  phdr: 0x76dd4034  phnum:         10
     23110: 
     23110: 
     23110: calling init: /lib/arm-linux-gnueabihf/libc.so.6
     23110: 
     23110: 
     23110: calling init: /usr/lib/arm-linux-gnueabihf/libarmmem.so
     23110: 
     23110: 
     23110: initialize program: ./hello
     23110: 
     23110: 
     23110: transferring control: ./hello
     23110: 
hello!
     23110: 
     23110: calling fini: ./hello [0]
     23110: 
     23110: 
     23110: calling fini: /usr/lib/arm-linux-gnueabihf/libarmmem.so [0]
     23110:

Ajouter plus d'informations: Je modifie le fichier architecture.S, et après le make j'ai reçu:

gcc -std=gnu99 -O2 -c -o trampoline.o trampoline.c
gcc -shared -o libarmmem.so architecture.o memcmp.o memcpymove.o memcpymove-a7.o memset.o trampoline.o
`architecture' referenced in section `.text' of trampoline.o: defined in discarded section `.note.GNU-stack' of architecture.o
`architecture' referenced in section `.text' of trampoline.o: defined in discarded section `.note.GNU-stack' of architecture.o
`architecture' referenced in section `.text' of trampoline.o: defined in discarded section `.note.GNU-stack' of architecture.o
`architecture' referenced in section `.text' of trampoline.o: defined in discarded section `.note.GNU-stack' of architecture.o
collect2: error: ld returned 1 exit status
Makefile:13: recipe for target 'libarmmem.so' failed
make: *** [libarmmem.so] Error 1

Il est probable que /usr/lib/arm-linux-gnueabihf/libarmmem.so soit la cause. J'ai trouvé ce fichier source:

Il manque l'annotation de pile non-exécutable, donc glibc rend la pile exécutable de façon conservative lorsque le DSO est préchargé. Les autres fichiers source ont ceci:

/* Prevent the stack from becoming executable */
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif

Il suffit donc de copier ceci dans architecture.S (à la fin du fichier) et de le reconstruire.

Vous pouvez vérifier avec eu-readelf -l /usr/lib/arm-linux-gnueabihf/libarmmem.so si ce DSO est bien le coupable. Il ne doit afficher aucun en-tête de programme GNU_STACK ou un en-tête de programme GNU_STACK marqué RWE dans l'avant-dernière colonne.





compiler-options