תאימות מדיניות

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

עיצוב מדיניות SELinux מבוסס טרבל שוקל הבחנה בינארית בין מדיניות של פלטפורמה וספק ; הסכימה הופכת מסובכת יותר אם מחיצות הספק מייצרות תלות, כגון platform < vendor < oem .

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

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

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

בעלות על אובייקט ותיוג

בעת התאמה אישית של מדיניות ב-Android 8.0 ואילך, בעלות חייבת להיות מוגדרת בבירור עבור כל אובייקט כדי להפריד בין מדיניות הפלטפורמה והספק. לדוגמה, אם הספק מציין את /dev/foo והפלטפורמה אז מתגים /dev/foo ב-OTA עוקב, תהיה התנהגות לא מוגדרת. עבור SELinux, זה מתבטא כהתנגשות תיוג. לצומת ההתקן יכולה להיות רק תווית בודדת אשר פותרת את התווית שהוחלה לאחרונה. כתוצאה:

  • תהליכים הזקוקים לגישה לתווית שהושמה שלא בהצלחה יאבדו את הגישה למשאב.
  • תהליכים שמקבלים גישה לקובץ עלולים להישבר בגלל שנוצר צומת המכשיר הלא נכון.

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

בנוסף להתנגשויות התוויות, שמות סוגים/מאפיינים של SELinux עשויים גם להתנגש. התנגשות שם סוג/תכונה תמיד תגרום לשגיאת מהדר מדיניות.

מרווח שמות הקלד/תכונה

SELinux אינו מאפשר מספר הצהרות מאותו סוג/תכונה. מדיניות עם הצהרות כפולות תיכשל בהידור. כדי להימנע מהתנגשויות של שמות סוגים ומאפיינים, יש להגדיר רווחי שמות בכל הצהרות הספקים החל ב- np_ .

type foo, domain; → type np_foo, domain;

בעלות על נכסי מערכת ותיוג תהליכים

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

סוג נכס קידומות מקובלות
מאפייני שליטה ctl.vendor.
ctl.start$vendor.
ctl.stop$vendor.
init.svc.vendor.
ניתן לקריאה-כתיבה vendor.
לקריאה בלבד ro.vendor.
ro.boot.
ro.hardware.
מַתְמִיד persist.vendor.

ספקים יכולים להמשיך להשתמש ro.boot.* (שמגיע מה-cmdline של הליבה) וב- ro.hardware.* (מאפיין ברור הקשור לחומרה).

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

בעלות על קובץ

מניעת התנגשויות עבור קבצים היא מאתגרת מכיוון שמדיניות הפלטפורמה והספק מספקות בדרך כלל תוויות לכל מערכות הקבצים. שלא כמו מתן שמות לסוגים, ריווח שמות של קבצים אינו מעשי מכיוון שרבים מהם נוצרים על ידי הקרנל. כדי למנוע התנגשויות אלה, עקוב אחר הנחיות השמות עבור מערכות קבצים בסעיף זה. עבור אנדרואיד 8.0, אלו הן המלצות ללא אכיפה טכנית. בעתיד, המלצות אלו יאכפו על ידי ה- Vendor Test Suite (VTS).

מערכת (/system)

רק תמונת המערכת חייבת לספק תוויות עבור /system דרך file_contexts , service_contexts וכו'. אם מתווספות תוויות עבור /system במדיניות /vendor , ייתכן שעדכון OTA למסגרת בלבד לא יהיה אפשרי.

ספק (/ספק)

המדיניות של AOSP SELinux כבר מסמנת חלקים ממחיצת vendor איתה הפלטפורמה מקיימת אינטראקציה, מה שמאפשר לכתוב כללי SELinux לתהליכי פלטפורמה כדי להיות מסוגלים לדבר ו/או לגשת לחלקים של מחיצת vendor . דוגמאות:

/vendor נתיב תווית מסופקת בפלטפורמה תהליכי פלטפורמה בהתאם לתווית
/vendor(/. * )? vendor_file כל לקוחות HAL במסגרת, ueventd , וכו'.
/vendor/framework(/. * )? vendor_framework_file dex2oat , appdomain וכו'.
/vendor/app(/. * )? vendor_app_file dex2oat , installd , idmap וכו'.
/vendor/overlay(/. * ) vendor_overlay_file system_server , zygote , idmap וכו'.

