c - LD_PRELOAD affects new child even after unsetenv("LD_PRELOAD") -


मेरा कोड निम्नानुसार है: preload.c, निम्न सामग्री के साथ:

  # शामिल करें & lt; stdio.h & gt; # शामिल करें & lt; stdlib.h & gt; Int __attribute __ ((कन्स्ट्रक्टर)) मुख्य_इनिट (रिक्त) {printf ("LD_PRELOAD:% x \ n", अनसेटन्यूव ("एलडी_PRELOAD")); फ़ाइल * fp = popen ("ls", "r"); pclose (एफपी); }  

फिर खोल में (देखभाल के साथ दूसरी कमान करते हैं !!):

  जीसीसी प्रीलाड c -shared -wl, -soname, mylib -o mylib.so -fPIC LD_PRELOAD =। / Mylib.so bash  

!!! आखिरी कमांड के साथ सावधान रहें, इसके परिणामस्वरूप "श-सी एलएस" फर्क करने के अंतहीन लूप का परिणाम होगा। सी के साथ 2 सेकंड के बाद इसे बंद करो, (या बेहतर ^ जेड और उसके बाद ps देखें)।

अधिक जानकारी

  1. यह समस्या किसी तरह से बाश से संबंधित है; या तो उपयोगकर्ता द्वारा चलाए जाने वाले कमांड के रूप में, या पॉपने के निष्पादन के रूप में।
  2. अतिरिक्त प्रमुख कारक: 1) पूर्व-लोड किए गए लाइब्रेरी से पॉपन करना, 2) संभवत: पॉपिन को लाइब्रेरी का प्रारंभिकरण अनुभाग।
  3. यदि आप उपयोग करते हैं:

      LD_DEBUG = सभी LD_DEBUG_OUTPUT = / tmp / ld-debug LD_PRELOAD =। / Mylib.so bash < / Code> 

    पिछले कमांड के स्थान पर, आपको कई डीडी-डीबग फ़ाइलें मिलेंगी, नामित /tmp/ld-debug.*। प्रत्येक forked प्रक्रिया के लिए एक इन सभी फाइलों में आप देखेंगे कि ये प्रतीक पहली बार mylib.so में खोजे थे, हालांकि LD_PRELOAD को पर्यावरण से हटा दिया गया था।

संपादित करें: इसलिए समस्या / सवाल वास्तव में था: आप कैसे <<कोड> LD_PRELOAD से पहले से लोड किए गए bash से मुख्य_इनित ()

इसका कारण यह है कि execve , जिसे आप के बाद कहा जाता है popen , पर्यावरण (शायद) से लेता है

  extern char ** वातावरण;  

जो कुछ वैश्विक राज्य चर है जो आपके पर्यावरण को इंगित करता है। unsetenv () सामान्य रूप से आपके वातावरण को संशोधित करता है और इसलिए ** वातावरण की सामग्री पर असर होगा।

यदि bash पर्यावरण के साथ कुछ विशेष करने की कोशिश करता है (अच्छी तरह से ... क्या यह एक शेल है?) तो आप परेशान हो सकते हैं।

स्पष्ट रूप से, bash overloads Unsetenv () से पहले भी main_init () । उदाहरण कोड को इसमें बदलना:

  extern char ** environ; Int __attribute __ ((कन्स्ट्रक्टर)) मुख्य_इनिट (शून्य) {int i; Printf ("एलडी_PRELOAD:% x \ n", अनसेटेनव ("एलडी_PRELOAD") को अनसेट करना; Printf ("LD_PRELOAD: \"% s \ "\ n", getenv ("एलडी_PRELOAD")); Printf ("वातावरण:% एलएक्स \ n", वातावरण); Printf ("unsetenv:% lx \ n", unsetenv); के लिए (i = 0; वातावरण [i]; i ++) printf ("env:% s \ n", वातावरण [i]); fflush (stdout); फ़ाइल * fp = popen ("ls", "r"); pclose (एफपी); }  

समस्या दिखाती है सामान्य चलने में ( cat , ls , आदि चल रहा है) मुझे इस संस्करण का अप्रसेंट के रूप में मिलता है:

  unsetenv: 7f4c78fd5290 unsetenv: 7f1127317290 unsetenv: 7f1ab63a2290  

हालांकि, bash या sh चल रहा है:

  unsetenv: 46d170  

तो, वहाँ तुम्हारे पास है bash ने आपको बेवकूफ़ बना दिया है; -)

तो बस अपने ही unsetenv का उपयोग करके वातावरण को संशोधित करें, ** वातावरण पर अभिनय करें < / Code>:

<पूर्व> के लिए (i = 0; वातावरण [i]; i ++) {यदि (स्ट्रस्ट (वातावरण [i], "एलडी_PRELOAD =")) {printf (" वातावरण से [% d] \ n ", i); वातावरण [i] [0] = 'डी'; }

जो strace में काम करने के लिए देखा जा सकता है:

  execve ("/ bin / sh", [ "Sh", "-c", "ls"], [... "DD_PRELOAD = mylib.so" ...]) = 0  

QED


Comments