5. सैंडबॉक्सी से संचार करना

डिफ़ॉल्ट रूप से, एक्ज़ीक्यूटर, फ़ाइल डिस्क्रिप्टर के ज़रिए Sandboxee से कम्यूनिकेट कर सकता है. आपको इन चीज़ों की ज़रूरत पड़ सकती है. उदाहरण के लिए, अगर आपको सिर्फ़ Sandboxee के साथ कोई फ़ाइल शेयर करनी है या Sandboxee का स्टैंडर्ड आउटपुट पढ़ना है.

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

फ़ाइल डिस्क्रिप्टर शेयर करना

Inter-Process Communication API (ipc.h देखें) का इस्तेमाल करके, MapFd() या ReceiveFd() का इस्तेमाल किया जा सकता है:

  • एक्ज़ीक्यूटर से Sandboxee से फ़ाइल डिस्क्रिप्टर को मैप करने के लिए, MapFd() का इस्तेमाल करें. इसका इस्तेमाल, एक्ज़ीक्यूटर से खोली गई फ़ाइल को Sandboxee में इस्तेमाल करने के लिए शेयर करने के लिए किया जा सकता है. इसका एक उदाहरण स्टैटिक में देखा जा सकता है.

    // The executor opened /proc/version and passes it to the sandboxee as stdin
    executor->ipc()->MapFd(proc_version_fd, STDIN_FILENO);
    
  • सॉकेटपेयर एंडपॉइंट बनाने के लिए, ReceiveFd() का इस्तेमाल करें. इसका इस्तेमाल, Sandboxee के स्टैंडर्ड आउटपुट या स्टैंडर्ड गड़बड़ियों को पढ़ने के लिए किया जा सकता है. टूल में, इसे इस्तेमाल करने का एक उदाहरण देखा जा सकता है.

    // The executor receives a file descriptor of the sandboxee stdout
    int recv_fd1 = executor->ipc())->ReceiveFd(STDOUT_FILENO);
    

comms API का इस्तेमाल करना

Sandbox2 एक सुविधाजनक comms API उपलब्ध कराता है. यह एक्ज़ीक्यूटर और Sandboxee के बीच पूर्णांक, स्ट्रिंग या बाइट बफ़र शेयर करने का एक आसान और आसान तरीका है. नीचे कुछ कोड स्निपेट दिए गए हैं, जिन्हें crc4 के उदाहरण में देखा जा सकता है.

comms API के साथ शुरुआत करने के लिए, आपको पहले Sandbox2 ऑब्जेक्ट से comms ऑब्जेक्ट पाना होगा:

sandbox2::Comms* comms = s2.comms();

कम्यूनिकेशन ऑब्जेक्ट उपलब्ध होने पर, डेटा को 'भेजें*' फ़ैमिली के किसी एक फ़ंक्शन का इस्तेमाल करके, Sandboxee को भेजा जा सकता है. crc4 के उदाहरण में, comms API के इस्तेमाल का उदाहरण देखा जा सकता है. नीचे दिया गया कोड स्निपेट, इस उदाहरण का एक छोटा हिस्सा दिखाता है. एक्ज़ीक्यूटर, SendBytes(buf, size) के साथ unsigned char buf[size] भेजता है:

if (!(comms->SendBytes(static_cast<const uint8_t*>(buf), sz))) {
  /* handle error */
}

Sandboxee से डेटा पाने के लिए, Recv* के किसी एक फ़ंक्शन का इस्तेमाल करें. नीचे दिया गया कोड स्निपेट, crc4 के उदाहरण का हिस्सा है. एक्ज़ीक्यूटर को, साइन न किए गए 32-बिट पूर्णांक में चेकसम मिलता है: uint32_t crc4;

if (!(comms->RecvUint32(&crc4))) {
  /* handle error */
}

बफ़र के साथ डेटा शेयर करना

डेटा शेयर करने की एक और सुविधा है, ज़्यादा डेटा शेयर करने के लिए buffer API का इस्तेमाल करना. साथ ही, एक्ज़ीक्यूटर और Sandboxee के बीच बार-बार भेजी जाने वाली महंगी कॉपी से बचा जाना.

एक्ज़ीक्यूटर, पास किए जाने वाले साइज़ और डेटा के हिसाब से या सीधे फ़ाइल डिस्क्रिप्टर से बफ़र बनाता है और उसे एक्ज़ीक्यूटर में comms->SendFD() और सैंडबॉक्स में comms->RecvFD() का इस्तेमाल करके सैंडबॉक्सी को भेजता है.

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

// start the sandbox asynchronously
s2.RunAsync();

// instantiate the comms object
sandbox2::Comms* comms = s2.comms();

// random buffer data we want to send
constexpr unsigned char buffer_data[] = /* random data */;
constexpr unsigned int buffer_dataLen = 34;

// create sandbox2 buffer
absl::StatusOr<std::unique_ptr<sandbox2::Buffer>> buffer =
     sandbox2::Buffer::CreateWithSize(1ULL << 20 /* 1Mib */);
std::unique_ptr<sandbox2::Buffer> buffer_ptr = std::move(buffer).value();

// point to the sandbox2 buffer and fill with data
uint8_t* buf = buffer_ptr‑>data();
memcpy(buf, buffer_data, buffer_data_len);

// send the data to the sandboxee
comms‑>SendFd(buffer_ptr‑>fd());

Sandboxee की ओर, आपको एक बफ़र ऑब्जेक्ट बनाना होगा और एक्सक्यूटर के भेजे गए फ़ाइल डिस्क्रिप्टर से डेटा को पढ़ना होगा:

// establish the communication with the executor
int fd;
comms.RecvFD(&fd);

// create the buffer
absl::StatusOr<std::unique_ptr<sandbox2::Buffer>> buffer =
     sandbox2::Buffer::createFromFd(fd);

// get the data
auto buffer_ptr = std::move(buffer).value();
uint8_t* buf = buffer_ptr‑>data();

/* work with the buf object */