כתוצאה מכך, יש לעקוב אחר כללים ספציפיים (לאכוף באמצעות neverallows ) בעת תיוג קבצים נוספים במחיצת vendor :

  • vendor_file חייבת להיות תווית ברירת המחדל עבור כל הקבצים במחיצת vendor . מדיניות הפלטפורמה מחייבת זאת כדי לגשת למימושי HAL מעבר.
  • כל exec_types החדשים שנוספו במחיצת vendor דרך הספק SEPolicy חייבים להיות בעלי תכונה vendor_file_type . זה נאכף באמצעות neverallows.
  • כדי למנוע התנגשויות עם עדכוני פלטפורמה/מסגרת עתידיים, הימנע מתיוג קבצים שאינם exec_types במחיצת vendor .
  • כל התלות בספרייה עבור HALs מאותו תהליך המזוהה עם AOSP חייבות להיות מתויגות כ- same_process_hal_file.

Procfs (/proc)

ניתן לתייג קבצים ב- /proc באמצעות התווית genfscon בלבד. באנדרואיד 7.0, גם הפלטפורמה וגם מדיניות הספק השתמשו genfscon כדי לתייג קבצים ב- procfs .

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

Debugfs (/sys/kernel/debug)

ניתן לתייג Debugfs גם ב- file_contexts וגם genfscon . באנדרואיד 7.0 עד אנדרואיד 10, גם פלטפורמה וגם debugfs ספק ניפוי באגים.

ב-Android 11, לא ניתן לגשת debugfs או להרכיב אותם במכשירי ייצור. יצרני התקנים צריכים להסיר debugfs .

Tracefs (/sys/kernel/debug/tracing)

Tracefs ניתן לתייג גם ב- file_contexts וגם genfscon . באנדרואיד 7.0, רק הפלטפורמה מסמנת את התוויות tracefs .

המלצה: רק פלטפורמה רשאית לתייג tracefs .

Sysfs (/sys)

קבצים ב- /sys עשויים להיות מתויגים גם באמצעות file_contexts וגם באמצעות genfscon . באנדרואיד 7.0, גם הפלטפורמה וגם הספק משתמשים file_contexts וב- genfscon כדי לתייג קבצים ב- sysfs .

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

tmpfs (/dev)

קבצים ב- /dev עשויים להיות מסומנים בתווית file_contexts . באנדרואיד 7.0, קבצי תוויות של פלטפורמה וספקים כאן.

המלצה: הספק רשאי לתייג רק קבצים ב- /dev/vendor (למשל, /dev/vendor/foo , /dev/vendor/socket/bar ).

שורשים (/)

קבצים ב / עשויים להיות מתויגים ב- file_contexts . באנדרואיד 7.0, קבצי תוויות של פלטפורמה וספקים כאן.

המלצה: רק המערכת רשאית לתייג קבצים ב- / .

נתונים (/data)

נתונים מסומנים באמצעות שילוב של file_contexts ו- seapp_contexts .

המלצה: לא לאפשר תיוג ספקים מחוץ /data/vendor . רק הפלטפורמה רשאית לתייג חלקים אחרים של /data .

תכונות תאימות

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

המדיניות נכתבת בעיקר במונחים של סוגים קיימים:

allow source_type target_type:target_class permission(s);

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

File_contexts:
/sys/A   u:object_r:sysfs:s0
Platform: allow p_domain sysfs:class perm;
Vendor: allow v_domain sysfs:class perm;

ניתן לשנות ל:

File_contexts:
/sys/A   u:object_r:sysfs_A:s0

למרות שמדיניות הספק תישאר זהה, ה- v_domain יאבד גישה עקב היעדר מדיניות עבור סוג sysfs_A החדש.

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

הגדרת מדיניות ציבורית כתכונות מנוסחות עומדת בשתי יעדי תאימות למדיניות:

  • ודא שקוד הספק ממשיך לעבוד לאחר עדכון הפלטפורמה . מושגת על ידי הוספת תכונות לסוגים קונקרטיים עבור אובייקטים התואמים לאלה שעליהם נשען קוד הספק, תוך שמירה על גישה.
  • יכולת לבטל פוליסה . מושגת על ידי תיחום ברור של ערכי מדיניות למאפיינים שניתן להסיר ברגע שהגרסה שאליה הם תואמים כבר לא נתמכת. הפיתוח יכול להמשיך בפלטפורמה, בידיעה שהמדיניות הישנה עדיין קיימת במדיניות הספקים והיא תוסר אוטומטית כאשר/אם היא תשתדרג.

