2013-07-09 9 views
8

In Linux, the mmap(2) man page erklärt, dass eine anonyme MappingAnonym mmap null gefüllt?

. . . wird von keiner Datei unterstützt; sein Inhalt wird auf Null initialisiert.

The FreeBSD mmap(2) man page keine ähnliche Garantie über Null-Füllung machen, obwohl es Versprechen macht, die nach dem Ende einer Datei in einem nicht-anonymen Mapping-Bytes mit Nullen aufgefüllt werden.

Welche Varianten von Unix versprechen Null-initialisierten Speicher von anonymen mmaps zurück zu geben? Welche geben in der Praxis einen Null-initialisierten Speicher zurück, machen aber auf ihren Manpages keine solchen Versprechen?

Es ist mein Eindruck, dass Zero-Füllung teilweise aus Sicherheitsgründen ist. Ich frage mich, ob irgendwelche mmap-Implementierungen die Null-Füllung für eine Seite übersprungen, die mmapped, munmapped, dann wieder von einem einzigen Prozess mmapped wurde, oder ob irgendwelche Implementierungen eine neu zugeordnete Seite mit pseudozufälligen Bits oder einer von Null verschiedenen Konstante füllen.

P.S. Apparently, even brk and sbrk used to guarantee zero-filled pages. Meine Experimente unter Linux scheinen zu zeigen, auch wenn volle Seiten mit Nullen aufgefüllt auf Seitenfehler nach einem sbrk Aufruf ordnet sie, Teilseiten sind nicht:

#include <unistd.h> 
#include <stdio.h> 

int main() { 
    const intptr_t many = 100; 
    char * start = sbrk(0); 
    sbrk(many); 
    for (intptr_t i = 0; i < many; ++i) { 
    start[i] = 0xff; 
    } 
    printf("%d\n",(int)start[many/2]); 
    sbrk(many/-2); 
    sbrk(many/2); 
    printf("%d\n",(int)start[many/2]); 
    sbrk(-1 * many); 
    sbrk(many/2); 
    printf("%d\n",(int)start[0]); 
} 

Antwort

7

Es ist schwer zu sagen, welche davon verspricht, was ohne einfach erschöpfende Aufzählung aller man-Seiten oder anderer Release-Dokumentation, aber der zugrunde liegende Code, der MAP_ANON handhabt, wird (normalerweise? immer?) auch verwendet, um bss-Platz für ausführbare Dateien zuzuordnen, und bss-Platz muss null sein. Also ist es verdammt wahrscheinlich.

Wenn Sie "Ihre alten Werte zurückgeben" (oder einige Werte ungleich null, aber höchstwahrscheinlich Ihre alten), wenn Sie die Zuordnung aufheben und neu zuordnen, scheint es durchaus möglich zu sein, wenn ein System "faul" wäre "über die Aufhebung der Freigabe. Ich habe nur ein paar Systeme verwendet, die mmap an erster Stelle unterstützen (BSD und Linux-Derivate) und keiner ist so faul, zumindest nicht in der Kernel-Code-Behandlung mmap.

Der Grund sbrk möglicherweise Null-fill eine "neugewachsene" Seite ist wahrscheinlich an Geschichte gebunden, oder deren Fehlen. Der aktuelle FreeBSD-Code übereinstimmt mit dem, was ich von den alten erinnern, Pre- mmap Tage: Es gibt zwei halb-geheime Variablen, minbrk und curbrk, und beide brk und sbrk nur SYS_break (den realen Systemaufruf) berufen, wenn sie curbrk bewegen zu einem Wert, der mindestens minbrk ist. (Eigentlich sieht dies etwas gebrochen: brk das at-dest Verhalten hat aber sbrk kommt noch hinzu, ihr Argument zu curbrk und ruft SYS_break scheint, da die Kernel prüft harmlos, in sys_obreak() in /sys/vm/vm_unix.c, so ein zu negativen sbrk() mit EINVAL scheitern..)

Ich müsste die Linux C-Bibliothek (und dann vielleicht Kernel-Code) betrachten, aber es kann einfach ignorieren Versuche, "die Pause zu senken", und nur einen "logischen Bruch" Wert in libc. Wenn Sie mmap() und keine Abwärtskompatibilitätserfordernisse haben, können Sie brk() und sbrk() vollständig in libc implementieren, indem Sie anonyme Zuordnungen verwenden, und es wäre trivial, beide als "Nur-Wachstum" zu implementieren.