יצירת מדיניות SELinux

בדף הזה מוסבר איך נוצרת מדיניות SELinux. מדיניות SELinux מורכבת משילוב של מדיניות הליבה של AOSP (פלטפורמה) ומדיניות ספציפית למכשיר (ספק). תהליך ה-build של מדיניות SELinux ב-Android 4.4 עד Android 7.0 מיזג את כל קטעי ה-sepolicy ויצר קובצי monolith בספריית השורש. המשמעות היא שמוכרי SoC ויצרני ODM שיניבו את הערך של boot.img (למכשירים שאינם A/B) או את הערך של system.img (למכשירי A/B) בכל פעם שהמדיניות תשתנה.

ב-Android מגרסה 8.0 ואילך, המדיניות של הפלטפורמה והמדיניות של הספק נוצרות בנפרד. SOC ו-OEM יכולים לעדכן את החלקים שלהם במדיניות, ליצור את התמונות שלהם (כמו vendor.img ו-boot.img) ולאחר מכן לעדכן את התמונות האלה בנפרד מהעדכונים של הפלטפורמה.

עם זאת, מאחר שקובצי המדיניות של SELinux מודולריים מאוחסנים במחיצות /vendor, התהליך init צריך לטעון מראש את המחיצות של המערכת והספק כדי שיוכל לקרוא קובצי SELinux מהמחיצות האלה ולמזג אותם עם קובצי הליבה של SELinux בתיקיית המערכת (לפני הטעינה שלהם בליבה).

קובצי מקור

הלוגיקה לבניית SELinux נמצאת בקבצים הבאים:

  • external/selinux: פרויקט SELinux חיצוני, המשמש ליצירת כלי שורת פקודה של HOST כדי לקמפל את המדיניות והתוויות של SELinux.
    • external/selinux/libselinux: ב-Android נעשה שימוש רק בקבוצת משנה של הפרויקט החיצוני libselinux, יחד עם כמה התאמות אישיות ספציפיות ל-Android. פרטים נוספים זמינים במאמר external/selinux/README.android.
    • external/selinux/libsepol:
      • chkcon: בדיקה אם הקשר אבטחה תקף למדיניות בינארית נתונה (קובץ הפעלה של מארח).
      • libsepol: ספריית SELinux לטיפול במדיניות אבטחה של קבצים בינאריים (ספרייה סטטית/משותפת של מארח, ספרייה סטטית של יעד).
    • external/selinux/checkpolicy: קומפילטור של מדיניות SELinux (קובצי הפעלה של המארח: checkpolicy,‏ checkmodule ו-dispol). תלוי ב-libsepol.
  • system/sepolicy: הגדרות הליבה של מדיניות SELinux ב-Android, כולל הקשרים וקובצי מדיניות. גם הלוגיקה העיקרית של build של מדיניות האבטחה נמצאת כאן (system/sepolicy/Android.mk).

פרטים נוספים על הקבצים מופיעים במאמר system/sepolicy הטמעת SELinux.

Android מגרסה 7.x ומטה

בקטע הזה נסביר איך המדיניות של SELinux נוצרת ב-Android 7.x וגרסאות מוקדמות יותר.

תהליך build ל-Android מגרסה 7.x ומטה

מדיניות SELinux נוצרת על ידי שילוב של מדיניות הליבה של AOSP עם התאמות ספציפיות למכשיר. לאחר מכן, המדיניות המשולבת מועברת למהדר המדיניות ולבודקים שונים. התאמה אישית ספציפית למכשיר מתבצעת באמצעות המשתנה BOARD_SEPOLICY_DIRS שמוגדר בקובץ Boardconfig.mk הספציפי למכשיר. משתנה ה-build הגלובלי הזה מכיל רשימה של ספריות שמציינות את הסדר שבו צריך לחפש קובצי מדיניות נוספים.

לדוגמה, ספק SoC ו-ODM יכולים להוסיף כל אחד ספרייה, אחת להגדרות הספציפיות ל-SoC ואחת להגדרות הספציפיות למכשיר, כדי ליצור את הגדרות SELinux הסופיות למכשיר נתון:

  • BOARD_SEPOLICY_DIRS += device/SOC/common/sepolicy
  • BOARD_SEPOLICY_DIRS += device/SoC/DEVICE/sepolicy

התוכן של קובצי file_contexts ב-system/sepolicy וב-BOARD_SEPOLICY_DIRS מצורף כדי ליצור את file_contexts.bin במכשיר:

בתמונה הזו מוצג הלוגיקה של build של SELinux ל-Android 7.x.

