2012-02-28 14 views
5

मुझे उम्मीद है कि एड्रेस स्पेस लेआउट रैंडमाइजेशन (एएलएसआर) के कारण किसी अन्य प्रक्रिया से फोर्क की गई प्रक्रिया में mmap पर कॉल करते समय अलग-अलग पते होंगे। लेकिन जैसा कि मैंने पाया, वह मामला नहीं था। मैंने उस उद्देश्य के लिए निम्नलिखित परीक्षण कार्यक्रम बनाया है। malloc द्वारा लौटाए गए सभी पते माता-पिता और बच्चे के लिए बिल्कुल समान हैं। ध्यान दें कि malloc, CL1, CL2, PL1 के लिए pl2 आंतरिक mmap का उपयोग करता है, क्योंकि वे बड़े ब्लॉकों हैं।पता स्पेस लेआउट रैंडमाइजेशन (एएलएसआर) और एमएमएपी

तो, मेरा सवाल यह है कि क्यों mmap एएलएसआर की उपस्थिति में भी अलग-अलग पते नहीं लौटा रहा है। शायद इसकी वजह यह है कि यहाँ यादृच्छिकरण के लिए बीज मूल और फोर्क प्रक्रिया के लिए समान है। या कोई अन्य कारण है?

int main() 
{ 
    pid = fork(); 

    if (pid == 0)    // child 
    { 
    void * c1 = malloc(4096); 
    void * c2 = malloc(4096); 

    void * cl1 = malloc((long)512e3); // internally uses mmap 
    void * cl2 = malloc((long)512e3); // internally uses mmap 

    printf("c1 = %p, c2 = %p, cl1 = %p, cl2 = %p!\n", c1, c2, cl1, cl2); 
    } 
    else 
    { 
    void * p1 = malloc(4096); 
    void * p2 = malloc(4096); 

    void * pl1 = malloc((long)512e3); // internally uses mmap 
    void * pl2 = malloc((long)512e3); // internally uses mmap 

    printf("p1 = %p, p2 = %p, pl1 = %p, pl2 = %p!\n", p1, p2, pl1, pl2); 
    } 

    return 0; 
} 
+0

मुझे यकीन नहीं है कि एएसएलआर के लिए आवश्यक है कि 'एमएमएपी' अलग-अलग पते लौटाए; इसका मतलब यह है कि यह * अलग * वापस कर सकता है। और शायद (बस एक अनुमान!) यह 'फोर्क' की तुलना में 'execve' द्वारा और अधिक ट्रिगर किया गया है। निश्चित रूप से, यदि मैं आपके कार्यक्रम के उत्तराधिकार में दो बार शुरू करता हूं, तो मुझे अलग-अलग पते मिल रहे हैं। और यह भविष्य के कर्नेल के साथ बदल सकता है, या शायद SELinux सक्षम लोगों के साथ ... –

+2

आपको यह उपयोगी मिल सकता है: http://xorl.wordpress.com/2011/01/16/linux- कर्नेल-aslr-implementation/ – Necrolis

+0

@ बेसिल: निश्चित रूप से, आपको प्रत्येक रन के लिए अलग-अलग पते मिलेंगे, लेकिन एक रन के लिए, दो प्रक्रियाओं (माता-पिता और बच्चे) के पते कभी अलग होते हैं? – MetallicPriest

उत्तर

4

आप नहीं फिर से randomize कर सकते हैं बच्चे की पता स्थान - सभी संकेत ऊपर छुआ करना होगा, और कहा कि (क्रम पर्यावरण भी पता नहीं है अपने डेटा का क्या हिस्सा संकेत है) तकनीकी रूप से असंभव है।

तो परिणाम जो आप देख रहे हैं, अपेक्षित है, फोर्क से बच्चे को अपने वर्चुअल एड्रेस लेआउट सहित फोर्किंग के समय अपने मूल पता स्थान की एक सटीक प्रति है।

आपको एक नया पता-स्थान लेआउट प्राप्त करने के लिए exec* कॉल की आवश्यकता होगी।

$ cat t.c 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 