יכולת כתיבה של מדיניות

כדי לעמוד ביעד שלא לדרוש ידע על שינויי גרסאות ספציפיים לפיתוח מדיניות, אנדרואיד 8.0 כולל מיפוי בין סוגי מדיניות ציבורית של פלטפורמה והתכונות שלהם. סוג foo ממופה לתכונה foo_v N , כאשר N היא הגרסה הממוקדת. vN מתאים למשתנה הבנייה PLATFORM_SEPOLICY_VERSION והוא בצורת MM.NN , כאשר MM מתאים למספר SDK של הפלטפורמה ו- NN היא גרסה ספציפית למדיניות פלטפורמה.

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

מדיניות ציבורית של פלטפורמה מיוצאת בתור allow source_foo target_bar: class perm ; נכלל כחלק ממדיניות הספקים. במהלך הקומפילציה (הכוללת את הגרסה המתאימה) היא עוברת טרנספורמציה למדיניות שתעבור לחלק הספק של המכשיר (מוצג בשפת הביניים המשותפת שהשתנתה (CIL)):

 (allow source_foo_vN target_bar_vN (class (perm)))

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

הבדלי מדיניות

יצירה אוטומטית של תכונות על ידי הוספת _v N לסוף כל סוג לא עושה כלום בלי מיפוי של תכונות לסוגים על פני הבדלי גרסאות. אנדרואיד מקיימת מיפוי בין גרסאות עבור תכונות ומיפוי של סוגים לתכונות אלו. זה נעשה בקובצי המיפוי שהוזכרו לעיל עם הצהרות, כגון (CIL):

(typeattributeset foo_vN (foo))

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

הסעיף הבא מפרט תרחישים עבור שדרוגי פלטפורמה.

אותם סוגים

תרחיש זה מתרחש כאשר אובייקט אינו משנה תוויות בגרסאות מדיניות. זה זהה לסוגי מקור ויעד וניתן לראות אותו עם /dev/binder , שכותרתו binder_device בכל הגרסאות. זה מיוצג במדיניות שעברה שינוי כ:

binder_device_v1 … binder_device_vN

בעת שדרוג מ- v1v2 , מדיניות הפלטפורמה חייבת להכיל:

type binder_device; -> (type binder_device) (in CIL)

בקובץ המיפוי v1 (CIL):

(typeattributeset binder_device_v1 (binder_device))

בקובץ המיפוי v2 (CIL):

(typeattributeset binder_device_v2 (binder_device))

במדיניות הספק v1 (CIL):

(typeattribute binder_device_v1)
(allow binder_device_v1 …)

במדיניות הספקים של v2 (CIL):

(typeattribute binder_device_v2)
(allow binder_device_v2 …)
סוגים חדשים

תרחיש זה מתרחש כאשר הפלטפורמה הוסיפה סוג חדש, מה שיכול לקרות בעת הוספת תכונות חדשות או במהלך הקשחת מדיניות.

  • תכונה חדשה . כאשר הסוג מסמן אובייקט שלא היה קיים בעבר (כגון תהליך שירות חדש), קוד הספק לא קיים עמו אינטראקציה ישירה בעבר ולכן לא קיימת מדיניות מתאימה. לתכונה החדשה המתאימה לסוג אין תכונה בגרסה הקודמת, ולכן לא תצטרך ערך בקובץ המיפוי המכוון לגרסה זו.
  • הקשחת מדיניות . כאשר הסוג מייצג הקשחת מדיניות, תכונת הסוג החדשה חייבת לקשר חזרה לשרשרת של תכונות התואמת לקודמתה (בדומה לדוגמה הקודמת המשנה /sys/A מ- sysfs ל- sysfs_A ). קוד הספק מסתמך על כלל המאפשר גישה ל- sysfs , וצריך לכלול את הכלל הזה כתכונה מהסוג החדש.

בעת שדרוג מ- v1v2 , מדיניות הפלטפורמה חייבת להכיל:

type sysfs_A; -> (type sysfs_A) (in CIL)
type sysfs; (type sysfs) (in CIL)

בקובץ המיפוי v1 (CIL):

(typeattributeset sysfs_v1 (sysfs sysfs_A))

בקובץ המיפוי v2 (CIL):

