1. একটি স্যান্ডবক্স এক্সিকিউটর পদ্ধতি বেছে নিন

স্যান্ডবক্সিং একজন নির্বাহক দিয়ে শুরু হয় ( স্যান্ডবক্স এক্সিকিউটর দেখুন), যেটি স্যান্ডবক্সী চালানোর জন্য দায়ী। executor.h হেডার ফাইলে এই উদ্দেশ্যে প্রয়োজনীয় API রয়েছে। এপিআই খুবই নমনীয় এবং আপনার ব্যবহারের ক্ষেত্রে কোনটি সবচেয়ে ভালো কাজ করে তা বেছে নিতে দেয়। নিম্নলিখিত বিভাগগুলি 3টি ভিন্ন পদ্ধতি বর্ণনা করে যা থেকে আপনি চয়ন করতে পারেন৷

পদ্ধতি 1: একাকী - স্যান্ডবক্সিং ইতিমধ্যে সক্ষম করে একটি বাইনারি চালান

এটি স্যান্ডবক্সিং ব্যবহার করার সবচেয়ে সহজ উপায় এবং যখন আপনি একটি সম্পূর্ণ বাইনারি স্যান্ডবক্স করতে চান যার জন্য আপনার কাছে কোনও উত্স কোড নেই তখন এটি প্রস্তাবিত পদ্ধতি৷ এটি স্যান্ডবক্সিং ব্যবহার করার সবচেয়ে নিরাপদ উপায়, কারণ সেখানে কোনো আনস্যান্ডবক্সিং ইনিশিয়ালাইজেশন নেই যা বিরূপ প্রভাব ফেলতে পারে।

নিম্নলিখিত কোড স্নিপেটে, আমরা স্যান্ডবক্স করার জন্য বাইনারিটির পথ এবং একটি execve syscall-এ যে আর্গুমেন্টগুলি পাস করতে হবে তা সংজ্ঞায়িত করি। আপনি executor.h হেডার ফাইলে দেখতে পাচ্ছেন, আমরা envp এর জন্য একটি মান নির্দিষ্ট করি না এবং তাই প্যারেন্ট প্রক্রিয়া থেকে পরিবেশটি অনুলিপি করি। মনে রাখবেন, প্রথম আর্গুমেন্ট সর্বদা কার্যকর করা প্রোগ্রামের নাম, এবং আমাদের স্নিপেট অন্য কোন আর্গুমেন্টকে সংজ্ঞায়িত করে না।

এই নির্বাহক পদ্ধতির উদাহরণ হল: স্ট্যাটিক এবং টুল

#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);

পদ্ধতি 2: Sandbox2 Forkserver - নির্বাহককে বলুন কখন স্যান্ডবক্স করা হবে

এই পদ্ধতিটি শুরু করার সময় আনস্যান্ডবক্সড হওয়ার নমনীয়তা প্রদান করে এবং তারপরে ::sandbox2::Client::SandboxMeHere() কল করে স্যান্ডবক্সিংয়ে কখন প্রবেশ করতে হবে তা বেছে নেওয়া হয়। আপনি যখন স্যান্ডবক্সিং শুরু করতে চান তখন এটি আপনাকে কোডে সংজ্ঞায়িত করতে সক্ষম হতে হবে এবং এটি একক-থ্রেডেড হতে হবে (কেন FAQ এ পড়ুন)।

নিম্নলিখিত কোড স্নিপেটে, আমরা উপরের পদ্ধতি 1 এ বর্ণিত একই কোড ব্যবহার করি। যাইহোক, প্রারম্ভের সময় একটি আনস্যান্ডবক্সড পদ্ধতিতে প্রোগ্রাম চালানোর অনুমতি দেওয়ার জন্য, আমরা 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 ) যখন এটি স্যান্ডবক্সে প্রবেশ করবে তখন তাকে অবহিত করে।

পদ্ধতি 3: কাস্টম ফর্কসার্ভার - একটি বাইনারি প্রস্তুত করুন, কাঁটাচামচের অনুরোধের জন্য অপেক্ষা করুন এবং নিজের হাতে স্যান্ডবক্স করুন

এই মোডটি আপনাকে একটি বাইনারি শুরু করতে, এটিকে স্যান্ডবক্সিংয়ের জন্য প্রস্তুত করতে এবং, আপনার বাইনারির জীবনচক্রের একটি নির্দিষ্ট মুহুর্তে, এটি নির্বাহকের কাছে উপলব্ধ করতে দেয়।

নির্বাহক আপনার বাইনারিতে একটি ফর্ক অনুরোধ পাঠাবে, যা 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 নেই। আরেকটি সাধারণ ব্যবহারের উদাহরণ হতে পারে যখন স্যান্ডবক্সির একটি দীর্ঘ, CPU- নিবিড় ইনিশিয়ালাইজেশন থাকে যা অবিশ্বস্ত ডেটা প্রক্রিয়া করার আগে চালানো যেতে পারে।

এই নির্বাহক পদ্ধতির একটি উদাহরণের জন্য, custom_fork দেখুন।

