מערכת Android ממליצה בחום ליצרני ציוד מקורי (OEM) לבדוק ביסודיות את ההטמעות של SELinux. יצרנים שמטמיעים SELinux צריכים להחיל את המדיניות החדשה קודם על קבוצת מכשירי בדיקה.
אחרי שמחילים מדיניות חדשה, מוודאים ש-SELinux פועל במצב הנכון במכשיר על ידי הפעלת הפקודה getenforce
.
הפקודה הזו מדפיסה את מצב 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_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
. - Actor – הרשומה
scontext
(הקשר המקור) מייצגת את הגורם המבצע, ובמקרה הזה את דמוןrmt_storage
. - Object (אובייקט) – הרשומה
tcontext
(הקשר של היעד) מייצגת את האובייקט שעליו מתבצעת הפעולה, במקרה הזה kmem. - תוצאה – הרשומה
tclass
(target class) מציינת את סוג האובייקט שעליו מתבצעת הפעולה, ובמקרה הזה מדובר ב-chr_file
(character device).
העברה של מחסניות של משתמשים וליבות
במקרים מסוימים, המידע שכלול ביומן האירועים לא מספיק כדי לאתר את מקור הדחייה. לעתים קרובות כדאי לאסוף את שרשרת הקריאות, כולל ליבת המערכת ומרחב המשתמש, כדי להבין טוב יותר למה נדחתה הגישה.
בליבות עדכניות מוגדרת נקודת מעקב בשם 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
. בגרסאות ליבה אחרות, אפשר לבחור קומיטים (commit) 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 Executable commands reference (חומרי עזר בנושא פקודות הפעלה של 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
היכולת לכתוב זיכרון ליבה, וזו פרצת אבטחה חמורה. לעתים קרובות, הצהרות audit2allow
הן רק נקודת התחלה. אחרי שמשתמשים בהצהרות האלה, יכול להיות שיהיה צורך לשנות את דומיין המקור ואת התווית של היעד, וגם לשלב פקודות מאקרו מתאימות, כדי להגיע למדיניות טובה. לפעמים הדחייה שנבדקת לא צריכה להוביל לשינויים במדיניות, אלא לשינויים באפליקציה הבעייתית.