التحقّق من صحة SELinux

يشجِّع Android المصنّعين الأصليين للأجهزة على اختبار عمليات تنفيذ SELinux بدقة. يجب أن تطبق الشركات المصنعة نظام SELinux الجديد مجموعة اختبارية من الأجهزة أولاً.

بعد تطبيق سياسة جديدة، تأكَّد من أن SELinux يعمل بالشكل الصحيح على الجهاز من خلال إصدار الأمر getenforce.

يؤدي ذلك إلى طباعة وضع SELinux العام: إما Enforforce أو Permissive. إلى لتحديد وضع SELinux لكل نطاق، فيجب عليك فحص أو تشغيل أحدث إصدار من sepolicy-analyze باستخدام علامة (-p) مناسبة، موجودة في /platform/system/sepolicy/tools/

عمليات رفض القراءة

تحقَّق من عدم وجود أخطاء، يتم توجيهها كسجلات أحداث إلى dmesg وlogcat ويمكن مشاهدتها محليًا على الجهاز. الشركات المصنِّعة فحص ناتج 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 لتفعيل نقطة التتبُّع هذه وتسجيل سلسلة الاتصال.

الإعدادات المتوافقة

  • نواة Linux >= 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

سلسلة الاستدعاء أعلاه هي سلسلة استدعاء موحّدة للنواة ومساحة المستخدم. فهو يمنحك تجربة أفضل لتدفق الرمز عن طريق بدء التتبع من مساحة المستخدم وصولاً إلى النواة (النواة) حيث حدوث الرفض. لمزيد من المعلومات عن simpleperf، يُرجى الاطّلاع على مرجع أوامر Simpleperf القابلة للتنفيذ.

التبديل إلى وضع السماح

يمكن إيقاف فرض SELinux باستخدام adb في إصدارات userdebug أو eng. لإجراء ذلك، عليك أولاً تبديل ADB إلى root من خلال تشغيل adb root. بعد ذلك، لتعطيل SELinux التنفيذ، قم بتشغيل:

adb shell setenforce 0

أو في سطر أوامر النواة (أثناء التشغيل المبكر للجهاز):

androidboot.selinux=permissive
androidboot.selinux=enforcing

أو من خلال إعدادات التشغيل في Android 12:

androidboot.selinux=permissive
androidboot.selinux=enforcing

استخدام التدقيق2allow

تأخذ أداة 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 فقط نقطة البداية. بعد استخدام هذه العبارات، قد تحتاج إلى تغيير ونطاق المصدر وتصنيف الهدف، بالإضافة إلى دمج وحدات الماكرو، للوصول إلى سياسة جيدة. في بعض الأحيان يجب أن يكون الإنكار الذي يتم فحصه ألا تؤدّي إلى أيّ تغييرات في السياسة على الإطلاق بل التطبيق المسيء بتغييره.