1. सैंडबॉक्स एक्ज़ीक्यूटर का तरीका चुनना

सैंडबॉक्स की प्रोसेस, एक्ज़ीक्यूटर (सैंडबॉक्स एक्ज़ीक्यूटर देखें) से शुरू होती है. यह Sandboxee को चलाने के लिए ज़िम्मेदार होता है. executor.h हेडर फ़ाइल में, इस काम के लिए ज़रूरी एपीआई शामिल होता है. यह एपीआई बहुत लचीला है. इससे आपको अपने इस्तेमाल के हिसाब से सबसे सही विकल्प चुनने में मदद मिलती है. नीचे दिए गए सेक्शन में, तीन अलग-अलग तरीकों के बारे में बताया गया है. इनमें से कोई एक तरीका चुना जा सकता है.

पहला तरीका: स्टैंड-अलोन – सैंडबॉक्सिंग की सुविधा पहले से चालू होने पर, किसी बाइनरी को एक्ज़ीक्यूट करना

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

यहां दिए गए कोड स्निपेट में, हम सैंडबॉक्स किए जाने वाले बाइनरी का पाथ और execve syscall को पास किए जाने वाले आर्ग्युमेंट तय करते हैं. जैसा कि आपको executor.h हेडर फ़ाइल में दिख रहा है, हमने envp के लिए कोई वैल्यू तय नहीं की है. इसलिए, हम पैरंट प्रोसेस से एनवायरमेंट कॉपी करते हैं. याद रखें, पहला आर्ग्युमेंट हमेशा उस प्रोग्राम का नाम होता है जिसे एक्ज़ीक्यूट करना है. हमारे स्निपेट में कोई दूसरा आर्ग्युमेंट तय नहीं किया गया है.

एक्ज़ीक्यूटर के इस तरीके के उदाहरण ये हैं: static और tool.

#include "sandboxed_api/sandbox2/executor.h"

std::string path = "path/to/binary";
std::vector<std::string> args = {path};  // args[0] will become the sandboxed
                                         // process' argv[0], typically the
                                         // path to the binary.
auto executor = absl::make_unique<sandbox2::Executor>(path, args);

दूसरा तरीका: Sandbox2 Forkserver – एक्ज़ीक्यूटर को यह बताना कि उसे कब सैंडबॉक्स किया जाना है

इस तरीके से, शुरू होने के दौरान सैंडबॉक्स से बाहर रहने की सुविधा मिलती है. इसके बाद, ::sandbox2::Client::SandboxMeHere() को कॉल करके, सैंडबॉक्स में शामिल होने का समय चुना जा सकता है. इसके लिए, आपको कोड में यह तय करना होगा कि सैंडबॉक्सिंग कब शुरू करनी है. साथ ही, यह सिंगल-थ्रेड होना चाहिए. इसके बारे में अक्सर पूछे जाने वाले सवालों में पढ़ें.

नीचे दिए गए कोड स्निपेट में, हमने उसी कोड का इस्तेमाल किया है जिसके बारे में ऊपर पहले तरीके में बताया गया है. हालांकि, प्रोग्राम को शुरू करने के दौरान, सैंडबॉक्स से बाहर चलाने की अनुमति देने के लिए, हम set_enable_sandbox_before_exec(false) को कॉल करते हैं.

#include "sandboxed_api/sandbox2/executor.h"

std::string path = "path/to/binary";
std::vector<std::string> args = {path};
auto executor = absl::make_unique<sandbox2::Executor>(path, args);
executor->set_enable_sandbox_before_exec(false);

अब एक्ज़ीक्यूटर के पास, सैंडबॉक्स को तब तक बंद रखने का विकल्प होता है, जब तक कि उसे सैंडबॉक्सी से सूचना नहीं मिल जाती. इसलिए, हमें ::sandbox2::Client इंस्टेंस बनाना होगा. साथ ही, एक्ज़ीक्यूटर और सैंडबॉक्सी के बीच कम्यूनिकेशन सेट अप करना होगा. इसके बाद, एक्ज़ीक्यूटर को यह सूचना देनी होगी कि हमारा इनिशियलाइज़ेशन पूरा हो गया है और अब हमें sandbox2_client.SandboxMeHere() को कॉल करके सैंडबॉक्सिंग शुरू करनी है.

// main() of sandboxee
int main(int argc, char** argv) {
  gflags::ParseCommandLineFlags(&argc, &argv, false);

  // Set-up the sandbox2::Client object, using a file descriptor (1023).
  sandbox2::Comms comms(sandbox2::Comms::kSandbox2ClientCommsFD);
  sandbox2::Client sandbox2_client(&comms);
  // Enable sandboxing from here.
  sandbox2_client.SandboxMeHere();
  

इस एक्ज़ीक्यूटर तरीके का एक उदाहरण crc4 है. इसमें crc4bin.cc सैंडबॉक्सी है और यह एक्ज़ीक्यूटर (crc4sandbox.cc) को सूचना देता है कि इसे सैंडबॉक्स में कब शामिल होना चाहिए.

तीसरा तरीका: कस्टम फ़ोर्कसर्वर – एक बाइनरी तैयार करें, फ़ोर्क के अनुरोधों का इंतज़ार करें, और सैंडबॉक्स को खुद मैनेज करें

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

एक्ज़ीक्यूटर, आपके बाइनरी को फ़ोर्क करने का अनुरोध भेजेगा. इससे fork() (::sandbox2::ForkingClient::WaitAndFork() के ज़रिए) फ़ोर्क हो जाएगा. नई प्रोसेस, ::sandbox2::Client::SandboxMeHere() के साथ सैंडबॉक्स करने के लिए तैयार हो जाएगी.

#include "sandboxed_api/sandbox2/executor.h"

// Start the custom ForkServer
std::string path = "path/to/binary";
std::vector<std::string> args = {path};
auto fork_executor = absl::make_unique<sandbox2::Executor>(path, args);
fork_executor->StartForkServer();

// Initialize Executor with Comms channel to the ForkServer
auto executor = absl::make_unique<sandbox2::Executor>(
    fork_executor->ipc()->GetComms());

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

इस एक्ज़ीक्यूटर तरीके के उदाहरण के लिए, custom_fork देखें.