क्या पाइप से एक देशी बाइनरी को निष्पादित करने का एक तरीका है?


13
echo 'main(){}' | gcc -xc - -o /dev/stdout | ???

क्या यूनिक्स जैसी प्रणाली पर आउटपुट बाइनरी को चलाने का एक तरीका है?

संपादित करें: मुझे सैंडबॉक्स वाले वातावरण में g ++ का आउटपुट चलाने के लिए इसकी आवश्यकता थी जहां मैं कोई फ़ाइल नहीं लिख सकता (दुर्भावनापूर्ण, मैं वादा करता हूं)।


मेरा मानना ​​है कि बुनियादी सुरक्षा तंत्र को इसे रोकना चाहिए। लेकिन अगर आपका इरादा सी-कोड को मक्खी पर चलाना है, तो बस इस्तेमाल करें csh
रोज़ज़ेट्राइजेविज़ ऑक्ट

जवाबों:


10

मुझे विश्वास नहीं होता कि यह संभव है। कार्यकारी (2) सिस्टम कॉल हमेशा एक फ़ाइल नाम या निरपेक्ष पथ की आवश्यकता है (फ़ाइल नाम हमेशा एक है char*)। posix_spawnफ़ाइल नाम के लिए भी समान आवश्यकताएं हैं।

निकटतम आप कर सकते हैं एक नामांकित पाइप में आउटपुट पाइप है और पाइप से निष्पादित करने का प्रयास करें। यह काम कर सकता है, हालांकि शेल किसी भी फ़ाइल को निष्पादित करने से इनकार कर सकता है जिसमें --x--x--xबिट्स सेट नहीं है । साथ पाइप बनाएं mkfifo(1)और देखें कि क्या आप इसे काम करने के लिए प्राप्त कर सकते हैं।

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

संपादित करें: जैसा कि मैट बताते हैं, पहला दृष्टिकोण काम नहीं करेगा क्योंकि लोडर निष्पादन योग्य में मांग-पृष्ठ का प्रयास करेगा, जो फ़ाइल पर यादृच्छिक खोज ट्रैफ़िक उत्पन्न करेगा, और यह एक पाइप पर संभव नहीं है। यह दूसरी तरह के दृष्टिकोण को छोड़ देता है।


2
मैं वास्तव में आश्चर्यचकित रहूँगा यदि पाइप ट्रिक ने काम किया - आप एक पाइप पर रैंडम सॉक्स नहीं कर सकते हैं, और उन्हें एमएमएपी नहीं कर सकते हैं - मुझे पूरा यकीन है कि रनटाइम लोडर / लिंकर को परेशान करेगा :) आपका दूसरा सुझाव अच्छा लगता है हालांकि, एक अस्थायी फ़ाइल के बिना कुछ भी नहीं आ सकता है।
Mat

@ मट - मुझे लगता है कि तुम सही हो। निष्पादन योग्य में मांग पेजिंग यादृच्छिक अभिगम यातायात का कारण होगा जो पाइप पर काम नहीं करेगा। विडंबना यह है कि यह वास्तव में SVR2.0 पर काम कर सकता है (अंतिम संस्करण जिसने मांग पेजिंग का उपयोग नहीं किया था) - बस अपनी उम्र दिखाने के लिए मैं वास्तव में एक एटी एंड टी 3 बी 2/400 का उपयोग करता था एक बार एसवीआर 2.0 के साथ ओ / एस के रूप में।
चिंता का

इसके बारे में कुछ और सोचने के साथ, मुझे पूरा यकीन है कि यूपीएक्स जैसे एक्सई पैकर्स विघटन और निष्पादन को रीड-ओनली मीडिया पर कर सकते हैं । जो कुछ भी स्टब पर वे निष्पादित करते हैं उसे डीकंप्रेस के बजाय पाइप से पढ़ने के लिए संशोधित करें, और ... काम हो सकता है।
Mat

@ मैटर पैकर्स में पहले से ही एक छवि भरी हुई है, वे एक नई प्रक्रिया शुरू नहीं करते हैं। समान करने के लिए मुझे इनपुट डेटा में एक मनमानी छलांग लगाने के लिए प्रक्रियाओं में से एक होने की आवश्यकता है (जिसे सुरक्षा भेद्यता माना जाएगा)।
एलेक्स बी