איור 1. לוגיקה של build של SELinux.

קובץ sepolicy מורכב מכמה קובצי מקור:

  • הטקסט הפשוט policy.conf נוצר על ידי שרשור של קבצים security_classes,‏ initial_sids,‏ *.te,‏ genfs_contexts ו-port_contexts בסדר הזה.
  • לכל קובץ (כמו security_classes), התוכן שלו הוא שרשור של הקבצים עם אותו שם ב-system/sepolicy/ וב-BOARDS_SEPOLICY_DIRS.
  • ה-policy.conf נשלח למהדר של SELinux לבדיקה של התחביר, ומתורגם לפורמט בינארי בתור sepolicy במכשיר.
    בתמונה הזו מוצגים הקבצים שיוצרים את קובץ המדיניות של SELinux עבור Android 7.x.

    איור 2. קובץ מדיניות של SELinux.

קובצי SELinux

לאחר הידור, מכשירי Android עם גרסת 7.x וגרסאות קודמות מכילים בדרך כלל את הקבצים הבאים שקשורים ל-SELinux:

  • selinux_version
  • sepolicy: פלט בינארי לאחר שילוב של קובצי מדיניות (כמו security_classes,‏ initial_sids ו-*.te)
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

פרטים נוספים זמינים במאמר הטמעת SELinux.

אתחול של SELinux

כשהמערכת מופעלת, SELinux נמצא במצב הרשאה (ולא במצב אכיפה). תהליך ה-init מבצע את המשימות הבאות:

  • טוען קבצים מסוג sepolicy מ-ramdisk לתוך הליבה דרך /sys/fs/selinux/load.
  • מעבר של SELinux למצב אכיפה.
  • הפעלת re-exec() כדי להחיל את כלל הדומיין של SELinux על עצמו.

כדי לקצר את זמן האתחול, צריך לבצע את הפקודה re-exec() בתהליך init בהקדם האפשרי.

Android מגרסה 8.0 ואילך

ב-Android 8.0, מדיניות SELinux מחולקת לרכיבים של פלטפורמה ורכיבים של ספק כדי לאפשר עדכונים עצמאיים של מדיניות הפלטפורמה או של מדיניות הספק, תוך שמירה על תאימות.

מדיניות האבטחה של הפלטפורמה מחולקת לחלקים פרטיים ולחלקים ציבוריים כדי לייצא סוגים ומאפיינים ספציפיים לכותבי מדיניות של ספקים. אנחנו מתחייבים לשמור על הסוגים או המאפיינים הציבוריים של הפלטפורמה כממשקי API יציבים בגרסה מסוימת של הפלטפורמה. אפשר להבטיח תאימות עם סוגים או מאפיינים ציבוריים קודמים של הפלטפורמה בכמה גרסאות באמצעות קובצי מיפוי של הפלטפורמה.

תהליך build ל-Android מגרסה 8.0

מדיניות SELinux ב-Android 8.0 נוצרת על ידי שילוב של חלקים מ-/system ומ-/vendor. הלוגיקה להגדרה המתאימה מפורטת בקטע /platform/system/sepolicy/Android.mk.

המדיניות קיימת במיקומים הבאים:

מיקום השירים הכלולים
system/sepolicy/public ה-API של מדיניות האבטחה בפלטפורמה
system/sepolicy/private פרטי הטמעת הפלטפורמה (ספקים יכולים להתעלם מהם)
system/sepolicy/vendor קבצי מדיניות והקשר שספקים יכולים להשתמש בהם (ספקים יכולים להתעלם מהם אם הם רוצים)
BOARD_SEPOLICY_DIRS מדיניות האבטחה של הספק
BOARD_ODM_SEPOLICY_DIRS (Android מגרסה 9 ואילך) Odm sepolicy
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android מגרסה 11 ואילך) ממשק ה-API של sepolicy ב-System_ext
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android מגרסה 11 ואילך) פרטי הטמעה של System_ext (ספקים יכולים להתעלם מהם)
PRODUCT_PUBLIC_SEPOLICY_DIRS (Android מגרסה 11 ואילך) ממשק ה-API של מדיניות האבטחה של המוצר
PRODUCT_PRIVATE_SEPOLICY_DIRS (Android מגרסה 11 ואילך) פרטי הטמעת המוצר (ספקים יכולים להתעלם מהם)

