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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

डीबग करना

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

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

कुछ प्लैटफ़ॉर्म पर, उपयोगकर्ता नेमस्पेस डिफ़ॉल्ट रूप से बंद रहते हैं. जैसे, 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 को बंद करना चाहिए, क्योंकि इससे आपकी डिस्क समय के साथ भर जाती है.