اندروید قویاً OEM ها را تشویق می کند تا پیاده سازی های SELinux خود را به طور کامل آزمایش کنند. همانطور که تولید کنندگان SELinux را پیاده سازی می کنند، آنها باید ابتدا سیاست جدید را در مجموعه آزمایشی از دستگاه ها اعمال کنند.
پس از اعمال یک خط مشی جدید، با صدور دستور getenforce مطمئن شوید که SELinux در حالت صحیح در دستگاه اجرا می شود.
این حالت جهانی SELinux را چاپ می کند: یا Enforcing یا 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)، تقریباً به شما میگوید که چه کاری انجام میشد. در این مورد، چیزی در تلاش بود تا به یک سوکت جریان یونیکس متصل شود. -
scontext (u:r:shell:s0)به شما می گوید که چه زمینه ای اقدام را آغاز کرده است. در این مورد این چیزی است که به عنوان پوسته در حال اجرا است. -
tcontext (u:r:netd:s0)زمینه هدف عمل را به شما می گوید. در این مورد، این یک سوکت unix_stream_ متعلق به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برجسته می شود. - Actor - مدخل
scontext(متن منبع) بازیگر را نشان می دهد، در این مورد دیمونrmt_storage. - Object - ورودی
tcontext(متن هدف) نشان دهنده شی مورد عمل است، در این مورد kmem. - نتیجه - ورودی
tclass(کلاس هدف) نشان دهنده نوع شیئی است که روی آن اعمال می شود، در این موردchr_file(دستگاه کاراکتر).
پشته های کاربر و هسته را تخلیه کنید
در برخی موارد، اطلاعات موجود در گزارش رویداد برای مشخص کردن منشا انکار کافی نیست. جمع آوری زنجیره تماس، از جمله هسته و فضای کاربر، برای درک بهتر چرایی انکار، اغلب مفید است.
هسته های اخیر یک نقطه ردیابی به نام avc:selinux_audited را تعریف می کنند. از Android simpleperf برای فعال کردن این نقطه ردیابی و گرفتن callchain استفاده کنید.
پیکربندی پشتیبانی شده
- هسته لینوکس >= 5.10، به ویژه شاخه های اصلی هسته مشترک Android و android12-5.10 پشتیبانی می شوند. شاخه android12-5.4 نیز پشتیبانی می شود. می توانید از
simpleperfبرای تعیین اینکه آیا نقطه ردیابی در دستگاه شما تعریف شده است استفاده کنید:adb root && adb shell simpleperf list | grep avc:selinux_audited. برای سایر نسخههای هسته، میتوانید cherry pick commits 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 ممکن است برای بررسی stacktrace ضبط شده استفاده شود. به عنوان مثال:
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 را با اجرای adb root به روت تغییر دهید. سپس، برای غیرفعال کردن اجرای SELinux، اجرا کنید:
adb shell setenforce 0
یا در خط فرمان کرنل (در هنگام باز کردن اولیه دستگاه):
androidboot.selinux=permissiveandroidboot.selinux=enforcing
یا از طریق bootconfig در اندروید 12:
androidboot.selinux=permissiveandroidboot.selinux=enforcing
از audit2allow استفاده کنید
ابزار audit2allow انکارهای dmesg را می گیرد و آنها را به بیانیه های خط مشی SELinux مربوطه تبدیل می کند. به این ترتیب، می تواند سرعت توسعه SELinux را بسیار افزایش دهد.
برای استفاده از آن، اجرا کنید:
adb pull /sys/fs/selinux/policyadb 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 توانایی نوشتن حافظه هسته، یک حفره امنیتی آشکار را می دهد. اغلب اظهارات audit2allow تنها یک نقطه شروع هستند. پس از استفاده از این عبارات، ممکن است لازم باشد دامنه منبع و برچسب هدف را تغییر دهید و همچنین ماکروهای مناسب را برای رسیدن به یک خط مشی خوب ترکیب کنید. گاهی اوقات انکار مورد بررسی به هیچ وجه نباید منجر به تغییر سیاستی شود. بلکه برنامه متخلف باید تغییر کند.