في هذه الصفحة، ستتعرّف على كيفية إنشاء مكتبة C/C++ معزولة باستخدام Sandboxed API (SAPI). يمكنك استخدامها كدليل إلى جانب الأمثلة ومستندات الرموز البرمجية في ملفات العناوين.
إنشاء التبعيات
يجب تثبيت الاعتمادات التالية على النظام:
- نواة Linux التي تتوافق مع مساحات أسماء UTS وIPC والمستخدم ومعرّف العملية (PID) والشبكة
- عناوين واجهة برمجة التطبيقات لمساحة المستخدم في Linux
- لتجميع الرمز البرمجي: GCC 6 (يُفضّل الإصدار 7 أو إصدار أحدث) أو Clang 7 (أو إصدار أحدث)
- لإنشاء ملفات العناوين تلقائيًا: Clang Python Bindings
- الإصدار 3.5 أو الإصدارات الأحدث من Python
- الإصدار 2.2.0 من Bazel أو الإصدار 3.12 أو الإصدارات الأحدث من CMake
استخدام Bazel
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
Gentoo
خيارات النواة المطلوبة:
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
Gentoo
خيارات النواة المطلوبة:
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++، عليك إعداد عنصرَين لمشروعك:
- مكتبة وضع الحماية
- رمز المضيف الذي سيستفيد من الوظائف التي توفّرها "المكتبة المحمية" ستنشئ SAPI كائن SAPI ورمز RPC تلقائيًا أثناء عملية الإنشاء.
قد تكون على دراية بمكتبة zlib من أمثلة Sandbox2، حيث تم وضع برنامج كامل (zpipe.c) في وضع الحماية. في الخطوات التالية، ستتعرّف على كيفية استخدام SAPI من أجل وضع مكتبة zlib في وضع الحماية واستخدام "المكتبة المحمية".
1. تحديد الوظائف المطلوبة
إذا نظرت إلى رمز المضيف zlib
(main_zlib.cc)،
يمكنك ملاحظة أنّ وظيفة الأداة هي قراءة البيانات من stdin واستخدام
دالة deflate()
في zlib لضغط البيانات إلى أن تتم قراءة العلامة EOF
.
يستخدم البرنامج إجمالاً ثلاث دوال من zlib:
-
deflateInit_()
: لتهيئة الضغط -
deflate()
: لتنفيذ عملية الضغط على جزء البيانات deflateEnd()
: لإنهاء عملية الضغط وتحرير بنى البيانات المخصّصة ديناميكيًا
في مثال واقعي، ستراجع مكتبة C/C++ وتحدّد الوظائف التي تحتاج إليها. تتمثّل إحدى الاستراتيجيات المحتملة في البدء باستخدام رمز المضيف واستخدام المكتبة بدون وضع الحماية. بعد ذلك، يمكنك في خطوة ثانية إنشاء "المكتبة المحمية" وتعديل "رمز التطبيق المضيف" لاستخدام طلبات الدوال المحمية.
2. كتابة قاعدة إنشاء sapi_library
بعد تحديد دوال zlib الثلاث المطلوبة من مكتبة zlib المحصورة، يمكنك تحديد قاعدة الإنشاء في ملف 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 في بيئة معزولة. الناتج هو كائن SAPI الذي يمكن تضمينه في رمز المضيف واستخدامه للتواصل مع المكتبة المحصورة في بيئة آمنة من خلال طلبات RPC. سياسة وضع الحماية المستخدَمة في هذا المثال هي السياسة التلقائية.
3- كتابة رمز المضيف أو تغييره
حان الوقت الآن لدمج مكتبة SAPI التي تم إنشاؤها في رمز المضيف.
إنشاء "صندوق الإبداع"
استخدِم sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());
لإنشاء عنصر وضع الحماية.
استخدِم sapi::zlib::ZlibApi api(&sandbox);
لإنشاء مثيل لكائن SAPI، وبالتالي إتاحة استخدام الدوال المحصورة في بيئة الاختبار المعزولة.
استخدام أنواع SAPI
أنواع SAPI هي أنواع خاصة في شكل فئات C++ توفّرها SAPI لأنّ أنواع C العادية لن تعمل في بعض الأحيان.
يمكن ملاحظة الاستخدام الأول لأحد أنواع SAPI في تعريف strm
، حيث يتم استخدام بنية SAPI: sapi::v::Struct<sapi::zlib::z_stream> strm;
نوع النموذج (sapi::zlib::z_stream
) هو مثال جيد على الرمز الذي يتم إنشاؤه تلقائيًا بواسطة قاعدة الإنشاء.
يمكنك الاطّلاع على صفحة المتغيرات للحصول على مزيد من التفاصيل.
تقديم طلبات بيانات من واجهة برمجة التطبيقات
لإجراء مكالمات إلى 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 "رمز التطبيق المضيف" عن "المكتبة المحصورة" وتمنح المتصل إمكانية إعادة تشغيل طلبات معالجة البيانات التي تتضمّن مشاكل أو إيقافها. تتجاوز SAPI Transaction ذلك وتكرّر تلقائيًا العمليات التي تعذّر إجراؤها.
يمكنك الاطّلاع على صفحة معاملات SAPI لمزيد من التفاصيل.
أمثلة
ضمن أمثلة، يمكنك العثور على بعض المكتبات التي أعدّها فريق SAPI مسبقًا.