بدء استخدام واجهة برمجة التطبيقات في وضع الحماية

في هذه الصفحة، ستتعرّف على كيفية إنشاء مكتبة C/C++ في وضع الحماية باستخدام Sandboxed API (SAPI). يمكنك استخدامها كدليل إلى جانب الـ أمثلة ووثائق الرموز في ملفات العناوين.

إنشاء المهام التابعة

يجب تثبيت المهام التابعة التالية على النظام:

  • نواة Linux مع دعم مساحات أسماء UTS وIPC والمستخدمين وأرقام تعريف العمليات والشبكة
  • عناوين واجهة برمجة تطبيقات مساحة مستخدمي Linux
  • لتجميع الرمز البرمجي: GCC 6 (يُفضّل الإصدار 7 أو الإصدارات الأحدث) أو Clang 7 (أو الإصدارات الأحدث)
  • لإنشاء ملفات العناوين التي تم إنشاؤها تلقائيًا: Clang Python Bindings
  • ‫Python 3.5 أو الإصدارات الأحدث
  • ‫Bazel الإصدار 2.2.0 أو CMake الإصدار 3.12 أو الإصدارات الأحدث.
    • ‫CMake فقط: GNU Make أو إصدار من عناوين مكتبة libcap وأداة تجميع مثل Ninja (يُنصح بها).

باستخدام 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://releases.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 Stub نيابةً عنك أثناء عملية التجميع.

قد تكون على دراية بمكتبة 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 للبحث عن مكتبة zlib في ملف WORKSPACE.

sapi_library(
    name = "zlib-sapi",
    srcs = [],
    hdrs = [],
    functions = [
        "deflateInit_",
        "deflate",
        "deflateEnd",
    ],
    lib = "@net_zlib//:zlib",
    lib_name = "Zlib",
    namespace = "sapi::zlib",
)

والنتيجة هي إنشاء مكتبة zlib في وضع الحماية. الناتج هو كائن SAPI الذي يمكن تضمينه في رمز المضيف واستخدامه للتواصل مع المكتبة في وضع الحماية باستخدام طلبات RPC.

يستخدم هذا المثال إعدادات وضع الحماية التلقائية التي يوفّرها DefaultConfig (sapi::SandboxConfig::DefaultConfig()).

‫3. كتابة رمز المضيف أو تغييره

حان الآن وقت دمج مكتبة SAPI التي تم إنشاؤها في رمز المضيف.

إنشاء وضع الحماية

استخدِم sapi::zlib::ZlibSandbox sandbox; لإنشاء كائن وضع الحماية.

استخدِم sapi::zlib::ZlibApi api(&sandbox); لإنشاء مثيل لكائن SAPI، ما يتيح استخدام الدوال في وضع الحماية.

لتخصيص سياسة وضع الحماية أو العلامات أو متغيرات البيئة أو الحدود، ابدأ من sapi::SandboxConfig::DefaultConfig()، وعدِّل الحقول ذات الصلة (باستخدام sapi::Sandbox2Config::DefaultPolicyBuilder()، sapi::SandboxConfig::DefaultFlags()، أو sapi::SandboxConfig::DefaultEnvironmentVariables() للحفاظ على الإعدادات الأساسية)، ومرِّر sapi::SandboxConfig إلى الدالة الإنشائية لوضع الحماية:

sapi::SandboxConfig config = sapi::SandboxConfig::DefaultConfig();
config.sandbox2.policy = sapi::Sandbox2Config::DefaultPolicyBuilder()
                             .AddFile("/path/to/file")
                             .BuildOrDie();
auto flags = sapi::SandboxConfig::DefaultFlags();
flags["my_flag"] = "value";
config.command_line_flags = std::move(flags);

sapi::zlib::ZlibSandbox sandbox(std::move(config));

استخدام أنواع 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.