ستتعلم في هذه الصفحة كيفية إنشاء مكتبة C/C++ في وضع الحماية باستخدام واجهة برمجة تطبيقات Sandboxed API (SAPI). يمكنك استخدامها كدليل إلى جانب الأمثلة ومستندات الترميز في ملفات العناوين.
بناء التبعيات
يجب تثبيت التبعيات التالية على النظام:
- نواة Linux مع دعم لـ UTS وIPC والمستخدم وPID ومساحات اسم الشبكة
- عناوين واجهة برمجة التطبيقات لمساحة المستخدم في Linux
- لتجميع الرمز الخاص بك: GCC 6 (الإصدار 7 أو إصدار أعلى يفضل) أو Clang 7 (أو إصدار أحدث)
- لإنشاء ملفات العناوين تلقائيًا: روابط Clang Python
- Python 3.5 أو إصدار أحدث
- الإصدار 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
جنتو
خيارات النواة المطلوبة:
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++، سيتعين عليك إعداد عنصرين لمشروعك:
- المكتبة المستندة إلى وضع الحماية
- رمز المضيف الذي سيستفيد من الوظائف التي تعرضها "مكتبة العناصر في وضع الحماية". سينشئ لك 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 لها خطوة أخرى إلى الأمام وتكرر تلقائيًا العمليات غير الناجحة.
ألقِ نظرة على صفحة معاملات SAPI لمزيد من التفاصيل.
أمثلة
ضمن الأمثلة، يمكنك العثور على بعض المكتبات التي سبق أن أعدّها فريق SAPI.