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

किसी समस्या की शिकायत करें सोर्स देखें Nightly · 8.0 · 7.4 · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

सैंडबॉक्सिंग के नुकसान

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

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

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

sandboxfs

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

sandboxfs इंस्टॉल करना

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

डाउनलोड करें

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

sandboxfs चलाएं

  1. (सिर्फ़ macOS के लिए) OSXFUSE इंस्टॉल करें.
  2. (सिर्फ़ macOS के लिए) यह तरीका अपनाएं:

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

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

  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 क्लस्टर नोड या 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 का इस्तेमाल करके, 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 को बंद रखना चाहिए. ऐसा इसलिए, क्योंकि यह समय के साथ आपकी डिस्क को भर देता है.