اندروید قویاً 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
(دستگاه کاراکتر).
Dumping User and Kernel Stacks
در برخی موارد، اطلاعات موجود در گزارش رویداد برای تعیین دقیق منشأ انکار کافی نیست. جمع آوری زنجیره تماس، از جمله هسته و فضای کاربر، برای درک بهتر چرایی انکار، اغلب مفید است.
هسته های اخیر یک نقطه ردیابی به نام 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=permissive
androidboot.selinux=enforcing
یا از طریق bootconfig در اندروید 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
توانایی نوشتن حافظه هسته، یک حفره امنیتی آشکار را می دهد. اغلب اظهارات audit2allow
تنها یک نقطه شروع هستند. پس از استفاده از این عبارات، ممکن است لازم باشد دامنه منبع و برچسب هدف را تغییر دهید و همچنین ماکروهای مناسب را برای رسیدن به یک خط مشی خوب ترکیب کنید. گاهی اوقات انکار مورد بررسی به هیچ وجه نباید منجر به تغییر سیاستی شود. بلکه برنامه متخلف باید تغییر کند.