(typeattributeset sysfs_v2 (sysfs))
(typeattributeset sysfs_A_v2 (sysfs_A))

במדיניות הספק v1 (CIL):

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

במדיניות הספקים של v2 (CIL):

(typeattribute sysfs_A_v2)
(allow … sysfs_A_v2 …)
(typeattribute sysfs_v2)
(allow … sysfs_v2 …)
הוסרו סוגים

תרחיש (נדיר) זה מתרחש כאשר סוג מוסר, מה שיכול לקרות כאשר האובייקט הבסיסי:

  • נשאר אבל מקבל תווית אחרת.
  • מוסר על ידי הפלטפורמה.

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

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

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

גרסה 1 לדוגמה: סוגי כיווץ (הסרת sysfs_A)

בעת שדרוג מ- v1v2 , מדיניות הפלטפורמה חייבת להכיל:

type sysfs; (type sysfs) (in CIL)

בקובץ המיפוי v1 (CIL):

(typeattributeset sysfs_v1 (sysfs))
(type sysfs_A) # in case vendors used the sysfs_A label on objects
(typeattributeset sysfs_A_v1 (sysfs sysfs_A))

בקובץ המיפוי v2 (CIL):

(typeattributeset sysfs_v2 (sysfs))

במדיניות הספק v1 (CIL):

