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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

सैंडबॉक्स करने से जुड़ी समस्याएं

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

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

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

सैंडबॉक्सF

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

सैंडबॉक्सf इंस्टॉल करें

नीचे दिए गए तरीके का इस्तेमाल करके, 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 बिल्ड चलाएं.

    bazel build target --experimental_use_sandboxfs
    

समस्या हल करना

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

डीबग करना

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

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

कुछ प्लैटफ़ॉर्म, जैसे कि Google Kubernetes Engine के क्लस्टर नोड या डीबीएएन पर, सुरक्षा से जुड़ी समस्याओं की वजह से, उपयोगकर्ता नेमस्पेस को डिफ़ॉल्ट रूप से बंद कर दिया जाता है. अगर /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 का इस्तेमाल करके Bazel ठीक उसी कमांड को दिखाएगा जो उसे बिल्ड के फ़ेल होने पर दिखाया गया था. इसमें वह हिस्सा भी दिखाया जाएगा जो सैंडबॉक्स को सेट अप करता है.

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

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)

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

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