सैंडबॉक्सिंग

समस्या की शिकायत करें सोर्स देखें

इस लेख में, Basel में सैंडबॉक्स करने, sandboxfs को इंस्टॉल करने, और आपके सैंडबॉक्सिंग एनवायरमेंट को डीबग करने के बारे में बताया गया है.

सैंडबॉक्सिंग, अनुमतियों को सीमित करने की ऐसी रणनीति है जो प्रोसेस को एक-दूसरे से या सिस्टम के रिसॉर्स से अलग करती है. Basel के लिए, इसका मतलब फ़ाइल सिस्टम ऐक्सेस को प्रतिबंधित करना है.

बेज़ल का फ़ाइल सिस्टम सैंडबॉक्स, काम करने वाली डायरेक्ट्री में प्रोसेस करता है. इसमें सिर्फ़ जाने-पहचाने इनपुट होते हैं. इसका मतलब है कि कंपाइलर और अन्य टूल को सोर्स फ़ाइलें तब तक नहीं दिखती हैं, जब तक उन्हें ऐक्सेस नहीं करना चाहिए. ऐसा तब तक होगा, जब तक उन्हें इसका सटीक पाथ न पता हो.

सैंडबॉक्सिंग, होस्ट एनवायरमेंट को किसी भी तरह से नहीं छिपाती है. प्रोसेस, फ़ाइल सिस्टम की सभी फ़ाइलों को आसानी से ऐक्सेस कर सकती हैं. हालांकि, उपयोगकर्ता नेमस्पेस के साथ काम करने वाले प्लैटफ़ॉर्म पर, प्रोसेस अपनी वर्किंग डायरेक्ट्री के बाहर की किसी भी फ़ाइल में बदलाव नहीं कर सकती. इससे यह पक्का होता है कि बिल्ड ग्राफ़ में ऐसी कोई छिपी हुई डिपेंडेंसी नहीं है जो बिल्ड की दोबारा बनाने की क्षमता पर असर डाल सकती है.

खास तौर पर, Basel हर कार्रवाई के लिए एक execroot/ डायरेक्ट्री बनाता है, जो एक्ज़ीक्यूशन के समय ऐक्शन की वर्क डायरेक्ट्री के तौर पर काम करती है. execroot/ कार्रवाई के लिए सभी इनपुट फ़ाइलें शामिल होती हैं और किसी भी जनरेट किए गए आउटपुट के लिए कंटेनर के तौर पर काम करती हैं. इसके बाद, Baze, ऑपरेटिंग सिस्टम से मिली तकनीक, Linux पर कंटेनर और macOS पर sandbox-exec का इस्तेमाल करके, execroot/ में होने वाली कार्रवाई को सीमित करता है.

सैंडबॉक्स करने की वजहें

  • ऐक्शन सैंडबॉक्सिंग के बिना, Basel को यह पता नहीं चल पाता कि टूल में ऐसी इनपुट फ़ाइलों का इस्तेमाल हुआ है या नहीं जिनका एलान नहीं किया गया है. इन फ़ाइलों में ऐसी फ़ाइलें शामिल होती हैं जो किसी कार्रवाई पर डिपेंडेंसी में साफ़ तौर पर मौजूद नहीं होती हैं. जब एलान नहीं की गई किसी इनपुट फ़ाइल में बदलाव होता है, तब भी Basel का मानना है कि बिल्ड अप-टू-डेट है और वह ऐक्शन को दोबारा नहीं बनाएगा. इस वजह से, इंक्रीमेंटल बिल्ड गलत हो सकता है.

  • कैश मेमोरी में सेव की गई एंट्री का गलत तरीके से फिर से इस्तेमाल करने पर, रिमोट कैश मेमोरी में समस्याएं पैदा होती हैं. शेयर की गई कैश मेमोरी में कैश मेमोरी में सेव होने पर, प्रोजेक्ट के हर डेवलपर पर असर पड़ता है. साथ ही, पूरी रिमोट कैश मेमोरी को वाइप करना संभव नहीं है.

  • सैंडबॉक्सिंग, रिमोट एक्ज़ीक्यूशन की तरह ही है — अगर कोई बिल्ड सैंडबॉक्सिंग के साथ ठीक से काम करता है, तो हो सकता है कि यह रिमोट एक्ज़ीक्यूशन के साथ भी काम करे. रिमोट तरीके से एक्ज़ीक्यूट करने की सुविधा की मदद से सभी ज़रूरी फ़ाइलें (लोकल टूल के साथ) अपलोड करें. इससे क्लस्टर को कंपाइल करने में लगने वाला खर्च कम हो जाएगा. किसी नए कंपाइलर को आज़माने या किसी मौजूदा टूल में बदलाव करने के बजाय, क्लस्टर में हर मशीन पर टूल इंस्टॉल करना पड़ेगा.

