5. স্যান্ডবক্সীর সাথে যোগাযোগ করা

ডিফল্টরূপে, নির্বাহক ফাইল বর্ণনাকারীর মাধ্যমে স্যান্ডবক্সীর সাথে যোগাযোগ করতে পারে। এটি আপনার প্রয়োজন হতে পারে, উদাহরণস্বরূপ যদি আপনি স্যান্ডবক্সীর সাথে একটি ফাইল ভাগ করতে চান বা স্যান্ডবক্সীর স্ট্যান্ডার্ড আউটপুট পড়তে চান৷

যাইহোক, আপনার সম্ভবত নির্বাহক এবং স্যান্ডবক্সির মধ্যে আরও জটিল যোগাযোগের যুক্তির প্রয়োজন রয়েছে। comms API ( comms.h হেডার ফাইলটি দেখুন) পূর্ণসংখ্যা, স্ট্রিং, বাইট বাফার, প্রোটোবাফ বা ফাইল বর্ণনাকারী পাঠাতে ব্যবহার করা যেতে পারে।

শেয়ারিং ফাইল বর্ণনাকারী

ইন্টার-প্রসেস কমিউনিকেশন API ব্যবহার করে ( ipc.h দেখুন), আপনি MapFd() বা ReceiveFd() ব্যবহার করতে পারেন :

  • এক্সিকিউটর থেকে স্যান্ডবক্সীতে ফাইল বর্ণনাকারীদের ম্যাপ করতে MapFd() ব্যবহার করুন। এটি স্যান্ডবক্সে ব্যবহারের জন্য নির্বাহক থেকে খোলা একটি ফাইল ভাগ করতে ব্যবহার করা যেতে পারে। একটি উদাহরণ ব্যবহার স্ট্যাটিক দেখা যেতে পারে।

    // The executor opened /proc/version and passes it to the sandboxee as stdin
    executor->ipc()->MapFd(proc_version_fd, STDIN_FILENO);
    
  • একটি সকেটপেয়ার এন্ডপয়েন্ট তৈরি করতে ReceiveFd() ব্যবহার করুন। এটি স্যান্ডবক্সীর স্ট্যান্ডার্ড আউটপুট বা স্ট্যান্ডার্ড ত্রুটিগুলি পড়তে ব্যবহার করা যেতে পারে। একটি উদাহরণ ব্যবহার টুল দেখা যেতে পারে.

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

comms API ব্যবহার করে

Sandbox2 একটি সুবিধাজনক comms API প্রদান করে। এটি নির্বাহক এবং স্যান্ডবক্সীর মধ্যে পূর্ণসংখ্যা, স্ট্রিং বা বাইট বাফারগুলি ভাগ করার একটি সহজ এবং সহজ উপায়৷ নীচে কিছু কোড স্নিপেট রয়েছে যা আপনি crc4 উদাহরণে খুঁজে পেতে পারেন।

comms API দিয়ে শুরু করার জন্য, আপনাকে প্রথমে Sandbox2 অবজেক্ট থেকে comms অবজেক্টটি পেতে হবে:

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

একবার comms অবজেক্ট উপলব্ধ হলে, Send* ফ্যামিলি অফ ফাংশনগুলির একটি ব্যবহার করে ডেটা স্যান্ডবক্সীতে পাঠানো যেতে পারে। আপনি 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 */
}

বাফারের সাথে ডেটা শেয়ার করা

আরেকটি ডেটা শেয়ারিং কার্যকারিতা হল বাফার API ব্যবহার করে প্রচুর পরিমাণে ডেটা শেয়ার করা এবং এক্সিকিউটর এবং স্যান্ডবক্সীর মধ্যে পাঠানো ব্যয়বহুল কপিগুলি এড়ানো।

এক্সিকিউটর একটি বাফার তৈরি করে, হয় আকার এবং ডেটা পাস করার জন্য, অথবা সরাসরি একটি ফাইল বর্ণনাকারী থেকে, এবং স্যান্ডবক্সিতে 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());

স্যান্ডবক্সীর পাশে, আপনাকে একটি বাফার অবজেক্টও তৈরি করতে হবে এবং এক্সিকিউটরের পাঠানো ফাইল বর্ণনাকারী থেকে ডেটা পড়তে হবে:

// 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 */
,

