Ich stoße damit meinen Kopf gegen die Wand.
Wenn ich in meinem Projekt Speicher mit mmap
dem Mapping ( /proc/self/maps
) zuordne, zeigt dies, dass es sich um einen lesbaren und ausführbaren Bereich handelt, obwohl ich nur lesbaren Speicher angefordert habe.
Nachdem ich mir strace (was gut aussah) und anderes Debugging angesehen hatte, konnte ich das einzige identifizieren, das dieses seltsame Problem zu vermeiden scheint: Baugruppendateien aus dem Projekt entfernen und nur reines C belassen (was?!)
Hier ist mein seltsames Beispiel: Ich arbeite an Ubunbtu 19.04 und Standard-GCC.
Wenn Sie die ausführbare Zieldatei mit der ASM-Datei (die leer ist) kompilieren, wird mmap
ein lesbarer und ausführbarer Bereich zurückgegeben. Wenn Sie ohne erstellen, verhält sie sich korrekt. Siehe die Ausgabe, /proc/self/maps
die ich in mein Beispiel eingebettet habe.
Beispiel.c
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
int main()
{
void* p;
p = mmap(NULL, 8192,PROT_READ,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);
{
FILE *f;
char line[512], s_search[17];
snprintf(s_search,16,"%lx",(long)p);
f = fopen("/proc/self/maps","r");
while (fgets(line,512,f))
{
if (strstr(line,s_search)) fputs(line,stderr);
}
fclose(f);
}
return 0;
}
Beispiel.s : Ist eine leere Datei!
Ausgänge
Mit der in ASM enthaltenen Version
VirtualBox:~/mechanics/build$ gcc example.c example.s -o example && ./example
7f78d6e08000-7f78d6e0a000 r-xp 00000000 00:00 0
Ohne die mitgelieferte ASM-Version
VirtualBox:~/mechanics/build$ gcc example.c -o example && ./example
7f1569296000-7f1569298000 r--p 00000000 00:00 0
-Wa,--noexecstack
.Antworten:
Linux hat eine Ausführungsdomäne namens
READ_IMPLIES_EXEC
, die bewirkt, dass alle zugewiesenen SeitenPROT_READ
ebenfalls angegeben werdenPROT_EXEC
. Dieses Programm zeigt Ihnen, ob dies für sich selbst aktiviert ist:Wenn Sie das zusammen mit einer leeren
.s
Datei kompilieren , werden Sie sehen, dass es aktiviert ist, aber ohne eine wird es deaktiviert. Der Anfangswert hierfür stammt aus den ELF-Metainformationen in Ihrer Binärdatei . Tu esreadelf -Wl example
. Diese Zeile wird angezeigt, wenn Sie ohne die leere.s
Datei kompiliert haben :Aber dieses, als Sie damit kompilierten:
Beachten Sie
RWE
statt nurRW
. Der Grund dafür ist, dass der Linker davon ausgeht, dass Ihre Assembly-Dateien read-implizite-exec erfordern, es sei denn, es wird ausdrücklich darauf hingewiesen, dass dies nicht der Fall ist. Wenn ein Teil Ihres Programms read-implizite-exec erfordert, ist es für Ihr gesamtes Programm aktiviert . Die Assembly-Dateien, die GCC kompiliert, geben an, dass dies in dieser Zeile nicht erforderlich ist (dies wird angezeigt, wenn Sie mit kompilieren-S
):Wenn Sie diese Zeile eingeben,
example.s
wird dem Linker mitgeteilt, dass er sie auch nicht benötigt, und Ihr Programm funktioniert dann wie erwartet.quelle
.o
Dateien erstellen ! Aber ich denke, dies ist der Mechanismus, dergcc -zexecstack
verwendet wird, und warum er nicht nur den Stapel, sondern alles ausführbar macht.-Wa,--noexecstack
. Ich denke, es ist eine sehr böse scharfe Kante. Der stille Verlust von nx-Stacks sollte eine Sicherheitslücke sein. Die Binutil-Leute sollten es reparieren..note.GNU-stack,"",@progbits
erklärt würde - im Moment ist sie undurchsichtig, was "diese magische Zeichenfolge verursacht diesen Effekt" entspricht, aber die Zeichenfolge sieht eindeutig so aus, als hätte sie eine Art Semantik.Alternativ zum Ändern Ihrer Assembly-Dateien mit GNU-spezifischen Varianten der Abschnittsanweisung können Sie
-Wa,--noexecstack
Ihrer Befehlszeile das Erstellen von Assembly-Dateien hinzufügen . Sehen Sie zum Beispiel, wie ich es in Musls macheconfigure
:https://git.musl-libc.org/cgit/musl/commit/configure?id=adefe830dd376be386df5650a09c313c483adf1a
Ich glaube, zumindest einige Versionen von clang mit integriertem Assembler erfordern möglicherweise die Übergabe als
--noexecstack
(ohne-Wa
), daher sollte Ihr Konfigurationsskript wahrscheinlich beide prüfen und prüfen, welche akzeptiert werden.Sie können auch verwenden
-Wl,-z,noexecstack
zur Linkzeit (inLDFLAGS
) verwenden, um das gleiche Ergebnis zu erhalten. Dies hat den Nachteil, dass es nicht hilft, wenn Ihr Projekt statische (.a
) Bibliotheksdateien zur Verwendung durch andere Software erstellt, da Sie dann die Verbindungszeitoptionen nicht steuern, wenn sie von anderen Programmen verwendet werden.quelle