,

1. একটি স্যান্ডবক্স এক্সিকিউটর পদ্ধতি বেছে নিন

স্যান্ডবক্সিং একজন নির্বাহক দিয়ে শুরু হয় ( স্যান্ডবক্স এক্সিকিউটর দেখুন), যেটি স্যান্ডবক্সী চালানোর জন্য দায়ী। executor.h হেডার ফাইলে এই উদ্দেশ্যে প্রয়োজনীয় API রয়েছে। এপিআই খুবই নমনীয় এবং আপনার ব্যবহারের ক্ষেত্রে কোনটি সবচেয়ে ভালো কাজ করে তা বেছে নিতে দেয়। নিম্নলিখিত বিভাগগুলি 3টি ভিন্ন পদ্ধতি বর্ণনা করে যা থেকে আপনি চয়ন করতে পারেন৷

পদ্ধতি 1: একাকী - স্যান্ডবক্সিং ইতিমধ্যে সক্ষম করে একটি বাইনারি চালান

এটি স্যান্ডবক্সিং ব্যবহার করার সবচেয়ে সহজ উপায় এবং যখন আপনি একটি সম্পূর্ণ বাইনারি স্যান্ডবক্স করতে চান যার জন্য আপনার কাছে কোনও উত্স কোড নেই তখন এটি প্রস্তাবিত পদ্ধতি৷ এটি স্যান্ডবক্সিং ব্যবহার করার সবচেয়ে নিরাপদ উপায়, কারণ সেখানে কোনো আনস্যান্ডবক্সিং ইনিশিয়ালাইজেশন নেই যা বিরূপ প্রভাব ফেলতে পারে।

নিম্নলিখিত কোড স্নিপেটে, আমরা স্যান্ডবক্স করার জন্য বাইনারিটির পথ এবং একটি execve syscall-এ যে আর্গুমেন্টগুলি পাস করতে হবে তা সংজ্ঞায়িত করি। আপনি executor.h হেডার ফাইলে দেখতে পাচ্ছেন, আমরা envp এর জন্য একটি মান নির্দিষ্ট করি না এবং তাই প্যারেন্ট প্রক্রিয়া থেকে পরিবেশটি অনুলিপি করি। মনে রাখবেন, প্রথম আর্গুমেন্ট সর্বদা কার্যকর করা প্রোগ্রামের নাম, এবং আমাদের স্নিপেট অন্য কোন আর্গুমেন্টকে সংজ্ঞায়িত করে না।

এই নির্বাহক পদ্ধতির উদাহরণ হল: স্ট্যাটিক এবং টুল

#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);

পদ্ধতি 2: Sandbox2 Forkserver - নির্বাহককে বলুন কখন স্যান্ডবক্স করা হবে

এই পদ্ধতিটি শুরু করার সময় আনস্যান্ডবক্সড হওয়ার নমনীয়তা প্রদান করে এবং তারপরে ::sandbox2::Client::SandboxMeHere() কল করে স্যান্ডবক্সিংয়ে কখন প্রবেশ করতে হবে তা বেছে নেওয়া হয়। আপনি যখন স্যান্ডবক্সিং শুরু করতে চান তখন এটি আপনাকে কোডে সংজ্ঞায়িত করতে সক্ষম হতে হবে এবং এটি একক-থ্রেডেড হতে হবে (কেন FAQ এ পড়ুন)।

নিম্নলিখিত কোড স্নিপেটে, আমরা উপরের পদ্ধতি 1 এ বর্ণিত একই কোড ব্যবহার করি। যাইহোক, প্রারম্ভের সময় একটি আনস্যান্ডবক্সড পদ্ধতিতে প্রোগ্রাম চালানোর অনুমতি দেওয়ার জন্য, আমরা 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 ) যখন এটি স্যান্ডবক্সে প্রবেশ করবে তখন তাকে অবহিত করে।

পদ্ধতি 3: কাস্টম ফর্কসার্ভার - একটি বাইনারি প্রস্তুত করুন, কাঁটাচামচের অনুরোধের জন্য অপেক্ষা করুন এবং নিজের হাতে স্যান্ডবক্স করুন

এই মোডটি আপনাকে একটি বাইনারি শুরু করতে, এটিকে স্যান্ডবক্সিংয়ের জন্য প্রস্তুত করতে এবং, আপনার বাইনারির জীবনচক্রের একটি নির্দিষ্ট মুহুর্তে, এটি নির্বাহকের কাছে উপলব্ধ করতে দেয়।

নির্বাহক আপনার বাইনারিতে একটি ফর্ক অনুরোধ পাঠাবে, যা 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 নেই। আরেকটি সাধারণ ব্যবহারের উদাহরণ হতে পারে যখন স্যান্ডবক্সির একটি দীর্ঘ, CPU- নিবিড় ইনিশিয়ালাইজেশন থাকে যা অবিশ্বস্ত ডেটা প্রক্রিয়া করার আগে চালানো যেতে পারে।

এই নির্বাহক পদ্ধতির একটি উদাহরণের জন্য, custom_fork দেখুন।