در این صفحه، نحوه ایجاد کتابخانه سندباکس C/C++ خود را با Sandboxed API (SAPI) خواهید آموخت. از آن به عنوان راهنما در کنار مثال ها و مستندات کد موجود در فایل های هدر استفاده کنید.
ایجاد وابستگی
وابستگی های زیر باید روی سیستم نصب شوند:
- هسته لینوکس با پشتیبانی از UTS، IPC، کاربر، PID و فضای نام شبکه
- هدرهای API فضای کاربران لینوکس
- برای کامپایل کد خود: GCC 6 (نسخه 7 یا بالاتر ترجیح داده می شود) یا Clang 7 (یا بالاتر)
- برای تولید خودکار فایلهای هدر: Clang Python Bindings
- پایتون 3.5 یا بالاتر
- Bazel نسخه 2.2.0 یا CMake نسخه 3.12 یا بالاتر.
با استفاده از بازل
Bazel سیستم ساخت توصیه شده است و ساده ترین سیستم برای ادغام با آن است.
مستندات ما از کامپایلر Clang استفاده می کند. اگر به یک زنجیره ابزار خاص نیاز دارید (مثلاً کامپایلر، پیوند دهنده و غیره)، برای اطلاعات در مورد نحوه تغییر زنجیره ابزار کامپایلر پیش فرض، به مستندات Bazel مراجعه کنید.
Debian 10 (Buster)
برای نصب وابستگی های ساخت:
echo "deb http://storage.googleapis.com/bazel-apt stable jdk1.8" | \ sudo tee /etc/apt/sources.list.d/bazel.list
wget -qO - https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install -qy build-essential linux-libc-dev bazel python3 \ python3-pip libclang-dev
pip3 install clang
جنتو
گزینه های هسته مورد نیاز:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
برای نصب وابستگی های ساخت:
emerge dev-util/bazel dev-python/typing dev-python/clang-python
با استفاده از CMake
CMake یک سیستم متا بیلد منبع باز محبوب است که فایل های پروژه را برای ابزارهای ساخت مانند Ninja یا Make تولید می کند.
Debian 10 (Buster)
برای نصب وابستگی های ساخت:
sudo apt-get install -qy build-essential linux-libc-dev cmake ninja-build \ python3 python3-pip libclang-dev libcap-dev
pip3 install absl-py clang
جنتو
گزینه های هسته مورد نیاز:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
برای نصب وابستگی های ساخت:
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python
فرآیند توسعه
برای سندباکس یک کتابخانه C/C++، باید دو مورد را برای پروژه خود آماده کنید:
- کتابخانه Sandboxed
- کد میزبان که از عملکردی که کتابخانه Sandboxed شما در معرض نمایش قرار می دهد استفاده می کند. SAPI در طول فرآیند ساخت، شی SAPI و RPC Stub را به طور خودکار برای شما تولید می کند.
ممکن است با zlib از نمونه های Sandbox2 در اینجا آشنایی داشته باشید که یک برنامه کامل ( zpipe.c ) sandbox شده است. در مراحل زیر، نحوه استفاده از SAPI برای جعبه شنود کتابخانه zlib و استفاده از کتابخانه Sandboxed را یاد خواهید گرفت.
1. تصمیم بگیرید که کدام توابع مورد نیاز است
اگر به کد میزبان zlib ( main_zlib.cc ) نگاه کنید، می بینید که عملکرد ابزار خواندن داده ها از stdin و استفاده از تابع deflate()
zlib برای فشرده سازی داده ها تا زمانی که یک نشانگر EOF
خوانده شود است. در کل، این برنامه از سه تابع از zlib استفاده می کند:
-
deflateInit_()
: برای مقداردهی اولیه برای فشرده سازی -
deflate()
: برای انجام عملیات فشرده سازی بر روی قطعه داده -
deflateEnd()
: برای پایان دادن به فشرده سازی و آزادسازی ساختارهای داده تخصیص یافته به صورت پویا
در یک مثال واقعی، کتابخانه C/C++ را بررسی کرده و تصمیم می گیرید که کدام توابع مورد نیاز است. یک استراتژی ممکن این است که با کد میزبان شروع کنید و از کتابخانه بدون جعبه ایمنی استفاده کنید. سپس، در مرحله دوم، میتوانید کتابخانه Sandboxed را ایجاد کنید و کد میزبان را برای استفاده از فراخوانی تابع sandbox شده تطبیق دهید.
2. قانون ساخت sapi_library را بنویسید
بعد از اینکه سه تابع zlib مورد نیاز از کتابخانه zlib sandbox شده را شناسایی کردید، می توانید قانون ساخت را در فایل BUILD تعریف کنید. اسناد مربوط به قانون ساخت sapi_library
را می توانید در صفحه قوانین ساخت پیدا کنید.
قطعه کد زیر تعریف sapi_library
را برای مثال zlib SAPI نشان می دهد. با استفاده از ویژگی lib
، به Bazel دستور داده می شود که در فایل WORKSPACE کتابخانه zlib را جستجو کند.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
نتیجه این است که کتابخانه zlib sandbox شده تولید می شود. خروجی شی SAPI است که می تواند در کد میزبان گنجانده شود و برای برقراری ارتباط با کتابخانه sandboxed از طریق تماس های RPC استفاده شود. سیاست Sandbox استفاده شده در این مثال، خط مشی پیش فرض است.
3. کد میزبان را بنویسید یا تغییر دهید
اکنون زمان آن است که کتابخانه SAPI تولید شده را در کد میزبان ادغام کنیم.
Sandbox را ایجاد کنید
استفاده از sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());
برای ایجاد یک شی جعبه شنی
استفاده از sapi::zlib::ZlibApi api(&sandbox);
برای نمونه سازی SAPI Object و در نتیجه در دسترس قرار دادن توابع sandboxed برای استفاده.
از انواع SAPI استفاده کنید
انواع SAPI انواع خاصی در قالب کلاس های C++ هستند که SAPI ارائه می دهد زیرا گاهی اوقات نوع C معمولی کار نمی کنند.
اولین استفاده از نوع SAPI را می توان در اعلان strm
مشاهده کرد، جایی که یک ساختار SAPI استفاده می شود: sapi::v::Struct<sapi::zlib::z_stream> strm;
نوع قالب ( sapi::zlib::z_stream
) نمونه خوبی از کدهایی است که به طور خودکار توسط قانون ساخت تولید می شود.
برای جزئیات بیشتر به صفحه متغیرها نگاه کنید.
برقراری تماس های API
برای برقراری تماس با defalteInit_
، deflate
یا deflateEnd
، از شیء SAPI استفاده کنید. اگر تصمیم دارید از رویکرد "تغییر" استفاده کنید، باید مطمئن شوید که پارامترهای تابع با مقادیر مورد انتظار مطابقت دارند.
نمونه ای از هر یک از تماس های مثال zlib :
api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION, version.PtrBefore(), sizeof(sapi::zlib::z_stream));
api.deflate(strm.PtrBoth(), flush);
api.deflateEnd(strm.PtrBoth()).IgnoreError();
استفاده از تراکنش های SAPI
SAPI کد میزبان را از کتابخانه Sandboxed جدا می کند و به تماس گیرنده این امکان را می دهد که درخواست های پردازش داده مشکل ساز را راه اندازی مجدد یا لغو کند. SAPI Transaction یک قدم جلوتر می رود و به طور خودکار فرآیندهای شکست خورده را تکرار می کند.
برای جزئیات بیشتر به صفحه معاملات SAPI نگاهی بیندازید.
مثال ها
در زیر نمونه ها می توانید چند کتابخانه را پیدا کنید که قبلاً توسط تیم SAPI تهیه شده است.
،در این صفحه، نحوه ایجاد کتابخانه سندباکس C/C++ خود را با Sandboxed API (SAPI) خواهید آموخت. از آن به عنوان راهنما در کنار مثال ها و مستندات کد موجود در فایل های هدر استفاده کنید.
ایجاد وابستگی
وابستگی های زیر باید روی سیستم نصب شوند:
- هسته لینوکس با پشتیبانی از UTS، IPC، کاربر، PID و فضای نام شبکه
- هدرهای API فضای کاربران لینوکس
- برای کامپایل کد خود: GCC 6 (نسخه 7 یا بالاتر ترجیح داده می شود) یا Clang 7 (یا بالاتر)
- برای تولید خودکار فایلهای هدر: Clang Python Bindings
- پایتون 3.5 یا بالاتر
- Bazel نسخه 2.2.0 یا CMake نسخه 3.12 یا بالاتر.
با استفاده از بازل
Bazel سیستم ساخت توصیه شده است و ساده ترین سیستم برای ادغام با آن است.
مستندات ما از کامپایلر Clang استفاده می کند. اگر به یک زنجیره ابزار خاص نیاز دارید (مثلاً کامپایلر، پیوند دهنده و غیره)، برای اطلاعات در مورد نحوه تغییر زنجیره ابزار کامپایلر پیش فرض، به مستندات Bazel مراجعه کنید.
Debian 10 (Buster)
برای نصب وابستگی های ساخت:
echo "deb http://storage.googleapis.com/bazel-apt stable jdk1.8" | \ sudo tee /etc/apt/sources.list.d/bazel.list
wget -qO - https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
sudo apt-get update
sudo apt-get install -qy build-essential linux-libc-dev bazel python3 \ python3-pip libclang-dev
pip3 install clang
جنتو
گزینه های هسته مورد نیاز:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
برای نصب وابستگی های ساخت:
emerge dev-util/bazel dev-python/typing dev-python/clang-python
با استفاده از CMake
CMake یک سیستم متا بیلد منبع باز محبوب است که فایل های پروژه را برای ابزارهای ساخت مانند Ninja یا Make تولید می کند.
Debian 10 (Buster)
برای نصب وابستگی های ساخت:
sudo apt-get install -qy build-essential linux-libc-dev cmake ninja-build \ python3 python3-pip libclang-dev libcap-dev
pip3 install absl-py clang
جنتو
گزینه های هسته مورد نیاز:
General setup --->
-*- Namespaces support
[*] UTS namespace
[*] IPC namespace
[*] User namespace (EXPERIMENTAL)
[*] PID Namespaces
[*] Network namespace
برای نصب وابستگی های ساخت:
emerge sys-kernel/linux-headers dev-util/cmake dev-util/ninja \
dev-python/clang-python
فرآیند توسعه
برای سندباکس یک کتابخانه C/C++، باید دو مورد را برای پروژه خود آماده کنید:
- کتابخانه Sandboxed
- کد میزبان که از عملکردی که کتابخانه Sandboxed شما در معرض نمایش قرار می دهد استفاده می کند. SAPI در طول فرآیند ساخت، شی SAPI و RPC Stub را به طور خودکار برای شما تولید می کند.
ممکن است با zlib از نمونه های Sandbox2 در اینجا آشنایی داشته باشید که یک برنامه کامل ( zpipe.c ) sandbox شده است. در مراحل زیر، نحوه استفاده از SAPI برای جعبه شنود کتابخانه zlib و استفاده از کتابخانه Sandboxed را یاد خواهید گرفت.
1. تصمیم بگیرید که کدام توابع مورد نیاز است
اگر به کد میزبان zlib ( main_zlib.cc ) نگاه کنید، می بینید که عملکرد ابزار خواندن داده ها از stdin و استفاده از تابع deflate()
zlib برای فشرده سازی داده ها تا زمانی که یک نشانگر EOF
خوانده شود است. در کل، این برنامه از سه تابع از zlib استفاده می کند:
-
deflateInit_()
: برای مقداردهی اولیه برای فشرده سازی -
deflate()
: برای انجام عملیات فشرده سازی بر روی قطعه داده -
deflateEnd()
: برای پایان دادن به فشرده سازی و آزادسازی ساختارهای داده تخصیص یافته به صورت پویا
در یک مثال واقعی، کتابخانه C/C++ را بررسی کرده و تصمیم می گیرید که کدام توابع مورد نیاز است. یک استراتژی ممکن این است که با کد میزبان شروع کنید و از کتابخانه بدون جعبه ایمنی استفاده کنید. سپس، در مرحله دوم، میتوانید کتابخانه Sandboxed را ایجاد کنید و کد میزبان را برای استفاده از فراخوانی تابع sandbox شده تطبیق دهید.
2. قانون ساخت sapi_library را بنویسید
بعد از اینکه سه تابع zlib مورد نیاز از کتابخانه zlib sandbox شده را شناسایی کردید، می توانید قانون ساخت را در فایل BUILD تعریف کنید. اسناد مربوط به قانون ساخت sapi_library
را می توانید در صفحه قوانین ساخت پیدا کنید.
قطعه کد زیر تعریف sapi_library
را برای مثال zlib SAPI نشان می دهد. با استفاده از ویژگی lib
، به Bazel دستور داده می شود که در فایل WORKSPACE کتابخانه zlib را جستجو کند.
sapi_library(
name = "zlib-sapi",
srcs = [],
hdrs = [],
functions = [
"deflateInit_",
"deflate",
"deflateEnd",
],
lib = "@net_zlib//:zlib",
lib_name = "Zlib",
namespace = "sapi::zlib",
)
نتیجه این است که کتابخانه zlib sandbox شده تولید می شود. خروجی شی SAPI است که می تواند در کد میزبان گنجانده شود و برای برقراری ارتباط با کتابخانه sandboxed از طریق تماس های RPC استفاده شود. سیاست Sandbox استفاده شده در این مثال، خط مشی پیش فرض است.
3. کد میزبان را بنویسید یا تغییر دهید
اکنون زمان آن است که کتابخانه SAPI تولید شده را در کد میزبان ادغام کنیم.
Sandbox را ایجاد کنید
استفاده از sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());
برای ایجاد یک شی جعبه شنی
استفاده از sapi::zlib::ZlibApi api(&sandbox);
برای نمونه سازی SAPI Object و در نتیجه در دسترس قرار دادن توابع sandboxed برای استفاده.
از انواع SAPI استفاده کنید
انواع SAPI انواع خاصی در قالب کلاس های C++ هستند که SAPI ارائه می دهد زیرا گاهی اوقات نوع C معمولی کار نمی کنند.
اولین استفاده از نوع SAPI را می توان در اعلان strm
مشاهده کرد، جایی که یک ساختار SAPI استفاده می شود: sapi::v::Struct<sapi::zlib::z_stream> strm;
نوع قالب ( sapi::zlib::z_stream
) نمونه خوبی از کدهایی است که به طور خودکار توسط قانون ساخت تولید می شود.
برای جزئیات بیشتر به صفحه متغیرها نگاه کنید.
برقراری تماس های API
برای برقراری تماس با defalteInit_
، deflate
یا deflateEnd
، از شیء SAPI استفاده کنید. اگر تصمیم دارید از رویکرد "تغییر" استفاده کنید، باید مطمئن شوید که پارامترهای تابع با مقادیر مورد انتظار مطابقت دارند.
نمونه ای از هر یک از تماس های مثال zlib :
api.deflateInit_(strm.PtrBoth(), Z_DEFAULT_COMPRESSION, version.PtrBefore(), sizeof(sapi::zlib::z_stream));
api.deflate(strm.PtrBoth(), flush);
api.deflateEnd(strm.PtrBoth()).IgnoreError();
استفاده از تراکنش های SAPI
SAPI کد میزبان را از کتابخانه Sandboxed جدا می کند و به تماس گیرنده این امکان را می دهد که درخواست های پردازش داده مشکل ساز را راه اندازی مجدد یا لغو کند. SAPI Transaction یک قدم جلوتر می رود و به طور خودکار فرآیندهای شکست خورده را تکرار می کند.
برای جزئیات بیشتر به صفحه معاملات SAPI نگاهی بیندازید.
مثال ها
در زیر نمونه ها می توانید چند کتابخانه را پیدا کنید که قبلاً توسط تیم SAPI تهیه شده است.