सैंडबॉक्स की कौनसी रणनीति इस्तेमाल करें

रणनीति से जुड़े फ़्लैग की मदद से, यह चुना जा सकता है कि किसी सैंडबॉक्स का इस्तेमाल कैसे किया जाए. sandboxed की रणनीति का इस्तेमाल करके, Basel ने यहां दिए गए सैंडबॉक्स में से एक इंप्लिमेंटेशन को चुना है. इसकी तुलना में, ओएस के हिसाब से बनाए गए सैंडबॉक्स और कम हरमेटिक जेनरिक सैंडबॉक्स को प्राथमिकता दी गई है. अगर आपने --worker_sandboxing फ़्लैग को पास किया है, तो लगातार वर्कर, जेनरिक सैंडबॉक्स में चलते हैं.

local (यानी standalone) रणनीति किसी भी तरह की सैंडबॉक्सिंग नहीं करती. यह बस कार्रवाई की कमांड लाइन को एक्ज़ीक्यूट करता है. साथ ही, उस डायरेक्ट्री को एक्ज़ीक्यूट करता है जो आपके फ़ाइल फ़ोल्डर के एक्सक्लूट के तौर पर सेट होती है.

processwrapper-sandbox, सैंडबॉक्स की गई ऐसी रणनीति है जिसके लिए किसी भी "ऐडवांस" सुविधा की ज़रूरत नहीं होती. इसे किसी भी POSIX सिस्टम पर काम करना चाहिए. यह सैंडबॉक्स डायरेक्ट्री बनाता है, जिसमें ऐसे सिमलिंक होते हैं जो ओरिजनल सोर्स फ़ाइलों पर ले जाते हैं. साथ ही, यह एक्सक्रूट के बजाय इस डायरेक्ट्री पर सेट की गई ऐक्टिव डायरेक्ट्री के साथ ऐक्शन की कमांड लाइन लागू करता है. इसके बाद, जाने-पहचाने आउटपुट आर्टफ़ैक्ट को सैंडबॉक्स से बाहर एक्सक्रूट में ले जाता है और सैंडबॉक्स को मिटा देता है. इससे, अनजाने में किसी भी ऐसी इनपुट फ़ाइल का इस्तेमाल नहीं हो पाता है जिसका एलान न किया गया हो. साथ ही, यह कार्रवाई को अनजान आउटपुट फ़ाइलों के साथ चलाए जाने से भी रोकता है.

linux-sandbox एक कदम आगे बढ़कर processwrapper-sandbox के सबसे ऊपर बन जाता है. Docker, हुड के तहत जो काम करता है उसी तरह यह Linux नेमस्पेस (उपयोगकर्ता, माउंट, पीआईडी, नेटवर्क, और आईपीसी नेमस्पेस) का इस्तेमाल करके, होस्ट की कार्रवाई को अलग करता है. इसका मतलब है कि सैंडबॉक्स डायरेक्ट्री को छोड़कर, पूरे फ़ाइल सिस्टम को सिर्फ़ पढ़ने के लिए बनाया जाता है. इससे, होस्ट फ़ाइल सिस्टम पर गलती से किसी भी आइटम में बदलाव नहीं हो पाता. इससे, गड़बड़ी की जांच जैसी स्थितियों से बचा जा सकता है. ऐसा गलती से आपकी $HOME डायरेक्ट्री को RM -rf' करने से रोका जा सकता है. इसके अलावा, इस कार्रवाई को नेटवर्क ऐक्सेस करने से भी रोका जा सकता है. linux-sandbox, पीआईडी नेमस्पेस का इस्तेमाल करके, कार्रवाई को किसी दूसरी प्रोसेस को देखने से रोकता है. साथ ही, आखिर में सभी प्रोसेस (भले ही कार्रवाई की वजह से डीमन का प्रमोशन किया गया हो) को सुरक्षित तरीके से खत्म करने के लिए भी इनका इस्तेमाल किया जाता है.

