SELinux מוגדר לדחייה כברירת מחדל, כלומר כל גישה שיש לה וו בקרנל צריכה לקבל הרשאה מפורשת במדיניות. כלומר, קובץ מדיניות מורכב מכמות גדולה של מידע לגבי כללים, סוגים, כיתות, הרשאות ועוד. התייחסות מלאה ל-SELinux היא מעבר להיקף המאמר הזה, אבל חשוב להבין איך לכתוב כללי מדיניות כשמפעילים מכשירים חדשים של Android. כבר יש הרבה מידע זמין לגבי SELinux. במסמכי העזרה מפורטות הצעות למקורות מידע.
קבצים של מפתחות
כדי להפעיל את SELinux, צריך לשלב את ליבת Android העדכנית ואז לשלב את הקבצים שנמצאים בספרייה system/sepolicy. לאחר הידור, הקבצים האלה כוללים את מדיניות האבטחה של הליבה של SELinux ומכסים את מערכת ההפעלה של Android במקור.
באופן כללי, לא מומלץ לשנות את קובצי system/sepolicy
ישירות. במקום זאת, מוסיפים או עורכים את קובצי המדיניות הספציפיים למכשיר בתיקייה /device/manufacturer/device-name/sepolicy
. ב-Android 8.0 ואילך, השינויים שתבצעו בקבצים האלה אמורים להשפיע רק על המדיניות בספריית הספקים. פרטים נוספים על הפרדה של מדיניות אבטחה ציבורית ב-Android 8.0 ואילך זמינים במאמר התאמה אישית של SEPolicy ב-Android 8.0 ואילך. ללא קשר לגרסה של Android, עדיין צריך לשנות את הקבצים הבאים:
קובצי מדיניות
קבצים שמסתיימים ב-*.te
הם קובצי מקור של מדיניות SELinux, שמגדירים את הדומיינים ואת התוויות שלהם. יכול להיות שתצטרכו ליצור קובצי מדיניות חדשים ב-/device/manufacturer/device-name/sepolicy
, אבל כדאי לנסות לעדכן קבצים קיימים במידת האפשר.
קובצי הקשר
קובצי ההקשר הם המקום שבו מציינים תוויות לאובייקטים.
file_contexts
מקצה תוויות לקבצים ומשתמשים בו רכיבים שונים במרחב המשתמש. כשיוצרים כללי מדיניות חדשים, יוצרים או מעדכנים את הקובץ הזה כדי להקצות תוויות חדשות לקבצים. כדי להחילfile_contexts
חדש, צריך ליצור מחדש את קובץ האימג' של מערכת הקבצים או להריץ אתrestorecon
בקובץ שרוצים לתייג מחדש. בשדרוגים, השינויים ב-file_contexts
חלים באופן אוטומטי על המחיצות של המערכת ושל נתוני המשתמש כחלק מהשדרוג. אפשר גם להחיל שינויים באופן אוטומטי בשדרוג למחיצות אחרות על ידי הוספת קריאות ל-restorecon_recursive
לקובץ init.board.rc אחרי שמחיצה מותקנת לקריאה וכתיבה.genfs_contexts
מקצה תוויות למערכת קבצים, כמוproc
אוvfat
, שלא תומכות במאפיינים מורחבים. ההגדרה הזו נטענת כחלק ממדיניות הליבה, אבל יכול להיות שהשינויים לא ייכנסו לתוקף ב-inodes שבליבה, ולכן תצטרכו להפעיל מחדש את המחשב או לבטל את הקישור של מערכת הקבצים ולקשר אותה מחדש כדי שהשינוי ייכנס לתוקף באופן מלא. אפשר גם להקצות תוויות ספציפיות למחיצות ספציפיות, כמוvfat
, באמצעות האפשרותcontext=mount
.property_contexts
מקצה תוויות למאפייני המערכת של Android כדי לקבוע אילו תהליכים יכולים להגדיר אותם. התהליךinit
קורא את ההגדרה הזו במהלך ההפעלה.service_contexts
מקצה תוויות לשירותי Android binder כדי לקבוע אילו תהליכים יכולים להוסיף (לרשום) ולמצוא (לחפש) הפניה ל-binder של השירות. התהליךservicemanager
קורא את ההגדרה הזו במהלך ההפעלה.seapp_contexts
מקצה תוויות לתהליכי אפליקציות ולספריות/data/data
. התהליךzygote
קורא את ההגדרות האלה בכל הפעלה של האפליקציה, ו-installd
קורא אותן במהלך ההפעלה.mac_permissions.xml
מקצה תגseinfo
לאפליקציות על סמך החתימה שלהן, ואפשר גם על סמך שם החבילה שלהן. לאחר מכן אפשר להשתמש בתגseinfo
כמפתח בקובץseapp_contexts
כדי להקצות תווית ספציפית לכל האפליקציות עם התגseinfo
. ההגדרה הזו נקראת על ידיsystem_server
במהלך ההפעלה.keystore2_key_contexts
מקצה תוויות למרחבי שמות של Keystore 2.0. את מרחב השמות האלה אוכף הדימון של keystore2. מאז ומתמיד, Keystore סיפק מרחבי שמות שמבוססים על UID/AID. בנוסף, ב-Keystore 2.0 מתבצעת אכיפה של מרחבי שמות שמוגדרים במדיניות האבטחה. תיאור מפורט של הפורמט והמוסכמות של הקובץ הזה זמין כאן.
קובץ makefile BoardConfig.mk
אחרי עריכה או הוספה של קובצי מדיניות והקשר, מעדכנים את קובץ ה-makefile /device/manufacturer/device-name/BoardConfig.mk
כך שיפנה לספריית המשנה sepolicy
לכל קובץ מדיניות חדש.
מידע נוסף על המשתנים BOARD_SEPOLICY
זמין
בקובץ system/sepolicy/README
.
BOARD_SEPOLICY_DIRS += \ <root>/device/manufacturer/device-name/sepolicy BOARD_SEPOLICY_UNION += \ genfs_contexts \ file_contexts \ sepolicy.te
אחרי היצירה מחדש, SELinux מופעל במכשיר. עכשיו אפשר להתאים אישית את כללי המדיניות של SELinux כדי להתאים אותם להוספות שלכם למערכת ההפעלה Android, כפי שמתואר בקטע התאמה אישית, או לאמת את ההגדרה הקיימת, כפי שמתואר בקטע אימות.
כשקבצי המדיניות החדשים והעדכונים של BoardConfig.mk מותקנים, הגדרות המדיניות החדשות מוטמעות באופן אוטומטי בקובץ המדיניות הסופי של הליבה. למידע נוסף על האופן שבו sepolicy נוצר במכשיר, ראו יצירת sepolicy.
הטמעה
כדי להתחיל לעבוד עם SELinux:
- מפעילים את SELinux בליבה:
CONFIG_SECURITY_SELINUX=y
- משנים את הפרמטר kernel_cmdline או bootconfig כך:
אוBOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
האפשרות הזו מיועדת רק לפיתוח ראשוני של מדיניות במכשיר. אחרי שתגדירו מדיניות אתחול ראשונית, תוכלו להסיר את הפרמטר הזה כדי שהמכשיר יאכוף את המדיניות או ייכשל ב-CTS.BOARD_BOOTCONFIG := androidboot.selinux=permissive
- מפעילים את המערכת במצב הרשאה רחבה ובודקים אילו דחיות מתרחשות במהלך האתחול:
ב-Ubuntu 14.04 ואילך: ב-Ubuntu 12.04:adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- בודקים את הפלט כדי לאתר אזהרות שדומות ל-
init: Warning! Service name needs a SELinux domain defined; please fix!
. להוראות ולכלים, ראו אימות. - זיהוי מכשירים וקבצים חדשים אחרים שצריך לתייג.
- משתמשים בתוויות קיימות או חדשות לאובייקטים. כדאי לעיין בקבצים
*_contexts
כדי לראות איך הדברים סומנו בעבר, ולהשתמש בידע לגבי משמעויות התוויות כדי להקצות תווית חדשה. באופן אידיאלי, זו תהיה תווית קיימת שתואמת למדיניות, אבל לפעמים נדרשת תווית חדשה וכללים לגישה לתווית הזו. מוסיפים את התוויות לקובצי ההקשר המתאימים. - מזהים דומיינים או תהליכים שצריכים להיות להם תחומי אבטחה משלהם.
סביר להניח שתצטרכו לכתוב מדיניות חדשה לגמרי לכל אחת מהן. לדוגמה, לכל השירותים שנוצרו מ-
init
צריכה להיות קבוצה משלהם. הפקודות הבאות עוזרות לגלות אילו שירותים עדיין פועלים (אבל צריך לבצע את הפעולות האלה בכל השירותים):
adb shell su -c ps -Z | grep init
adb shell su -c dmesg | grep 'avc: '
- בודקים את השדה
init.device.rc
כדי לזהות דומיינים שאין להם סוג דומיין. כדאי להקצות להם דומיין מוקדם בתהליך הפיתוח, כדי להימנע מהוספת כללים ל-init
או מהבלבול בין הרשאות הגישה שלinit
לבין הרשאות גישה אחרות שכלולות במדיניות משלהם. - מגדירים את
BOARD_CONFIG.mk
כך שישתמש במשתניBOARD_SEPOLICY_*
. לפרטים על ההגדרה, אפשר לעיין בקובץ README ב-system/sepolicy
. - בודקים את הקובץ init.device.rc ואת הקובץ fstab.device, ומקפידים שכל שימוש ב-
mount
תואם למערכת קבצים עם תוויות תקינות, או שצוינה אפשרותcontext= mount
. - בודקים כל דחייה ויוצרים מדיניות SELinux כדי לטפל בכל אחת מהן כראוי. תוכלו לעיין בדוגמאות בקטע התאמה אישית.
מומלץ להתחיל מהמדיניות ב-AOSP ולהמשיך ממנה בהתאמות אישיות משלכם. מידע נוסף על אסטרטגיית המדיניות ועל חלק מהשלבים האלה זמין במאמר כתיבת מדיניות SELinux.
תרחישים לדוגמה
ריכזנו כאן כמה דוגמאות ספציפיות לנקודות חולשה שחשוב להביא בחשבון כשיוצרים תוכנה משלכם ומדיניות SELinux משויכת:
קישורי סימון: מכיוון שקישורי סימון מופיעים כקבצים, הם קרובות נקרא כקבצים, מה שעלול להוביל לנקודות חולשה. לדוגמה, רכיבים מסוימים עם הרשאות, כמו init
, משנים את ההרשאות של קבצים מסוימים, לפעמים באופן פתוח מדי.
לאחר מכן, תוקפים עשויים להחליף את הקבצים האלה בקישורים סימבוליים לקוד שבשליטתם, וכך לאפשר לתוקף לשכתב קבצים שרירותיים. עם זאת, אם אתם יודעים שהאפליקציה שלכם אף פעם לא עוברת על קישור ל-symlink, תוכלו לאסור עליה לעשות זאת באמצעות SELinux.
קובצי מערכת: כדאי להביא בחשבון את סוג קובצי המערכת שצריך לשנות רק בשרת המערכת. עם זאת, מאחר ש-netd
, init
ו-vold
פועלים בתור root, יש להם גישה לקבצים האלה במערכת. לכן, אם netd
נפרץ, הוא עלול לפגוע בקובצים האלה ואולי גם בשרת המערכת עצמו.
בעזרת SELinux אפשר לזהות את הקבצים האלה כקובצי נתונים של שרת המערכת.
לכן, הדומיין היחיד שיש לו הרשאת קריאה/כתיבה אליהם הוא שרת המערכת.
גם אם netd
נפרץ, הוא לא יכול להחליף דומיינים לדומיין של שרת המערכת ולגשת לקובצי המערכת האלה, למרות שהוא פועל בתור root.
נתוני אפליקציה: דוגמה נוספת היא סוג הפונקציות שצריכות לפעול בתור root אבל לא צריכות לקבל גישה לנתוני האפליקציה. האפשרות הזו מאוד שימושית כי אפשר להצהיר על טענות נכוֹנוּת רחבות, למשל איסור גישה לאינטרנט לדומיינים מסוימים שלא קשורים לנתוני האפליקציה.
setattr: בפקודות כמו chmod
ו-chown
, אפשר לזהות את קבוצת הקבצים שבהם הדומיין המשויך יכול לבצע setattr
. כל דבר מחוץ לזה יכול להיות אסור לשינויים האלה, גם על ידי משתמש root. לכן, יכול להיות שאפליקציה תרוץ את chmod
ו-chown
נגד משתמשים שמסומנים בתווית app_data_files
, אבל לא נגד משתמשים שמסומנים בתווית shell_data_files
או system_data_files
.