2013-07-09 11 views
8

In Linux, the mmap(2) man page wyjaśnia, że ​​anonimowego odwzorowaniaAnonimowy mmap zero wypełniony?

. . . nie jest wspierany przez żaden plik; jego zawartość jest inicjowana do zera.

The FreeBSD mmap(2) man page nie czyni podobną gwarancję o zerowej nadzieniem, choć obiecuje, że bajtów od końca pliku w nieanonimowego mapowania są zero-wypełniony.

Jakie smaki Unix obiecują zwrócić zerową pamięć z anonimowych mmaps? Które z nich w praktyce zwracają pamięć zerową, ale nie zawierają takiej obietnicy na swoich stronach man?

Mam wrażenie, że wypełnianie zera jest częściowo ze względów bezpieczeństwa. Zastanawiam się, czy jakiekolwiek implementacje mmap pomijają wypełnianie zerowe dla strony, która została zmapowana, zmapowana, a następnie zmapowana ponownie przez pojedynczy proces, lub jeśli jakiekolwiek implementacje wypełnią nowo zmapowaną stronę pseudolosowymi bitami lub pewną stałą niezerową.

P.S. Apparently, even brk and sbrk used to guarantee zero-filled pages. Moje eksperymenty na Linuksa zdają się wskazywać, że nawet jeśli pełnych stron są zerowe wypełnione po winy strony po wezwaniem sbrk przydziela im częściowe strony nie są:

#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]); 
} 

Odpowiedz

7

Trudno powiedzieć, które z nich obiecują co bez prostu wyczerpujące wyliczanie wszystkich stron podręcznika man lub innej dokumentacji wydania, ale podstawowy kod obsługujący MAP_ANON jest (zwykle? zawsze?) również używany do mapowania w przestrzeni bss dla plików wykonywalnych, a przestrzeń bss musi być wypełniona zerami. Więc jest to całkiem prawdopodobne.

Co do "oddawania starych wartości" (lub niektórych niezerowych wartości, ale najprawdopodobniej starych), jeśli usuniesz mapowanie i mapujesz, to z pewnością wydaje się możliwe, jeśli jakiś system miałby być "leniwy" "o zwrocie. Użyłem tylko kilku systemów, które obsługują w pierwszej kolejności mmap (pochodne BSD i Linux) i żaden z nich nie jest leniwy w ten sposób, przynajmniej nie w kodzie obsługi kodu mmap.

Powód, dla którego sbrk może wypełnić lub nie wypełnić ponownie stronę "odrodzoną" prawdopodobnie wiąże się z historią lub jej brakiem. Obecny kod FreeBSD pasuje do tego, co pamiętam ze starego, pre-mmap dni: istnieją dwie pół-tajne zmienne, minbrk i curbrk, i oba brk i sbrk będą wywoływały tylko SYS_break (prawdziwe wywołanie systemowe), jeśli będą się przemieszczać. curbrk do wartości co najmniej minbrk. (Faktycznie, wygląda to nieco uszkodzony: brk ma zachowanie przy-najmniej ale sbrk tylko dodaje jej argument curbrk i wywołuje SYS_break Wydaje się nieszkodliwe, ponieważ kontrole jądra, w sys_obreak() w /sys/vm/vm_unix.c, więc zbyt negatywna sbrk() zakończy się niepowodzeniem z EINVAL..)

Musiałbym zajrzeć do biblioteki Linux C (a może i kodu jądra), ale może po prostu zignorować próby "obniżenia przerwy" i po prostu zapisać wartość "logicznej przerwy" w bibliotece libc. Jeśli masz mmap() i nie masz wymagań kompatybilności wstecznej, możesz wdrożyć brk() i w całości w bibliotece libc, używając anonimowych mapowań, i byłoby trywialnie zaimplementować oba z nich jako "tylko do wzrostu".