(typeattribute sysfs_A_v1)
(allow … sysfs_A_v1 …)
(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

במדיניות הספקים של v2 (CIL):

(typeattribute sysfs_v2)
(allow … sysfs_v2 …)

דוגמה גרסה 2: הסרה מלאה (סוג foo)

בעת שדרוג מ- v1v2 , מדיניות הפלטפורמה חייבת להכיל:

# nothing - we got rid of the type

בקובץ המיפוי v1 (CIL):

(type foo) #needed in case vendors used the foo label on objects
(typeattributeset foo_v1 (foo))

בקובץ המיפוי v2 (CIL):

# nothing - get rid of it

במדיניות הספק v1 (CIL):

(typeattribute foo_v1)
(allow foo …)
(typeattribute sysfs_v1)
(allow sysfs_v1 …)

במדיניות הספקים של v2 (CIL):

(typeattribute sysfs_v2)
(allow sysfs_v2 …)
כיתה/הרשאות חדשות

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

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

allow {domain -coredomain} *:new_class perm;

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

הכיתה/הרשאות הוסרו

תרחיש זה מתרחש כאשר מנהל אובייקטים מוסר (כגון מנהל האובייקטים ZygoteConnection ) ואינו אמור לגרום לבעיות. המחלקה וההרשאות של מנהל האובייקטים יכולות להישאר מוגדרות במדיניות עד שגרסת הספק לא תשתמש בה עוד. זה נעשה על ידי הוספת ההגדרות לקובץ המיפוי המתאים.

התאמה אישית של ספקים לסוגים חדשים/מתויגים מחדש

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

מכיוון שמדיניות הספקים היא תמיד הישנה ביותר במכשיר, אין צורך להמיר אוטומטית את כל סוגי הספקים למאפיינים במדיניות. הפלטפורמה אינה מסתמכת על שום דבר מסומן במדיניות הספקים מכיוון שלפלטפורמה אין ידע על כך; עם זאת, הפלטפורמה תספק את התכונות והסוגים הציבוריים שבהם היא משתמשת כדי ליצור אינטראקציה עם אובייקטים המסומנים עם סוגים אלה (כגון domain , sysfs_type וכו'). כדי שהפלטפורמה תמשיך לקיים אינטראקציה נכונה עם אובייקטים אלה, יש ליישם את התכונות והסוגים כראוי וייתכן שיהיה צורך להוסיף כללים ספציפיים לדומיינים הניתנים להתאמה אישית (כגון init ).

שינויים בתכונות עבור אנדרואיד 9

מכשירים שמשדרגים ל-Android 9 יכולים להשתמש בתכונות הבאות, אך אסור למכשירים המופעלים עם Android 9.

תכונות המפר

אנדרואיד 9 כולל את המאפיינים האלה הקשורים לתחום:

  • data_between_core_and_vendor_violators . תכונה לכל הדומיינים שמפרים את הדרישה לא לשתף קבצים לפי נתיב בין vendor לדומיינים coredomains . תהליכים של פלטפורמה וספק לא צריכים להשתמש בקבצים בדיסק כדי לתקשר (ABI לא יציב). המלצה:
    • קוד הספק צריך להשתמש ב- /data/vendor .
    • המערכת לא צריכה להשתמש ב- /data/vendor .
  • system_executes_vendor_violators . תכונה עבור כל תחומי המערכת (למעט דומיינים init ו- shell domains ) שמפרים את הדרישה של אי ביצוע קבצים בינאריים של ספקים. לביצוע של קבצים בינאריים של ספקים יש API לא יציב. פלטפורמה לא אמורה להפעיל בינאריים של ספקים ישירות. המלצה:
    • תלות כזו של פלטפורמה בקבצים בינאריים של ספקים חייבת להיות מאחורי HIDL HALs.

      אוֹ

    • יש להעביר coredomains שצריכים גישה לקוביות בינאריות של ספקים למחיצת הספק ובכך להפסיק להיות coredomain .

תכונות לא מהימנות

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

  1. שרתי HwBinder אינם מבצעים אימות לקוח מכיוון שכרגע HIDL אינו חושף מידע UID של המתקשר. גם אם HIDL אכן חשפה נתונים כאלה, שירותי HwBinder רבים פועלים ברמה מתחת לזו של אפליקציות (כגון, HALs) או שאסור להסתמך על זהות האפליקציה לצורך הרשאה. לפיכך, ליתר ביטחון, הנחת ברירת המחדל היא שכל שירות של HwBinder מתייחס לכל לקוחותיו כבעלי אישור שווה לבצע פעולות המוצעות על ידי השירות.
  2. שרתי HAL (תת-קבוצה של שירותי HwBinder) מכילים קוד עם שיעור שכיחות גבוה יותר של בעיות אבטחה מאשר רכיבי system/core ויש להם גישה לשכבות התחתונות של המחסנית (כל הדרך עד לחומרה) ובכך מגדילות את ההזדמנויות לעקוף את מודל האבטחה של אנדרואיד .

שירותים בטוחים

שירותי כספת כוללים:

  • same_process_hwservice . שירותים אלו (בהגדרה) פועלים בתהליך של הלקוח ובכך הם בעלי גישה זהה לתחום הלקוח בו מתנהל התהליך.
  • coredomain_hwservice . שירותים אלה אינם מהווים סיכונים הקשורים לסיבה מס' 2.
  • hal_configstore_ISurfaceFlingerConfigs . שירות זה תוכנן במיוחד לשימוש בכל תחום.
  • hal_graphics_allocator_hwservice . פעולות אלו מוצעות גם על ידי שירות surfaceflinger Binder, שאליו מורשים גישה לאפליקציות.
  • hal_omx_hwservice . זוהי גרסת HwBinder של שירות mediacodec Binder, שאליו אפליקציות מורשות לגשת.
  • hal_codec2_hwservice . זוהי גרסה חדשה יותר של hal_omx_hwservice .

תכונות שימושיות

לכל hwservices שאינם נחשבים בטוחים יש את התכונה untrusted_app_visible_hwservice . לשרתי HAL המתאימים יש את התכונה untrusted_app_visible_halserver . אסור למכשירים המופעלים עם אנדרואיד 9 להשתמש באף אחד מהמאפיינים untrusted .

המלצה:

  • אפליקציות לא מהימנות צריכות במקום זאת לדבר עם שירות מערכת שמדבר עם הספק HIDL HAL. לדוגמה, אפליקציות יכולות לדבר עם binderservicedomain , ואז mediaserver (שהוא binderservicedomain ) בתורו מדבר עם hal_graphics_allocator .

    אוֹ

  • אפליקציות הזקוקות לגישה ישירה ל-HAL vendor צריכות להיות עם תחום sepolicy משלהן המוגדר על ידי ספק.

בדיקות תכונות קובץ

אנדרואיד 9 כולל מבחני זמן בנייה המבטיחים שלכל הקבצים במיקומים ספציפיים יש את התכונות המתאימות (כגון, לכל הקבצים ב- sysfs יש את התכונה sysfs_type הנדרשת).

פלטפורמה-מדיניות ציבורית

מדיניות הפלטפורמה-ציבור היא הליבה של התאמה למודל ארכיטקטורת אנדרואיד 8.0 מבלי לשמור רק על האיחוד של מדיניות הפלטפורמה מ-v1 ו-v2. ספקים נחשפים לקבוצת משנה של מדיניות פלטפורמה המכילה סוגים ומאפיינים ניתנים לשימוש וכללים על אותם סוגים ותכונות, אשר לאחר מכן הופכים לחלק ממדיניות הספקים (כלומר vendor_sepolicy.cil ).

סוגים וכללים מתורגמים אוטומטית במדיניות שנוצרה על ידי הספק ל- attribute_v N כך שכל הסוגים המסופקים על ידי הפלטפורמה הם תכונות עם גרסאות (עם זאת, התכונות אינן מנוסחות). הפלטפורמה אחראית למיפוי הסוגים הקונקרטיים שהיא מספקת לתכונות המתאימות כדי להבטיח שמדיניות הספק ממשיכה לתפקד ושהכללים שסופקו עבור גרסה מסוימת כלולים. השילוב של מדיניות ציבורית של פלטפורמה ומדיניות ספקים עונה על מטרת מודל הארכיטקטורה של אנדרואיד 8.0 לאפשר בניית פלטפורמה וספק עצמאיים.

מיפוי לייחוס שרשראות

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

שמירה על מטרה להסתיר מידע על גרסה מכותב המדיניות פירושה יצירה אוטומטית של התכונות המנוסות והקצאתן לסוגים המתאימים. במקרה הנפוץ של טיפוסים סטטיים, זה פשוט: type_foo ממפה ל- type_foo_v1 .

עבור שינוי תווית אובייקט כגון sysfssysfs_A או mediaserveraudioserver , יצירת מיפוי זה אינה טריוויאלית (ומתוארת בדוגמאות לעיל). מנהלי מדיניות הפלטפורמה חייבים לקבוע כיצד ליצור את המיפוי בנקודות מעבר עבור אובייקטים, מה שדורש הבנת הקשר בין אובייקטים והתוויות שהוקצו להם וקביעה מתי זה מתרחש. עבור תאימות לאחור, המורכבות הזו צריכה להיות מנוהלת בצד הפלטפורמה, שהיא המחיצה היחידה שעלולה להופיע.

גרסה למעלה

לשם הפשטות, פלטפורמת אנדרואיד משחררת גרסת sepolicy כאשר נחתך ענף מהדורה חדש. כפי שתואר לעיל, מספר הגרסה כלול ב- PLATFORM_SEPOLICY_VERSION והוא בצורת MM.nn , כאשר MM מתאים לערך SDK ו- nn הוא ערך פרטי המתוחזק ב- /platform/system/sepolicy. לדוגמה, 19.0 עבור Kitkat, 21.0 עבור Lollipop, 22.0 עבור Lollipop-MR1 23.0 עבור Marshmallow, 24.0 עבור נוגט, 25.0 עבור Nougat-MR1, 26.0 עבור Oreo, 27.0 עבור Oreo-MR1 ו 28.0 arenv עבור Android. תמיד מספרים שלמים. לדוגמה, אם חבטת MR לגירסאות מחייבת שינוי לא תואם ב- system/sepolicy/public אך לא ב-API bump, גרסת ה-sepolicy יכולה להיות: vN.1 . הגרסה הקיימת בענף פיתוח היא 10000.0 שאף פעם לא יהיה בשימוש בהתקני-משלוח.

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

השפעת הביצועים של מספר תכונות

כפי שמתואר ב- https://github.com/SELinuxProject/cil/issues/9 , מספר רב של תכונות שהוקצו לסוג מביא לבעיות ביצועים במקרה של החמצת מטמון מדיניות.

זו אושרה כבעיה באנדרואיד, ולכן בוצעו שינויים באנדרואיד 8.0 כדי להסיר תכונות שנוספו למדיניות על ידי מהדר המדיניות, כמו גם כדי להסיר תכונות שאינן בשימוש. שינויים אלה פתרו רגרסיות ביצועים.

System_ext מדיניות ציבורית ומוצר ציבורית

החל מאנדרואיד 11, מחיצות system_ext ומחיצות המוצר רשאיות לייצא את הסוגים הציבוריים המיועדים להן למחיצת הספק. בדומה למדיניות ציבורית של הפלטפורמה, הספק משתמש בסוגים ובכללים המתורגמים אוטומטית לתכונות הגירסאות, למשל מ- type ל- type_ N , כאשר N היא הגרסה של הפלטפורמה שעל פיה בנויה מחיצת הספק.

כאשר מחיצות system_ext ומחיצות המוצר מבוססות על אותה גרסת פלטפורמה N , מערכת ה-build מייצרת קובצי מיפוי בסיסיים ל- system_ext/etc/selinux/mapping/ N .cil ו- product/etc/selinux/mapping/ N .cil , המכילים זהות. מיפויים type type_ N . הספק יכול לגשת type עם התכונה המנוסחת type_ N .

במקרה שרק מחיצות system_ext ומחיצות המוצר מתעדכנות, אמור N ל- N+1 (או מאוחר יותר), בעוד הספק נשאר ב- N , הספק עלול לאבד גישה לסוגי מערכת_ext ומחיצות המוצר. כדי למנוע שבירה, מחיצות system_ext ומחיצות המוצר צריכות לספק קובצי מיפוי מסוגי בטון למאפיינים type_ N כל שותף אחראי לתחזוקת קובצי המיפוי, אם הם מתכוונים לתמוך בספק N עם N+1 (או מאוחר יותר) system_ext ומחיצות מוצר.

לשם כך, השותפים צפויים:

  1. העתק את קובצי המיפוי הבסיסיים שנוצרו מ- N system_ext ומחיצות המוצר לעץ המקור שלהם.
  2. שנה את קבצי המיפוי לפי הצורך.
  3. התקן את קובצי המיפוי ל- N+1 (או מאוחר יותר) system_ext ומחיצות המוצר.

לדוגמה, נניח של- N system_ext יש סוג ציבורי אחד בשם foo_type . אז system_ext/etc/selinux/mapping/ N .cil במחיצת N system_ext ייראה כך:

(typeattributeset foo_type_N (foo_type))
(expandtypeattribute foo_type_N true)
(typeattribute foo_type_N)

אם bar_type מתווסף ל- N+1 system_ext, ואם יש למפות bar_type ל- foo_type עבור ספק N , ניתן לעדכן את N .cil מ-

(typeattributeset foo_type_N (foo_type))

ל

(typeattributeset foo_type_N (foo_type bar_type))

ולאחר מכן מותקן במחיצה של N+1 system_ext. ספק N יכול להמשיך לגשת ל- foo_type ו- bar_type של N+1 system_ext.

תיוג הקשרי SELinux

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

הקשרי קובץ

אנדרואיד 8.0 הציגה את השינויים הבאים עבור file_contexts :

  • כדי למנוע תקורה נוספת של קומפילציה במכשיר במהלך האתחול, file_contexts מפסיקים להתקיים בצורה הבינארית. במקום זאת, הם קריאים, קובץ טקסט של ביטוי רגולרי כגון {property, service}_contexts (כפי שהיו לפני 7.0).
  • ה- file_contexts מחולקים בין שני קבצים:
    • plat_file_contexts
      • פלטפורמת אנדרואיד file_context שאין לה תוויות ספציפיות למכשיר, למעט תיוג חלקים של מחיצת /vendor שיש לתייג במדויק כדי להבטיח תפקוד תקין של קובצי ה-sepolicy.
      • חייב להתגורר במחיצת system ב- /system/etc/selinux/plat_file_contexts במכשיר ולהיטען על ידי init בהתחלה יחד עם הספק file_context .
    • vendor_file_contexts
      • file_context ספציפי למכשיר שנבנה על ידי שילוב של file_contexts שנמצאו בספריות שעליהן הצביע BOARD_SEPOLICY_DIRS בקבצי Boardconfig.mk של המכשיר.
      • יש להתקין ב- /vendor/etc/selinux/vendor_file_contexts במחיצת vendor ולהיטען על ידי init בהתחלה יחד עם הפלטפורמה file_context .

הקשרי נכס

באנדרואיד 8.0, ה- property_contexts מפוצל בין שני קבצים:

  • plat_property_contexts
    • פלטפורמת Android property_context שאין לה תוויות ספציפיות למכשיר.
    • חייב להתגורר במחיצת system ב- /system/etc/selinux/plat_property_contexts ולהיטען על ידי init בהתחלה יחד עם הספק property_contexts .
  • vendor_property_contexts
    • property_context ספציפי למכשיר שנבנה על ידי שילוב של property_contexts שנמצאו בספריות שעליהן הצביע BOARD_SEPOLICY_DIRS בקבצי Boardconfig.mk של המכשיר.
    • חייב להתגורר במחיצת vendor ב- /vendor/etc/selinux/vendor_property_contexts ולהיטען על ידי init בהתחלה יחד עם הפלטפורמה property_context

הקשרי שירות

באנדרואיד 8.0, service_contexts מפוצל בין הקבצים הבאים:

  • plat_service_contexts
    • service_context ספציפי לפלטפורמת Android עבור servicemanager . ל- service_context אין תוויות ספציפיות למכשיר.
    • חייב להתגורר במחיצת system ב- /system/etc/selinux/plat_service_contexts ולהיטען על ידי servicemanager בהתחלה יחד עם הספק service_contexts .
  • vendor_service_contexts
    • service_context ספציפי למכשיר שנבנה על ידי שילוב של service_contexts שנמצאו בספריות שעליהן הצביע BOARD_SEPOLICY_DIRS בקבצי Boardconfig.mk של המכשיר.
    • חייב להתגורר במחיצת vendor ב- /vendor/etc/selinux/vendor_service_contexts ולהיטען על ידי servicemanager בהתחלה יחד עם הפלטפורמה service_contexts .
    • למרות servicemanager מחפש את הקובץ הזה בזמן האתחול, עבור התקן TREBLE תואם לחלוטין, ה- vendor_service_contexts אסור להתקיים. הסיבה לכך היא שכל האינטראקציה בין תהליכי vendor system חייבת לעבור דרך hwservicemanager / hwbinder .
  • plat_hwservice_contexts
    • פלטפורמת Android hwservice_context עבור hwservicemanager שאין לה תוויות ספציפיות למכשיר.
    • חייב להתגורר במחיצת system ב- /system/etc/selinux/plat_hwservice_contexts ולהיטען על ידי hwservicemanager בהתחלה יחד עם vendor_hwservice_contexts .
  • vendor_hwservice_contexts
    • hwservice_context ספציפי למכשיר שנבנה על ידי שילוב של hwservice_contexts שנמצאו בספריות שעליהן הצביע BOARD_SEPOLICY_DIRS בקבצי Boardconfig.mk של המכשיר.
    • חייב להתגורר במחיצת vendor ב- /vendor/etc/selinux/vendor_hwservice_contexts ולהיטען על ידי hwservicemanager בהתחלה יחד עם plat_service_contexts .
  • vndservice_contexts
    • service_context ספציפי למכשיר עבור vndservicemanager שנבנה על ידי שילוב vndservice_contexts שנמצאו בספריות שעליהן הצביע BOARD_SEPOLICY_DIRS ב- Boardconfig.mk של המכשיר.
    • קובץ זה חייב להימצא במחיצת vendor בכתובת /vendor/etc/selinux/vndservice_contexts ולהיטען על ידי vndservicemanager בהתחלה.

הקשרים של Seapp

באנדרואיד 8.0, seapp_contexts מפוצל בין שני קבצים:

  • plat_seapp_contexts
    • פלטפורמת אנדרואיד seapp_context שאין בה שינויים ספציפיים למכשיר.
    • חייב להתגורר במחיצת system ב- /system/etc/selinux/plat_seapp_contexts.
  • vendor_seapp_contexts
    • הרחבה ספציפית למכשיר לפלטפורמה seapp_context שנבנתה על ידי שילוב של seapp_contexts שנמצאו בספריות שעליהן הצביע BOARD_SEPOLICY_DIRS בקבצי Boardconfig.mk של המכשיר.
    • חייב להתגורר במחיצת vendor ב- /vendor/etc/selinux/vendor_seapp_contexts .

הרשאות MAC

באנדרואיד 8.0, הקובץ mac_permissions.xml מחולק בין שני קבצים:

  • פלטפורמה mac_permissions.xml
    • פלטפורמת Android mac_permissions.xml שאין בה שינויים ספציפיים למכשיר.
    • חייב להתגורר במחיצת system ב- /system/etc/selinux/.
  • ללא פלטפורמה mac_permissions.xml
    • הרחבה ספציפית למכשיר לפלטפורמה mac_permissions.xml שנבנתה מ- mac_permissions.xml שנמצאת בספריות שעליהן הצביע BOARD_SEPOLICY_DIRS בקבצי Boardconfig.mk של המכשיר.
    • חייב להתגורר במחיצת vendor ב- /vendor/etc/selinux/.