Ich schreibe einen Unit-Test für meine UTF8-Manipulationsbibliothek, und ich möchte, dass mein Test zu segfault, wenn eine Funktion in einen Pufferüberlauf geht. So kam ich auf die Idee, zwei Seiten nebeneinander im Speicher abzubilden, die erste mit PROT_READ | PROT_WRITE, und die zweite mit PROT_NONE. Auf diese Weise ist im Falle eines Überlaufs ein Segfault garantiert. Hier ist ein Beispiel:
void *addr1, *addr2; /* these are the pages; mmap call left out for simplicity */
char *p = (char *) (addr1 + getpagesize() - 8);
utf8_encode(aUtf8String, p, 8); // this shouldn't segfault
Das Problem ist, wenn ich die zweite Seite zuordne, stürzt mein Programm ab. Hier ist ein Beispielprogramm, das das Problem reproduziert (GNU/Linux):
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
void checkMap(void *p)
{
if(p == MAP_FAILED) {
printf("error running mmap: %s\n", strerror(errno));
exit(1);
}
}
int main(void)
{
void *addr1, *addr2;
size_t pagesize;
pagesize = getpagesize();
checkMap(addr1 = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
checkMap(addr2 = mmap(addr1 + pagesize, pagesize, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0)); /* segfaults */
munmap(addr1, pagesize);
munmap(addr2, pagesize);
return 0;
}
Interessanterweise führt eine printf()-Anweisung vor der ersten mmap() dazu, dass das Programm erfolgreich läuft. Weiß jemand, warum mmap segfaulting ist? Wenn mein Ziel mit mmap() nicht zu erreichen ist, hat jemand einen anderen Rat, wie ich meinen Code auf Pufferüberlauf testen könnte?
0 Stimmen
Ihr Code funktioniert bei mir perfekt. Das einzige Problem ist, dass Sie die Datei unistd.h für getpagesize() nicht einbinden. Der Compiler wird den Typ erraten. Das könnte auf 64bit-Systemen zu Problemen führen, wenn er einen 32bit int vermutet.
0 Stimmen
Ich habe es auch getestet, und ich bekomme das Segfaulting, aber nicht innerhalb von main(). Vielmehr stürzt es im Glibc-Code ab, beim Beenden ... Wirklich seltsam, das hier. Ich habe auf einer sehr einfachen 32-Bit-Maschine getestet.
0 Stimmen
Nur aus Neugierde, mit welcher Kernel-Version/Distro läuft es bei Ihnen? Ich habe es gerade auf einer 64-Bit-Version ausprobiert (nach #including unistd.h), und jetzt schlägt es auf munmap fehl.
0 Stimmen
Als kurze Nachbereitung scheint es nur in dem Fall abzustürzen, wenn addr2 = addr1 + pagesize. Ich habe versucht, 2 * pagesize und -2 * pagesize hinzuzufügen, und dann ist der Absturz weg. Seltsam.
0 Stimmen
Unwind- Das ist mir auch schon aufgefallen; es tritt nur auf, wenn die Seiten im Speicher nebeneinander liegen.
0 Stimmen
Erfinden Sie das Rad nicht neu. Electric Fence und andere Debug-Haufen werden dies für Sie tun.