darwin-sandbox समान है, लेकिन macOS के लिए. यह Apple के sandbox-exec टूल का इस्तेमाल करके, Linux सैंडबॉक्स के करीब-करीब पूरा करता है.

ऑपरेटिंग सिस्टम के बताए गए तरीकों में पाबंदियों की वजह से, linux-sandbox और darwin-sandbox, दोनों "नेस्ट किए गए" क्रम में काम नहीं करते. Docker अपने कंटेनर मैजिक के लिए, Linux नेमस्पेस का भी इस्तेमाल करता है. इसलिए, Docker कंटेनर के अंदर linux-sandbox को आसानी से नहीं चलाया जा सकता, जब तक कि docker run --privileged का इस्तेमाल न किया जाए. macOS पर, sandbox-exec को ऐसी प्रोसेस में नहीं चलाया जा सकता जिसे पहले से ही सैंडबॉक्स किया जा रहा हो. इसलिए, ऐसे मामलों में Baze, अपने-आप processwrapper-sandbox का इस्तेमाल करना बंद कर देता है.

अगर आपको इसके बजाय कोई बिल्ड गड़बड़ी मिलती है — जैसे कि गलती से, कम सख्त एक्ज़ीक्यूशन रणनीति का इस्तेमाल करके बिल्ड न करना — तो उन एक्ज़ीक्यूशन रणनीतियों की सूची में साफ़ तौर पर बदलाव करें जिनका इस्तेमाल Basel ने किया है (उदाहरण के लिए, bazel build --spawn_strategy=worker,linux-sandbox).

डाइनैमिक एक्ज़ीक्यूशन के लिए आम तौर पर लोकल एक्ज़ीक्यूशन के लिए सैंडबॉक्सिंग की ज़रूरत होती है. ऑप्ट आउट करने के लिए, --experimental_local_lockfree_output फ़्लैग को पास करें. डाइनैमिक एक्ज़ीक्यूशन, परसिस्टेंट वर्कर को सैंडबॉक्स करता है.

सैंडबॉक्सिंग की समस्याएं

  • सैंडबॉक्सिंग के लिए अतिरिक्त सेटअप और टियरडाउन लागत आती है. यह लागत कितनी बड़ी होगी, यह कई चीज़ों पर निर्भर करता है. जैसे, होस्ट ओएस का आकार और उसकी परफ़ॉर्मेंस. Linux के लिए, सैंडबॉक्स किए गए बिल्ड बहुत कम मामलों में कुछ प्रतिशत से ज़्यादा धीमे होते हैं. --reuse_sandbox_directories को सेट करने से, सेटअप और टियरडाउन का खर्च कम हो सकता है.

  • सैंडबॉक्स करने से, टूल में मौजूद कैश मेमोरी को पूरी तरह बंद कर दिया जाता है. कमज़ोर सैंडबॉक्स गारंटी की कीमत पर, परसिस्टेंट वर्कर का इस्तेमाल करके, इसे कम किया जा सकता है.

  • सैंडबॉक्स करने के लिए, मल्टीप्लेक्स वर्कर को साफ़ तौर पर सपोर्ट करने वाले वर्कर की ज़रूरत होती है. मल्टीप्लेक्स सैंडबॉक्सिंग की सुविधा न देने वाले वर्कर, डाइनैमिक एक्ज़ीक्यूशन के तहत सिंगलप्लेक्स वर्कर के तौर पर चलते हैं. इससे ज़्यादा मेमोरी खर्च हो सकती है.

सैंडबॉक्सएफ़

sandboxfs एक FUSE फ़ाइल सिस्टम है. यह सिस्टम में मौजूद फ़ाइल सिस्टम को आर्बिट्रेरी व्यू के तौर पर दिखाता है. इसके लिए, समय की सज़ा नहीं दी जाती. Baze, हर कार्रवाई के लिए तुरंत execroot/ जनरेट करने के लिए, sandboxfs का इस्तेमाल करता है. इससे, हज़ारों सिस्टम कॉल करने में लगने वाले खर्च से भी बचा जा सकता है. ध्यान दें कि execroot/ में आगे I/O, FUSE ओवरहेड की वजह से धीमा हो सकता है.

सैंडबॉक्सएफ़ इंस्टॉल करना

sandboxfs को इंस्टॉल करने और इसके साथ बेज़ल बिल्ड करने के लिए, यह तरीका अपनाएं:

डाउनलोड करें