מערכת ה-build משתמשת במדיניות הזו כדי ליצור רכיבי מדיניות של system,‏ system_ext,‏ product,‏ vendor ו-odm במחיצה המתאימה. השלבים כוללים:

  1. המרת כללי המדיניות לפורמט SELinux Common Intermediate Language ‏ (CIL), ובמיוחד:
    1. מדיניות פלטפורמה ציבורית (system +‏ system_ext +‏ product)
    2. מדיניות פרטית וציבורית משולבת
    3. המדיניות של public + vendor ו-BOARD_SEPOLICY_DIRS
  2. יצירת גרסאות למדיניות שסופקו על ידי הציבור כחלק ממדיניות הספק. כדי לעשות זאת, משתמשים במדיניות ה-CIL הציבורית שנוצרה כדי להנחות את המדיניות המשולבת של הציבור, הספק ו-BOARD_SEPOLICY_DIRS לגבי החלקים שצריך להפוך למאפיינים שייקוש למדיניות הפלטפורמה.
  3. יצירת קובץ מיפוי שמקשר בין החלקים של הפלטפורמה לבין החלקים של הספק. בשלב הראשון, הקישור הזה רק מקשר את הסוגים מהמדיניות הציבורית למאפיינים התואמים במדיניות הספק. בהמשך, הוא גם יספק את הבסיס לקובץ ששמור בגרסאות עתידיות של הפלטפורמה, ויאפשר תאימות למדיניות הספק שמטרגטת את גרסת הפלטפורמה הזו.
  4. שילוב של קובצי מדיניות (תיאור של פתרונות במכשיר ופתרונות שנוצרו מראש).
    1. שילוב של מדיניות המיפוי, הפלטפורמה והספק.
    2. קומפילציה של קובץ המדיניות הבינארי של הפלט.

מדיניות אבטחה ציבורית של פלטפורמה

מדיניות האבטחה הציבורית של הפלטפורמה כוללת את כל מה שמוגדר בקטע system/sepolicy/public. הפלטפורמה יכולה להניח שהסוגים והמאפיינים שמוגדרים במדיניות הציבורית הם ממשקי API יציבים לגרסה מסוימת של הפלטפורמה. זהו החלק של מדיניות האבטחה (sepolicy) שמיוצא על ידי הפלטפורמה, שבו מפתחי המדיניות של הספק (כלומר המכשיר) יכולים לכתוב מדיניות נוספת ספציפית למכשיר.

הסוגים מחולקים לגרסאות בהתאם לגרסה של המדיניות שבה נכתבים קובצי הספק, כפי שמוגדר במשתנה ה-build‏ PLATFORM_SEPOLICY_VERSION. לאחר מכן, המדיניות הציבורית עם הגרסאות נכללת במדיניות הספק (בפורמט המקורי שלה) ובמדיניות הפלטפורמה. לכן, המדיניות הסופית כוללת את מדיניות הפלטפורמה הפרטית, את מדיניות האבטחה הציבורית הנוכחית של הפלטפורמה, את המדיניות הספציפית למכשיר ואת המדיניות הציבורית עם הגרסה התואמת לגרסה של הפלטפורמה שבה נכתבה מדיניות המכשיר.

מדיניות אבטחה פרטית של פלטפורמה

מדיניות האבטחה הפרטית של הפלטפורמה כוללת את כל מה שמוגדר בקטע /system/sepolicy/private. החלק הזה של המדיניות כולל את הסוגים, ההרשאות והמאפיינים של הפלטפורמה בלבד שנדרשים לפונקציונליות שלה. הם לא מיוצאים לכלי ליצירת כללי המדיניות של vendor/device. כותבי מדיניות שלא קשורים לפלטפורמה לא יכולים לכתוב את תוספי המדיניות שלהם על סמך סוגים/מאפיינים/כללים שהוגדרו במדיניות האבטחה הפרטית של הפלטפורמה. בנוסף, מותר לשנות את הכללים האלה או שהם עשויים להיעלם כחלק מעדכון של המסגרת בלבד.

מיפוי פרטי של פלטפורמה

המיפוי הפרטי של הפלטפורמה כולל הצהרות מדיניות שממפות את המאפיינים שנחשפו במדיניות הציבורית של הפלטפורמה בגרסאות הקודמות של הפלטפורמה לסוגי הנתונים הספציפיים שמשמשים במדיניות האבטחה הציבורית הנוכחית של הפלטפורמה. כך תוכלו להבטיח שמדיניות הספק שנכתבה על סמך מאפיינים ציבוריים של הפלטפורמה מגרסאות הקודמות של מדיניות האבטחה הציבורית של הפלטפורמה תמשיך לפעול. ניהול הגרסאות מבוסס על משתנה ה-build PLATFORM_SEPOLICY_VERSION שמוגדר ב-AOSP לגרסה מסוימת של הפלטפורמה. קיים קובץ מיפוי נפרד לכל גרסה קודמת של הפלטפורמה שממנה הפלטפורמה הזו אמורה לקבל את מדיניות הספק. מידע נוסף זמין בקטע תאימות.