@ एलेक्स बी: आप विशेष रूप से पूछ रहे हैं कि इनपुट डेटा में मनमानी छलांग कैसे लगाई जाए। जब आप यह सुझाव देते हैं कि आप वास्तव में ऐसा करते हैं तो आप क्यों शिकायत करेंगे? क्या आप करने की कोशिश कर रहे हैं, इसे रोकने के लिए विशेष रूप से सैंडबॉक्स का उद्देश्य है?
डेविड श्वार्ट्ज

7

मेम्फ़ड syscall का उपयोग करके एक समाधान: https://github.com/abbat/elfexec

यह मेमोरी में एक नामित फ़ाइल डिस्क्रिप्टर बनाता है जिसका उपयोग किया जा सकता है exec। एक छद्म कोड:

#include <linux/memfd.h>
...
int memfd = syscall(SYS_memfd_create, "someName", 0);
...
write(memfd,... elf-content...);
...
fexecve(memfd, argv, environ);

1
memfd.hजब तक आप उपयोग नहीं करना चाहते हैं, तब तक आपको शीर्ष लेख की आवश्यकता नहीं है MFD_CLOEXEC(जो #! /bin/shकि लिनक्स में बग के कारण स्क्रिप्ट को तोड़ देगा fexecve())। यह बहुत जटिल नहीं है, आप अपने जवाब में 20-लाइन वर्किंग सैंपल को शामिल कर सकते हैं (जैसे। यह git gist - हालांकि यह आपके लिए ड्रॉप-इन रिप्लेसमेंट नहीं है elfexec, क्योंकि यह आपको निर्दिष्ट करने की भी अनुमति देगा argv[0], और बाइनरी चलाएगा केवल एक पाइप से (UUoC अनिवार्य; ;-))
मस्वी

इसलिए मुझे यह नहीं मिला कि यह कैसे काम करने की उम्मीद है। gcc .o/ tmp में फाइल लिखेगा और यदि यह नहीं हो सका तो मर जाएगा।
जोशुआ

4

आप tcc की कोशिश कर सकते हैं , जो किसी भी मध्यवर्ती फ़ाइलों को लिखे बिना, एक चरण में एक कार्यक्रम को संकलित और निष्पादित करेगा। यह gcc नहीं है, जो आपके लिए एक समस्या हो सकती है, लेकिन यह शानदार रूप से तेज़ है, इसलिए यह आपके उद्देश्यों के लिए gcc से बेहतर शर्त लगा सकता है।


2

यह स्वचालित रूप से आपके कोड का संकलन चलाएगा, लेकिन इसे करने के लिए फ़ाइल सिस्टम पर एक फ़ाइल (टेम्परली) बनाता है।

echo 'main(){}' | gcc -xc -o /tmp/a.out && chmod u+x /tmp/a.out && /tmp/a.out && rm -f /tmp/a.out

(मैं अभी यह परीक्षण कर रहा हूं, लेकिन मुझे पूरा यकीन है कि यह या इसके कुछ करीब आपके लिए काम करेगा)

संपादित करें: यदि आपके पाइपिंग का लक्ष्य गति के लिए समीकरण से बाहर भौतिक डिस्क को काटने के लिए है, तो इंटरमीडिएट फ़ाइल को रखने के लिए राम डिस्क बनाने पर विचार करें ।


यह निश्चित रूप से काम करेगा, लेकिन यह प्रश्न के मुख्य बिंदु को याद करता है - एक बाइनरी कोड निष्पादित करने के लिए जो डिस्क पर कभी नहीं लिखा जाता है।
rozcietrzewiacz

@rozcietrzewiacz मेरी आशा थी कि यह उपयोगी होगा यदि लक्ष्य आसानी से आवश्यक भौतिक फ़ाइल से निपटने के बिना मक्खी पर कोड का एक टुकड़ा चलाने के लिए था।
14

हाँ मैं समझता हूँ। लेकिन उसके लिए, एक बस का उपयोग कर सकते हैं csh
rozcietrzewiacz

0

जैसे @TheQUUX ने सुझाव दिया, मैंने इसे स्वयं परीक्षण नहीं किया है, लेकिन आप कोशिश कर सकते हैं cling- "एलएलवीएम और क्लैंग लाइब्रेरी के शीर्ष पर बनाया गया इंटरएक्टिव सी ++ इंटरप्रेटर।"

अधिक जानकारी यहां पाएं: https://cdn.rawgit.com/root-project/cling/master/www/index.html

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.