डाउनलोड और इंस्टॉल करें sandboxfs, ताकि sandboxfs बाइनरी आपके PATH में खत्म हो जाए.

sandboxfs चलाएं

  1. (सिर्फ़ macOS के लिए) OSXFUSE इंस्टॉल करें.
  2. (सिर्फ़ macOS के लिए) चलाएं:

    sudo sysctl -w vfs.generic.osxfuse.tunables.allow_other=1
    

    ऐसा आपको इंस्टॉल करने के बाद और हर बार फिर से चालू होने के बाद करना होगा, ताकि यह पक्का किया जा सके कि macOS की मुख्य सिस्टम सेवाएं, सैंडबॉक्सएफ़ के ज़रिए काम करें.

  3. --experimental_use_sandboxfs के साथ बेज़ल बिल्ड चलाएं.

    bazel build target --experimental_use_sandboxfs
    

समस्या हल करने से जुड़ी जानकारी

अगर आपको की जाने वाली कार्रवाइयों के लिए एनोटेशन के तौर पर darwin-sandbox या linux-sandbox के बजाय local दिखता है, तो इसका मतलब यह हो सकता है कि सैंडबॉक्स की सुविधा बंद है. इसे चालू करने के लिए, --genrule_strategy=sandboxed --spawn_strategy=sandboxed को पास करें.

डीबग करना

सैंडबॉक्स की समस्याओं को डीबग करने के लिए, नीचे दी गई रणनीतियों का पालन करें.

बंद किए गए नेमस्पेस

Google Kubernetes Engine क्लस्टर नोड या Debian जैसे प्लैटफ़ॉर्म पर, सुरक्षा से जुड़ी समस्याओं की वजह से उपयोगकर्ता नेमस्पेस को डिफ़ॉल्ट रूप से बंद कर दिया जाता है. अगर /proc/sys/kernel/unprivileged_userns_clone फ़ाइल मौजूद है और उसमें 0 है, तो उपयोगकर्ता नेमस्पेस को चालू किया जा सकता है. इसके लिए, यह तरीका अपनाएं:

   sudo sysctl kernel.unprivileged_userns_clone=1

नियम निष्पादन विफल

सिस्टम के सेटअप की वजह से, हो सकता है कि सैंडबॉक्स नियमों को लागू न कर पाए. अगर आपको namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory जैसा कोई मैसेज दिखता है, तो सैंडबॉक्स को बंद करने की कोशिश करें. इसके लिए, जेननियमों के लिए --strategy=Genrule=local का इस्तेमाल करें और अन्य नियमों के लिए --spawn_strategy=local का इस्तेमाल करें.

बिल्ड विफलताओं के लिए विस्तृत डीबगिंग

अगर आपका बिल्ड फ़ेल हो गया है, तो --verbose_failures और --sandbox_debug का इस्तेमाल करके दिखाएं कि बिल्ड के फ़ेल होने पर उसे सही-सही निर्देश मिले.

गड़बड़ी के मैसेज का उदाहरण:

ERROR: path/to/your/project/BUILD:1:1: compilation of rule
'//path/to/your/project:all' failed:

Sandboxed execution failed, which may be legitimate (such as a compiler error),
or due to missing dependencies. To enter the sandbox environment for easier
debugging, run the following command in parentheses. On command failure, a bash
shell running inside the sandbox will then automatically be spawned

namespace-sandbox failed: error executing command
  (cd /some/path && \
  exec env - \
    LANG=en_US \
    PATH=/some/path/bin:/bin:/usr/bin \
    PYTHONPATH=/usr/local/some/path \
  /some/path/namespace-sandbox @/sandbox/root/path/this-sandbox-name.params --
  /some/path/to/your/some-compiler --some-params some-target)

अब जनरेट की गई सैंडबॉक्स डायरेक्ट्री की जांच की जा सकती है. साथ ही, यह देखा जा सकता है कि Basel ने कौनसी फ़ाइलें बनाई हैं. इसके बाद, कमांड को फिर से चलाकर देखा जा सकता है कि वह कैसे काम करती है.

ध्यान दें कि --sandbox_debug का इस्तेमाल करने पर, Basel सैंडबॉक्स डायरेक्ट्री को नहीं मिटाता है. अगर लगातार डीबग करने की कोशिश नहीं की जाती है, तो आपको --sandbox_debug को बंद करना चाहिए, क्योंकि इससे आपकी डिस्क समय के साथ भर जाती है.