5. স্যান্ডবক্সীর সাথে যোগাযোগ করা

ডিফল্টরূপে, নির্বাহক ফাইল বর্ণনাকারীর মাধ্যমে স্যান্ডবক্সীর সাথে যোগাযোগ করতে পারে। এটি আপনার প্রয়োজন হতে পারে, উদাহরণস্বরূপ যদি আপনি স্যান্ডবক্সীর সাথে একটি ফাইল ভাগ করতে চান বা স্যান্ডবক্সীর স্ট্যান্ডার্ড আউটপুট পড়তে চান৷

যাইহোক, আপনার সম্ভবত নির্বাহক এবং স্যান্ডবক্সির মধ্যে আরও জটিল যোগাযোগের যুক্তির প্রয়োজন রয়েছে। comms API ( comms.h হেডার ফাইলটি দেখুন) পূর্ণসংখ্যা, স্ট্রিং, বাইট বাফার, প্রোটোবাফ বা ফাইল বর্ণনাকারী পাঠাতে ব্যবহার করা যেতে পারে।

শেয়ারিং ফাইল বর্ণনাকারী

ইন্টার-প্রসেস কমিউনিকেশন API ব্যবহার করে ( ipc.h দেখুন), আপনি MapFd() বা ReceiveFd() ব্যবহার করতে পারেন :

  • এক্সিকিউটর থেকে স্যান্ডবক্সীতে ফাইল বর্ণনাকারীদের ম্যাপ করতে MapFd() ব্যবহার করুন। এটি স্যান্ডবক্সে ব্যবহারের জন্য নির্বাহক থেকে খোলা একটি ফাইল ভাগ করতে ব্যবহার করা যেতে পারে। একটি উদাহরণ ব্যবহার স্ট্যাটিক দেখা যেতে পারে।

    // The executor opened /proc/version and passes it to the sandboxee as stdin
    executor->ipc()->MapFd(proc_version_fd, STDIN_FILENO);
    
  • একটি সকেটপেয়ার এন্ডপয়েন্ট তৈরি করতে ReceiveFd() ব্যবহার করুন। এটি স্যান্ডবক্সীর স্ট্যান্ডার্ড আউটপুট বা স্ট্যান্ডার্ড ত্রুটিগুলি পড়তে ব্যবহার করা যেতে পারে। একটি উদাহরণ ব্যবহার টুল দেখা যেতে পারে.

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

comms API ব্যবহার করে

Sandbox2 একটি সুবিধাজনক comms API প্রদান করে। এটি নির্বাহক এবং স্যান্ডবক্সীর মধ্যে পূর্ণসংখ্যা, স্ট্রিং বা বাইট বাফারগুলি ভাগ করার একটি সহজ এবং সহজ উপায়৷ নীচে কিছু কোড স্নিপেট রয়েছে যা আপনি crc4 উদাহরণে খুঁজে পেতে পারেন।

comms API দিয়ে শুরু করার জন্য, আপনাকে প্রথমে Sandbox2 অবজেক্ট থেকে comms অবজেক্টটি পেতে হবে:

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

একবার comms অবজেক্ট উপলব্ধ হলে, Send* ফ্যামিলি অফ ফাংশনগুলির একটি ব্যবহার করে ডেটা স্যান্ডবক্সীতে পাঠানো যেতে পারে। আপনি 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 */
}

বাফারের সাথে ডেটা শেয়ার করা

আরেকটি ডেটা শেয়ারিং কার্যকারিতা হল বাফার API ব্যবহার করে প্রচুর পরিমাণে ডেটা শেয়ার করা এবং এক্সিকিউটর এবং স্যান্ডবক্সীর মধ্যে পাঠানো ব্যয়বহুল কপিগুলি এড়ানো।

এক্সিকিউটর একটি বাফার তৈরি করে, হয় আকার এবং ডেটা পাস করার জন্য, অথবা সরাসরি একটি ফাইল বর্ণনাকারী থেকে, এবং স্যান্ডবক্সিতে 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());

স্যান্ডবক্সীর পাশে, আপনাকে একটি বাফার অবজেক্টও তৈরি করতে হবে এবং এক্সিকিউটরের পাঠানো ফাইল বর্ণনাকারী থেকে ডেটা পড়তে হবে:

// 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 */