int main(int argc, char **argv) 
{ 
    printf("%p\n", malloc((long)512e3)); 
    if ((argc > 1) && fork()) { 
     execl("./a.out", "./a.out", NULL); 
    } 
    return 0; 
} 
$ gcc -Wall t.c 
$ ./a.out 1 
0x7f5bf6962010 
0x7f3483044010 
$ ./a.out 1 
0x7f1ce7462010 
0x7feb2adc2010 

(और यकीन है कि /proc/sys/kernel/randomize_va_space शून्य भी नहीं है।)

+0

ओपी को फोर्क को पतों को बदलने के लिए पहले मैपिंग नहीं करना प्रतीत होता है, केवल कांटे के बाद स्वतंत्र रूप से यादृच्छिक पते प्राप्त करने के बाद नए मैपिंग के लिए। यह तकनीकी रूप से असंभव नहीं है, लेकिन जैसा कि मेरे उत्तर में वर्णित है, यह एक बुरा विचार है। –

+0

तो, आपका मतलब है कि हर भविष्य में mmap, sbrk, malloc आदि माता-पिता और बाल प्रक्रियाओं के लिए समान पते लौटाएंगे? – MetallicPriest

+1

@ मेटालिक प्रिस्टेस्ट: यदि आप उन्हें एक ही मात्रा में सटीक उसी क्रम में करते हैं, और कोई बाहरी कारक खेल नहीं आता है (संसाधन सीमाएं, सादा ओओएम, आदि), शायद हां एक सादे लिनक्स कर्नेल के साथ। गतिशील आवंटन को यादृच्छिक बनाने के लिए कुछ पैच मौजूद हो सकते हैं, लेकिन आधार कर्नेल नहीं। इस पर अधिक के लिए आर .. का जवाब देखें। – Mat

5

ASLR मुख्य रूप से ढेर करने के लिए नीचे उपयोगकर्ता के अंतरिक्ष पता स्थान के ऊपर से दूरी randomizes, और stack- के नीचे से दूरी आरक्षित स्थान पहले mmap (जो शायद गतिशील लिंकर का मानचित्रण है)। किसी भी और यादृच्छिकरण में वर्चुअल मेमोरी स्पेस पर गंभीर खंडन प्रभाव पड़ेंगे, और इस प्रकार उन कार्यक्रमों को तोड़ दिया जाएगा जिन्हें बड़े mmap एस (उदाहरण के लिए 32-बिट मशीन पर 1-2 जीबी मैपिंग) बनाने की आवश्यकता है।

मैंने कुछ लिनक्स डिस्ट्रोज़ जहाज पैच किए गए कर्नेल को देखा है जो mmap द्वारा भेजे गए पते पर अधिक यादृच्छिकता प्रदर्शन करते हैं। उनमें से कुछ आपको स्टैक के विस्तार के लिए आरक्षित आरक्षित जगह के साथ मैपिंग ओवरलैपिंग भी देते हैं, और फिर जब स्टैक बढ़ता है तो यह आपके मैपिंग को घुमाता है (जिसके परिणामस्वरूप एक बड़ा अंतर सुरक्षा सुरक्षा छेद होता है, जो कि गैर-यादृच्छिक पता असाइनमेंट के कारण बहुत बड़ा होता है) । इन हैक्स से दूर रहो।

+0

तो हम मान सकते हैं कि एक फोर्क प्रक्रिया में mmap हमेशा माता-पिता के समान पते को वापस नहीं करेगा? सही? – MetallicPriest

+0

यह आज (आमतौर पर) सच है, लेकिन मैं भविष्य के कर्नेल के लिए यह नहीं मानूंगा। कुछ भी निर्दिष्ट नहीं करता है, यह केवल वर्तमान कार्यान्वयन है। और कर्नेल लोग इसे सुधारना चाहते हैं। –

+0

मैं धारणाओं को एक तरफ या दूसरे बनाने से बचूंगा। उदाहरण के लिए, यह बहुत बड़ी मैपिंग से पहले यादृच्छिक पैडिंग (अनैप्ड पेज) की एक छोटी राशि को जोड़ने के लिए संभवतः सुरक्षित/उचित होगा (क्योंकि प्रतिशत-वार ओवरहेड/विखंडन आवश्यक रूप से बहुत छोटा होगा)। –

संबंधित मुद्दे