Android מגרסה 11 ואילך

system_ext ו-product sepolicy

ב-Android 11 נוספות המדיניות system_ext והמדיניות של המוצר. בדומה למדיניות sepolicy של הפלטפורמה, המדיניות system_ext ומדיניות המוצר מחולקות למדיניות ציבורית ולמדיניות פרטית.

מדיניות הציבור מיוצאת לספק. סוגי מאפיינים הופכים ל-API יציב, ומדיניות הספק יכולה להפנות לסוגי מאפיינים במדיניות הציבורית. הסוגים מחולקים לגרסאות לפי PLATFORM_SEPOLICY_VERSION, והמדיניות המחולקת לגרסאות כלולה במדיניות של הספק. המדיניות המקורית כלולה בכל מחיצה של system_ext ושל המוצר.

המדיניות הפרטית מכילה את סוגי הפריטים, ההרשאות והמאפיינים שנדרשים לפונקציונליות של המחיצות system_ext ושל המחיצות של המוצרים, ורק להם. המדיניות הפרטית לא גלויה לספק, כלומר הכללים האלה הם פנימיים וניתן לשנות אותם.

מיפוי של system_ext ומוצרים

האפשרות system_ext והאפשרות product מורשות לייצא את הסוגים הציבוריים הייעודיים שלהן אל הספק. עם זאת, האחריות לשמירה על תאימות היא של כל שותף בנפרד. לשם תאימות, שותפים יכולים לספק קובצי מיפוי משלהם שממפים את המאפיינים עם הגרסאות של הגרסאות הקודמות לסוגי נתונים ספציפיים שמשמשים את מדיניות האבטחה הציבורית הנוכחית.

  • כדי להתקין קובץ מיפוי ל-system_ext, מעבירים קובץ cil שמכיל את פרטי המיפוי הרצויים אל {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil, ואז מוסיפים את system_ext_{ver}.cil אל PRODUCT_PACKAGES.
  • כדי להתקין קובץ מיפוי של מוצר, מעבירים קובץ cil שמכיל את פרטי המיפוי הרצויים אל {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil, ואז מוסיפים את product_{ver}.cil אל PRODUCT_PACKAGES.

דוגמה להוספת קובץ מיפוי של מחיצה של מוצר במכשיר redbull.

מדיניות SELinux שנוצרה מראש

לפני ש-init מפעיל את SELinux, הוא אוסף את כל קובצי ה-CIL מהמחיצות (system, ‏ system_ext, ‏ product, ‏ vendor ו-odm) ומעבד אותם למדיניות בינארית, הפורמט שאפשר לטעון לליבת ליבה.init מאחר שהקמפיליציה נמשכת זמן מה (בדרך כלל שנייה או שתיים), קובצי ה-CIL מקובצים מראש בזמן ה-build וממוקמים ב-/vendor/etc/selinux/precompiled_sepolicy או ב-/odm/etc/selinux/precompiled_sepolicy, יחד עם גיבובי ה-sha256 של קובצי ה-CIL של הקלט. במהלך זמן הריצה, init בודק אם אחד מקובצי המדיניות עודכן על ידי השוואת הגיבובים. אם לא חלו שינויים, init יטען את המדיניות שעברתה הידור מראש. אם לא, init יעבור הידור בזמן אמת וישתמש בו במקום בקוד המקודד מראש.

באופן ספציפי יותר, המערכת משתמשת במדיניות שעברתה הידור מראש אם כל התנאים הבאים מתקיימים. כאן, הערך {partition} מייצג את המחיצה שבה נמצאת המדיניות שעברתה הידור מראש: vendor או odm.

  • גם /system/etc/selinux/plat_sepolicy_and_mapping.sha256 וגם /{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 קיימים והם זהים.
  • גם /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256 וגם /{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256 לא קיימים. או ששניהם קיימים וזהים.
  • גם /product/etc/selinux/product_sepolicy_and_mapping.sha256 וגם /{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256 לא קיימים. או ששניהם קיימים וזהים.

אם יש הבדל בין הערכים, init חוזר לנתיב הידור במכשיר. לפרטים נוספים, ראו system/core/init/selinux.cpp.