يشجّع Android بشدة المصنّعين الأصليين للأجهزة على اختبار عمليات تنفيذ SELinux بدقة. عندما يطبّق المصنّعون حزمة SELinux، عليهم تطبيق المحاولة الجديدة السياسة على مجموعة اختبارية من الأجهزة أولاً.
بعد تطبيق سياسة جديدة، تأكَّد من أنّ SELinux يعمل في
الوضع الصحيح على الجهاز من خلال إصدار الأمر getenforce
.
يؤدي ذلك إلى طباعة وضع SELinux الشامل: إما "فرض" أو "سماح". لتحديد
وضع SELinux لكل نطاق، عليك فحص الملفات
المقابلة أو تشغيل أحدث إصدار من sepolicy-analyze
باستخدام
علامة (-p
) المناسبة، الموجودة في
/platform/system/sepolicy/tools/
.
عمليات رفض القراءة
تحقَّق من الأخطاء التي يتم توجيهها كسجلات أحداث إلى dmesg
وlogcat
ويمكن عرضها على الجهاز. على المصنّعين examiningفحص إخراج SELinux لتحديد dmesg
على هذه الأجهزة
وتحسين الإعدادات قبل الإصدار العلني في الوضع المتساهل ثم التبديل
إلى الوضع الصارم. تحتوي رسائل سجلّ SELinux على avc:
، وبالتالي يمكن
العثور عليها بسهولة باستخدام grep
. يمكن تسجيل سجلات الرفض الحالية من خلال تشغيل cat /proc/kmsg
أو الحصول على سجلات الرفض من عملية التشغيل السابقة عن طريق تشغيل cat /sys/fs/pstore/console-ramoops
.
تكون رسائل خطأ SELinux محدودة بمعدَّل بعد اكتمال التمهيد لتجنب إهدار السجلات. للتأكّد من رؤية جميع الرسائل ذات الصلة، يمكنك إيقاف ذلك
عن طريق تشغيل adb shell auditctl -r 0
.
باستخدام هذا الإخراج، يمكن للشركات المصنعة تحديد متى ينتهك مستخدمو النظام أو المكونات سياسة SELinux. ويمكن للشركات المصنِّعة بعد ذلك إصلاح هذا السلوك السيئ، إما من خلال إجراء تغييرات على البرنامج أو سياسة SELinux أو كليهما.
على وجه التحديد، تشير رسائل السجلّ هذه إلى العمليات التي ستتعطّل في "وضع التنفيذ" وسبب ذلك. يُرجى الاطّلاع على المثال أدناه:
avc: denied { connectto } for pid=2671 comm="ping" path="/dev/socket/dnsproxyd" scontext=u:r:shell:s0 tcontext=u:r:netd:s0 tclass=unix_stream_socket
فسّر هذا الناتج على النحو التالي:
- يمثّل الرمز
{ connectto }
أعلاه الإجراء الذي يتم اتّخاذه. إلى جانب علامةtclass
في النهاية (unix_stream_socket
)، توضّح لك هذه العلامة ما كان يتم العمل عليه تقريبًا. في هذه الحالة، كان هناك شيء يحاول الاتصال بمقبس بث unix. - يُعلمك الرمز
scontext (u:r:shell:s0)
بالسياق الذي بدأ الإجراء. في هذه الحالة، يكون الأمر شيئًا مثل واجهة الأوامر. - توضِّح لك السمة
tcontext (u:r:netd:s0)
سياق الهدف من الإجراء. وفي هذه الحالة، يكون لدى Unix_stream_socket مملوك لشركةnetd
. - يمنحك الرمز
comm="ping"
في أعلى الصفحة تلميحًا إضافيًا حول ما كان يتم تنفيذه في وقت إنشاء الرفض. في هذه الحالة، يعد تلميحًا جيدًا.
مثال آخر:
adb shell su root dmesg | grep 'avc: '
جهاز إخراج الصوت:
<5> type=1400 audit: avc: denied { read write } for pid=177 comm="rmt_storage" name="mem" dev="tmpfs" ino=6004 scontext=u:r:rmt:s0 tcontext=u:object_r:kmem_device:s0 tclass=chr_file
في ما يلي العناصر الرئيسية من هذا الرفض:
- الإجراء: يتم تمييز الإجراء الذي تمّت محاولة تنفيذه بين قوسَين،
read write
أوsetenforce
. - المُنفِّذ: يمثّل إدخال
scontext
(سياق المصدر) المُنفِّذ، وفي هذه الحالة الخادمrmt_storage
. - العنصر: يمثّل إدخال
tcontext
(السياق المستهدَف) العنصر الذي يتم اتّخاذ إجراء بشأنه، وفي هذه الحالة kmem. - النتيجة - يشير الإدخال
tclass
(الفئة المستهدفة) إلى نوع العنصر الذي يتم اتخاذ إجراء بشأنه، في هذه الحالةchr_file
(جهاز حرف).
تفريغ حزم المستخدم والنواة
في بعض الحالات، لا تكون المعلومات الواردة في سجلّ الأحداث كافية لتحديد مصدر الرفض. غالبًا ما يكون من المفيد جمع سلسلة الاتصال، بما في ذلك النواة kernel و مساحة المستخدم، لفهم سبب حدوث الرفض بشكل أفضل.
تحدِّد نواة التشغيل الحديثة نقطة تتبُّع باسم avc:selinux_audited
. استخدِم Android
simpleperf
لتفعيل نقطة التتبّع هذه والتقاط سلسلة الاتصال.
الإعدادات المتوافقة
- يتوافق الإصدار 5.10 من Linux kernel >= 5.10، ولا سيّما فروع Android Common Kernel،
Mainline،
وandroid12-5.10
.
يمكنك أيضًا استخدام الفرع android12-5.4. يمكنك استخدام
simpleperf
لتحديد ما إذا تم تحديد نقطة التتبّع على جهازك:adb root && adb shell simpleperf list | grep avc:selinux_audited
. بالنسبة إلى إصدارات النواة الأخرى، يمكنك اختيار المساهمات التالية: dd81662 و 30969bc. - من المفترض أن يكون من الممكن إعادة إنتاج الحدث الذي تُجري تصحيح أخطاء له. لا يمكن استخدام أحداث وقت التشغيل باستخدام Simpleperf، ولكن قد يظل بإمكانك إعادة تشغيل الخدمة لبدء الحدث.
تسجيل سلسلة المكالمات
الخطوة الأولى هي تسجيل الحدث باستخدام simpleperf record
:
adb shell -t "cd /data/local/tmp && su root simpleperf record -a -g -e avc:selinux_audited"
ومن ثم، يجب تشغيل الحدث الذي تسبب في الرفض. بعد ذلك، من المفترض أن يتم
إيقاف التسجيل. في هذا المثال، باستخدام Ctrl-c
، كان يجب أن يكون قد تم أخذ العيّنة:
^Csimpleperf I cmd_record.cpp:751] Samples recorded: 1. Samples lost: 0.
أخيرًا، يمكن استخدام simpleperf report
لفحص تتبُّع تسلسل استدعاء الدوال البرمجية الذي تم التقاطه.
على سبيل المثال:
adb shell -t "cd /data/local/tmp && su root simpleperf report -g --full-callgraph" [...] Children Self Command Pid Tid Shared Object Symbol 100.00% 0.00% dmesg 3318 3318 /apex/com.android.runtime/lib64/bionic/libc.so __libc_init | -- __libc_init | -- main toybox_main toy_exec_which dmesg_main klogctl entry_SYSCALL_64_after_hwframe do_syscall_64 __x64_sys_syslog do_syslog selinux_syslog slow_avc_audit common_lsm_audit avc_audit_post_callback avc_audit_post_callback
سلسلة الاتصال المذكورة أعلاه هي نواة موحَّدة وسلسلة مكالمات userspace. فهي تمنحك نظرة أفضل لتدفق الرمز عن طريق بدء التتبع من مساحة المستخدم وصولاً إلى النواة (kernel) حيث يحدث الرفض. لمزيد من المعلومات حول simpleperf
، يُرجى الاطّلاع على
مرجع أوامر Simpleperf التنفيذية.
التبديل إلى وضع السماح
يمكن إيقاف فرض SELinux باستخدام adb في إصدارات userdebug أو eng. لإجراء ذلك،
بدِّل أولاً ADB إلى root من خلال تشغيل adb root
. بعد ذلك، لإيقاف فرض سياسة SELinux، يمكنك تنفيذ:
adb shell setenforce 0
أو في سطر أوامر النواة (أثناء التشغيل المبكر للجهاز):
androidboot.selinux=permissive
androidboot.selinux=enforcing
أو من خلال bootconfig في Android 12:
androidboot.selinux=permissive
androidboot.selinux=enforcing
استخدام audit2allow
تأخذ أداة audit2allow
عمليات الرفض dmesg
وتحوّلها إلى عبارات سياسة SELinux المقابلة. وبالتالي، يمكنه
تسريع تطوير SELinux بشكل كبير.
لاستخدامه، يمكنك تنفيذ:
adb pull /sys/fs/selinux/policy
adb logcat -b events -d | audit2allow -p policy
ومع ذلك، يجب توخي الحذر عند فحص كل إضافة محتملة للتحقق مما إذا كانت تطلب أذونات تتعدى الحدّ المسموح به. على سبيل المثال، يؤدي تقديم audit2allow
rmt_storage
النفي الذي سبق عرضه إلى العبارة التالية
المقترَحة لسياسة SELinux:
#============= shell ============== allow shell kernel:security setenforce; #============= rmt ============== allow rmt kmem_device:chr_file { read write };
سيمنح ذلك rmt
إمكانية كتابة ذاكرة kernel، ما يشكّل
ثغرة أمنية واضحة. غالبًا ما تكون عبارات audit2allow
نقطة بداية فقط. بعد استخدام هذه العبارات، قد تحتاج إلى تغيير
نطاق المصدر وتصنيف الهدف، بالإضافة إلى دمج
وحدات الماكرو المناسبة، للوصول إلى سياسة جيدة. في بعض الأحيان، لا يؤدي الرفض الذي تتم مراجعته
إلى إجراء أي تغييرات على السياسة على الإطلاق، بل يجب تعديل التطبيق المعني
.