במאמר הזה מתואר איך מערכת Android מטפלת בבעיות תאימות למדיניות עם OTA בפלטפורמה, שבה ההגדרות של SELinux בפלטפורמה החדשות עשויות להיות שונות מהספק הישן הגדרות SELinux.
תכנון מדיניות SELinux שמבוסס על טרבל מביא בחשבון הבחנה בינארית
בין מדיניות platform למדיניות ספק; הסכמה הופכת
מורכבים יותר אם מחיצות של ספקים יוצרות יחסי תלות, כמו
platform
< vendor
< oem
ב-Android מגרסה 8.0 ואילך, המדיניות הגלובלית של SELinux מחולקת לפרטי ורכיבים ציבוריים. הרכיבים הציבוריים מורכבים מהמדיניות תשתית שמובטחת להיות זמינה בגרסת פלטפורמה. המדיניות הזו תיחשף לכותבי מדיניות הספקים כדי לאפשר לספקים ליצור קובץ מדיניות ספק, שבשילוב עם המדיניות שסופקה על ידי הפלטפורמה, תיצור מדיניות לגבי פונקציונליות מלאה של המכשיר.
- במסגרת ניהול גרסאות, המדיניות שמיוצאת לפלטפורמה-ציבורית תיכתב כך: מאפיינים.
- כדי להקל על כתיבת המדיניות, הסוגים המיוצאים יומרו מאפיינים כחלק מתהליך ה-build של המדיניות. גלוי לכולם יכול להיות שנשתמש בהם גם באופן ישיר, בהחלטות לגבי תוויות שסופקו על ידי הספק קובצי הקשרים.
ב-Android נשמר מיפוי בין סוגי הבטון שיוצאו בפלטפורמה המדיניות שלנו ואת המאפיינים בעלי הגרסאות התואמים של כל פלטפורמה . הדבר מבטיח שכאשר אובייקטים מתויגים באמצעות סוג, אינה מפרה את ההתנהגות המובטחת על ידי מדיניות הפלטפורמה-ציבורית . המיפוי הזה נשמר על ידי שמירה על קובץ מיפוי עדכני כל גרסת פלטפורמה, שבה נשמרים פרטי החברות של כל אחת מהפלטפורמות הסוג שמיוצא במדיניות הציבורית.
בעלות ותיוג של אובייקטים
במהלך התאמה אישית של המדיניות ב-Android מגרסה 8.0 ואילך, צריך להגדיר בעלות בבירור
עבור כל אובייקט, כדי לשמור בנפרד על מדיניות הפלטפורמה והספק. לדוגמה, אם
תוויות הספק /dev/foo
, הפלטפורמה, ואז תוויות
/dev/foo
ב-OTA הבא, תהיה התנהגות לא מוגדרת. עבור
SELinux, שמתבטא בהתנגשות בין תוויות. צומת המכשיר יכול לכלול רק
תווית אחת שמפנה לתווית האחרונה שהוחלה. כתוצאה מכך:
- תהליכים שצריכים גישה לתווית שהוחלה עליהם בהצלחה יאבדו את הגישה למשאב.
- תהליכים שמקבלים גישה לקובץ עלולים לא לפעול בגלל שגיאה הצומת של המכשיר נוצר.
במאפייני המערכת יש גם פוטנציאל להתנגשויות בין שמות שעלולות לגרום התנהגות לא מוגדרת במערכת (וגם לסימון SELinux). התנגשויות בין תוויות הפלטפורמה לתוויות הספק יכולות להתרחש כל אובייקט עם SELinux כולל מאפיינים, שירותים, תהליכים, קבצים ו-sockets. כדי להימנע של הבעיות האלה, להגדיר בבירור את הבעלות על האובייקטים.
בנוסף להתנגשויות של תוויות, שמות של סוג/מאפיינים SELinux עשויים להתנגש. התנגשות בין שמות של סוג או מאפיין תמיד תוביל לשגיאת מהדר של מדיניות.
ריווח שמות של סוג/מאפיינים
ב-SELinux אי אפשר להשתמש בהצהרות מרובות מאותו סוג או מאותו מאפיין. מדיניות
עם הצהרות כפולות, לא יהיה אוסף. כדי להימנע משימוש בהקלדה
התנגשויות בין שמות מאפיינים, כל הצהרות הספקים צריכות להיות במרחב שמות
החל מ-vendor_
.
type foo, domain; → type vendor_foo, domain;
מאפיין מערכת וגם תהליך הבעלות על תוויות
עדיף להימנע מהתנגשויות בין תוויות באמצעות מרחבי שמות של נכסים. שפת תרגום לזהות בקלות את מאפייני הפלטפורמה ולהימנע מהתנגשויות שמות כשמשנים שם או מוסיפים נכסים של פלטפורמה מיוצאת, מוודאים שלכל נכסי הספקים יש קידומות משלו:
סוג הנכס | תחיליות מקובלות |
---|---|
מאפייני בקרה | ctl.vendor. ctl.start$vendor. ctl.stop$vendor. init.svc.vendor.
|
ניתן לכתיבה | vendor. |
קריאה-בלבד | ro.vendor. ro.boot. ro.hardware.
|
מתמיד | persist.vendor. |
ספקים יכולים להמשיך להשתמש ב-ro.boot.*
(שמקורו בליבה (kernel)
cmdline) ו-ro.hardware.*
(מאפיין ברור שקשור לחומרה).
כל שירותי הספק בקובצי rc התחלתיים צריכים להכיל vendor.
לשירותים באתחול קובצי rc של מחיצות שהן לא מערכת. כללים דומים הם
הוחלו על תוויות SELinux עבור מאפייני הספק (vendor_
של מאפייני הספק).
בעלות על קובץ
קשה למנוע התנגשויות בין קבצים, כי הפלטפורמה והספק הן בדרך כלל מספקים תוויות לכל מערכות הקבצים. בשונה ממתן שמות לסוגים, אין אפשרות ליישם רווחים בין שמות קבצים, מכיוון שרבים מהם נוצרים של הליבה. כדי למנוע התנגשויות כאלה, צריך לפעול לפי ההנחיות למתן שמות למערכות קבצים בקטע הזה. ב-Android 8.0, אלה המלצות ללא דרישות טכניות לאכיפה. בעתיד, ההמלצות האלה ייאכפו על ידי חבילת בדיקה של ספקים (VTS).
מערכת (/מערכת)
רק תמונת המערכת חייבת לספק תוויות לרכיבי /system
עד file_contexts
, service_contexts
וכו'. אם תוויות
לרכיבי /system
נוספו במדיניות /vendor
,
יכול להיות שלא תוכלו לעדכן OTA רק באמצעות framework.
ספק (/ספק)
מדיניות AOSP SELinux כבר מציינת חלקים ממחיצה vendor
הפלטפורמה מקיימת אינטראקציה איתן, וכך מאפשרת לכתוב כללי SELinux לפלטפורמה
כדי שיוכלו לדבר ו/או לגשת לחלקים של vendor
מחיצה. לדוגמה:
נתיב אחד (/vendor ) |
תווית של הפלטפורמה | תהליכי פלטפורמה בהתאם לתווית |
---|---|---|
/vendor(/.*)?
|
vendor_file
|
כל לקוחות HAL ב-framework, 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
. הזה נאכף באמצעות איסורים. - כדי למנוע התנגשויות עם עדכונים עתידיים של פלטפורמה או framework, מומלץ לא להוסיף תוויות
קבצים אחרים מלבד
exec_types
במחיצהvendor
. - לכל יחסי התלות של ספריות עבור HAL של תהליך שמזוהה על ידי AOSP צריך להיות
מתויג בתור
same_process_hal_file.
Procfs (/proc)
ניתן לתייג קבצים בתיקייה /proc
באמצעות genfscon
בלבד
התיוג. ב-Android 7.0, גם
פלטפורמה
וספק
המדיניות משתמשת ב-genfscon
כדי להוסיף תוויות לקבצים ב-procfs
.
המלצה: רק תוויות של מדיניות הפלטפורמה /proc
.
אם ל-vendor
תהליכים נדרשת גישה לקבצים ב-/proc
מתויגות כרגע בתווית ברירת המחדל (proc
), מדיניות הספק
לא צריך לתייג אותם במפורש, אלא להשתמש במקום זאת
סוג proc
כדי להוסיף כללים לדומיינים של ספקים. זה מאפשר לפלטפורמה
עדכונים כדי להתאים לממשקי ליבה עתידיים שנחשפו דרך
procfs
ותייגו אותם במפורש לפי הצורך.
ניפוי באגים (/sys/kernel/debug)
אפשר להוסיף תווית ל-Debugfs
גם ב-file_contexts
וגם
genfscon
. מ-Android 7.0 עד Android 10, גם תווית הפלטפורמה וגם תווית הספק
debugfs
ב-Android 11, לא ניתן להשתמש ב-debugfs
מתבצעת גישה או טעינה למכשירים בסביבת הייצור. יצרני מכשירים צריכים
הסרה של debugfs
.
Tracefs (/sys/kernel/debug/tracing)
אפשר להוסיף תווית ל-Tracefs
גם ב-file_contexts
וגם
genfscon
. ב-Android 7.0, רק תוויות הפלטפורמה
tracefs
המלצה: רק פלטפורמה יכולה להוסיף תווית tracefs
.
Sysfs (/sys)
יכול להיות שקבצים בתיקייה /sys
יתויגו באמצעות המאפיינים file_contexts
ו-genfscon
. ב-Android 7.0, השימוש בפלטפורמה וגם בספק
file_contexts
ו-genfscon
כדי להוסיף תוויות לקבצים ב
sysfs
.
המלצה: יכול להיות שהפלטפורמה תתייג את התווית sysfs
צמתים שלא ספציפיים למכשיר. אחרת, רק הספק יכול להוסיף תוויות לקבצים.
tmpfs (/dev)
יכול להיות שקבצים בתיקייה /dev
יתויגו ב-file_contexts
. לחשבון
Android 7.0, כאן מופיעים קובצי תוויות של הפלטפורמה והספק.
המלצה: הספק יכול להוסיף תווית רק לקבצים שנמצאים
/dev/vendor
(למשל, /dev/vendor/foo
,
/dev/vendor/socket/bar
).
Rootfs (/)
יכול להיות שקבצים בתיקייה /
יתויגו ב-file_contexts
. ב-Android
7.0, כאן מופיעים קובצי תוויות של הפלטפורמה והספק.
המלצה: רק המערכת יכולה להוסיף תוויות לקבצים שנמצאים ב-/
.
נתונים (/נתונים)
הנתונים מתויגים באמצעות שילוב של 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
החדש
מהסוג הזה.
על ידי הגדרת מדיניות במונחים של מאפיינים, אנחנו יכולים לתת לאובייקט הבסיסי יש מאפיין שתואם למדיניות גם לגבי הפלטפורמה וגם בקוד הספק. אפשר לעשות את זה בכל הסוגים כדי ליצור ביעילות attribute-Policy שבו סוגים קונקרטיים אף פעם לא בשימוש. בפועל, צריך לעשות זאת רק לגבי רכיבי המדיניות שחופפים בין פלטפורמה והספק, שמוגדרים כמדיניות ציבורית של הפלטפורמה שמובנית כחלק ממדיניות הספקים.
הגדרת מדיניות ציבורית כמאפיינים בעלי גרסאות עומדת בדרישות של שתי סעיפי מדיניות יעדי תאימות:
- מוודאים שקוד הספק ממשיך לפעול אחרי עדכון הפלטפורמה. הושג על ידי הוספת מאפיינים לסוגים קונקרטיים של אובייקטים שתואמים ל אלה שעליהם הסתמכו קוד הספק, תוך שמירה על הגישה.
- יכולת להוציא משימוש את המדיניות. הושג באופן ברור שמגדירה מדיניות למאפיינים שניתן להסיר ברגע הגרסה שאליה הם משויכים כבר לא נתמכת. יכולת הפיתוח להמשיך בפלטפורמה, ידיעה שהמדיניות הישנה עדיין קיימת המדיניות לספקים, ותוסר באופן אוטומטי כאשר/אם היא ישודרגו.
יכולת כתבי המדיניות
כדי לעמוד במטרה שלא נדרש ידע לגבי שינויים מסוימים בגרסאות של
ו-Android 8.0 כולל מיפוי בין פלטפורמה ציבורית
עקרונות המדיניות והמאפיינים שלהם. הסוג foo
ממופה
למאפיין foo_vN
, כאשר N
הוא
גרסה מטורגטת. vN
תואם ל-
משתנה build PLATFORM_SEPOLICY_VERSION
בפורמט
MM.NN
, כאשר MM
תואם למספר ה-SDK של הפלטפורמה
ו-NN
היא גרסה ספציפית למדיניות בנושא מדיניות.
למאפיינים במדיניות הציבורית אין גרסאות, אלא קיימים כ-API ב- איזו מדיניות ספק ופלטפורמה אפשר ליצור כדי לשמור על הממשק בין השניים המחיצות יציבות. בעלי הרשאת כתיבה של מדיניות הפלטפורמה והספק יכולים להמשיך לכתוב המדיניות כפי שהיא נכתבת היום.
מדיניות ציבורית של פלטפורמה שמיוצאת כ-allow source_foo target_bar:class
perm;
נכללת במדיניות הספק. במהלך
compilation (שכולל את
גרסה תואמת) היא עוברת טרנספורמציה למדיניות שתפנה אל
החלק של הספק במכשיר (מוצג בנתוני הביניים שעברו שינוי
שפה (CIL)):
(allow source_foo_vN target_bar_vN (class (perm)))
מאחר שמדיניות הספק אף פעם לא נמצאת בחזית הפלטפורמה, אין צורך לדאוג לגביה בגרסאות קודמות. עם זאת, מדיניות הפלטפורמה צריכה לדעת עד כמה הספק רחוק היא לכלול את המאפיינים של הסוגים ולהגדיר מדיניות שתואמת של גרסאות שונות.
הבדלים במדיניות
יצירה אוטומטית של מאפיינים על ידי הוספה של _vN
לסוף
מכל סוג לא עושה שום דבר בלי למפות את המאפיינים לסוגים שונים של הגרסה
שונים. מערכת Android שומרת על מיפוי בין הגרסאות של המאפיינים
מיפוי של סוגים למאפיינים האלה. זה נעשה במיפוי שהוזכר
קבצים שמכילים הצהרות כמו (CIL):
(typeattributeset foo_vN (foo))
שדרוגי פלטפורמות
בקטע הבא מתוארים תרחישים של שדרוגים לפלטפורמה.
סוגים זהים
התרחיש הזה מתרחש כשאובייקט לא משנה תוויות בגרסאות של מדיניות.
הדבר זהה לסוגי מקור ויעד, וניתן לראות את הנתונים האלה כך
/dev/binder
, עם התווית binder_device
בכל המוצרים
גרסאות חדשות. הוא מיוצג במדיניות שעברה שינוי כך:
binder_device_v1 … binder_device_vN
כשמשדרגים מ-v1
← v2
, מדיניות הפלטפורמה חייבת
מכילים:
type binder_device; -> (type binder_device) (in CIL)
בקובץ המיפוי v1 (CIL):
(typeattributeset binder_device_v1 (binder_device))
בקובץ המיפוי v2 (CIL):
(typeattributeset binder_device_v2 (binder_device))
במדיניות לספקים בגרסה 1 (CIL):
(typeattribute binder_device_v1) (allow binder_device_v1 …)
במדיניות לספקים בגרסה 2 (CIL):
(typeattribute binder_device_v2) (allow binder_device_v2 …)
סוגים חדשים
התרחיש הזה מתרחש כשהפלטפורמה הוסיפה סוג חדש, וזה יכול לקרות כשמוסיפים תכונות חדשות או במהלך הקשחת המדיניות.
- תכונה חדשה. כשהסוג מתייג לאובייקט שסומן שלא היה קיים בעבר (למשל, תהליך שירות חדש), קוד הספק הייתה אינטראקציה ישירה איתו בעבר, כך שלא קיימת מדיניות תואמת. הגרסה החדשה לסוג המתאים אין מאפיין כך שלא תצטרכו רשומה במיקוד של קובץ המיפוי, .
- הקשחת מדיניות. כשהסוג מייצג מדיניות
הקשחה, מאפיין הסוג החדש חייב לקשר חזרה לשרשרת של מאפיינים
שתואמת לדוגמה הקודמת (בדומה לדוגמה הקודמת 'שינוי'
/sys/A
מ-sysfs
עדsysfs_A
). הספק הקוד מסתמך על כלל שמאפשר גישה אלsysfs
, כדי לכלול את הכלל הזה כמאפיין מהסוג החדש.
כשמשדרגים מ-v1
← v2
, מדיניות הפלטפורמה חייבת
מכילים:
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))
במדיניות לספקים בגרסה 1 (CIL):
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
במדיניות לספקים בגרסה 2 (CIL):
(typeattribute sysfs_A_v2) (allow … sysfs_A_v2 …) (typeattribute sysfs_v2) (allow … sysfs_v2 …)
סוגים שהוסרו
תרחיש (נדיר) זה מתרחש לאחר הסרת סוג, שיכול לקרות כאשר אובייקט בסיסי:
- נשאר אבל מקבל תווית אחרת.
- הוסר על ידי הפלטפורמה.
במהלך השחרור של המדיניות, המערכת מסירה סוג והאובייקט עם תווית הסוג הזה מקבלים תווית אחרת שכבר קיימת. הדבר מייצג מיזוג של מיפויי מאפיינים: לקוד הספק עדיין צריכה להיות גישה באמצעות התכונה שהיה לה בעבר, אבל שאר המערכת חייבת יוכל לגשת אליו באמצעות המאפיין החדש.
אם המאפיין שאליו המאפיין הוחלף הוא חדש, התווית מחדש היא כמו במקרה של סוג האותיות החדש, מלבד במקרים שבהם נעשה שימוש בתווית קיימת, הפונקציה תוספת של המאפיין הישן מהסוג החדש תגרום לתוויות של אובייקטים אחרים מסוג כזה, יהיו נגישים חדשים. זה בעצם מה שעושה ונחשב להצעה קבילה לשמירה על בתאימות מלאה.
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
דוגמה 1: סוגי כיווץ (הסרת sysfs_A)
כשמשדרגים מ-v1
← v2
, מדיניות הפלטפורמה חייבת
מכילים:
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))
במדיניות לספקים בגרסה 1 (CIL):
(typeattribute sysfs_A_v1) (allow … sysfs_A_v1 …) (typeattribute sysfs_v1) (allow … sysfs_v1 …)
במדיניות לספקים בגרסה 2 (CIL):
(typeattribute sysfs_v2) (allow … sysfs_v2 …)
דוגמה 2: הסרה מלאה (סוג foo)
כשמשדרגים מ-v1
← v2
, מדיניות הפלטפורמה חייבת
מכילים:
# 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
במדיניות לספקים בגרסה 1 (CIL):
(typeattribute foo_v1) (allow foo …) (typeattribute sysfs_v1) (allow sysfs_v1 …)
במדיניות לספקים בגרסה 2 (CIL):
(typeattribute sysfs_v2) (allow sysfs_v2 …)
כיתה או הרשאות חדשות
התרחיש הזה מתרחש כששדרוג הפלטפורמה כולל רכיבי מדיניות חדשים
שלא קיימות בגרסאות הקודמות. לדוגמה, כשמערכת Android הוסיפה את
מנהל האובייקטים servicemanager
שיצר את ההוספה, החיפוש והרשימה
הרשאות, דימויים של ספקים שרוצים להירשם
ל-servicemanager
הרשאות נדרשות שלא
זמינים. ב-Android 8.0, רק מדיניות הפלטפורמה יכולה להוסיף סיווגים חדשים
הרשאות.
כדי להתיר את כל הדומיינים שניתן היה ליצור או להרחיב בהתאם למדיניות הספק כדי להשתמש במחלקה החדשה ללא הפרעות, מדיניות הפלטפורמה צריכה לכלול דומה ל:
allow {domain -coredomain} *:new_class perm;
לשם כך נדרשת אפילו מדיניות שמאפשרת גישה לכל הממשקים (מדיניות ציבורית) כדי לוודא שתמונת הספק מקבלת גישה. אם התוצאה של המדיניות הזו היא מדיניות אבטחה (כפי שהיא עשויה להיות עם שינויים של מנהל שירות), ספק שיש אפשרות לאלץ את השדרוג.
כיתה/הרשאות הוסרו
התרחיש הזה מתרחש כשמסירים מנהל אובייקטים (למשל
ZygoteConnection
מנהל אובייקטים) ולא אמור לגרום לבעיות.
המחלקה וההרשאות של מנהל אובייקטים יישארו מוגדרות במדיניות עד
של הספק כבר לא משתמשת בו. כדי לעשות את זה, מוסיפים את ההגדרות.
לקובץ המיפוי המתאים.
התאמה אישית של ספק עבור סוגים חדשים/מסומנים מחדש
סוגי ספקים חדשים נמצאים בליבה של פיתוח מדיניות ספקים, לפי הצורך כדי לתאר תהליכים, קבצים בינאריים, מכשירים, מערכות משנה ונתונים מאוחסנים חדשים. בתור ולכן חשוב לאפשר יצירה של סוגים שמוגדרים על ידי הספק.
מדיניות הספק היא תמיד הישנה ביותר במכשיר, לכן אין צורך
להמיר באופן אוטומטי את כל סוגי הספקים למאפיינים במדיניות. הפלטפורמה
לא מסתמכת על פריטים שסומנו במדיניות הספק, כי הפלטפורמה לא
ידע עליו; עם זאת, הפלטפורמה תספק את המאפיינים
הסוגים שבהם הוא משתמש כדי לקיים אינטראקציה עם אובייקטים שתויגו עם הסוגים האלה (כמו
domain
, sysfs_type
וכו'). כדי שהפלטפורמה
ימשיכו לפעול בצורה תקינה עם האובייקטים האלה, המאפיינים והסוגים
חייב להיות מיושם כראוי וייתכן שיהיה צורך להוסיף כללים ספציפיים
דומיינים שניתנים להתאמה אישית (כמו init
).
שינויים במאפיינים ל-Android 9
במכשירים שמשדרגים ל-Android 9 אפשר להשתמש במאפיינים הבאים, אבל מכשירים כשמשיקים עם Android 9, אסור.
מאפייני ההפרה
מערכת Android 9 כוללת את המאפיינים הבאים שקשורים לדומיין:
data_between_core_and_vendor_violators
מאפיין לכל הדומיינים שמפרים את הדרישה שלא לשתף קבצים עד נתיב ביןvendor
ל-coredomains
. פלטפורמה ו אסור להשתמש בתהליכי ספק בקבצים בדיסק כדי לתקשר (ABI לא יציב). המלצה:- קוד הספק צריך להשתמש ב-
/data/vendor
. - המערכת לא צריכה להשתמש ב-
/data/vendor
.
- קוד הספק צריך להשתמש ב-
system_executes_vendor_violators
תכונה עבור כל הדומיינים של המערכת (למעטinit
ו-shell domains
) שמפרות את הדרישה לאי-שימוש בקבצים בינאריים של ספקים. ביצוע של בקבצים הבינאריים של הספקים יש API לא יציב. אין להפעיל קבצים בינאריים של ספקים בפלטפורמה ישירות. המלצה:- יחסי התלות של פלטפורמה שכאלו בקבצים הבינאריים של ספקים חייבים להיות מאחורי תקן HIDL HAL.
או
coredomains
שצריכים גישה לקבצים הבינאריים של הספקים צריכים להיות הועבר למחיצת הספק, וכתוצאה מכך להפסיק להיותcoredomain
.
- יחסי התלות של פלטפורמה שכאלו בקבצים הבינאריים של ספקים חייבים להיות מאחורי תקן HIDL HAL.
מאפיינים לא מהימנים
לאפליקציות לא מהימנות שמארחות קוד שרירותי לא צריכה להיות גישה ל-HwBinder שירותים, מלבד אלה שנחשבים בטוחים מספיק לגישה מאפליקציות כאלה (השירותים הבטוחים מפורטים בהמשך). שתי הסיבות העיקריות לכך הן:
- שרתי HwBinder לא מבצעים אימות לקוח כי כרגע HIDL לא חושפת את פרטי UID של המתקשר. גם אם HIDL כן חשף נתונים כאלה, שירותי HwBinder פועלים ברמה נמוכה מזו של אפליקציות (כמו HAL) לא יכולה להסתמך על זהות האפליקציה לצורך קבלת הרשאה. לכן, מטעמי בטיחות, ברירת המחדל ההנחה היא שכל שירות HwBinder מתייחס לכל הלקוחות שלו באופן שווה מורשה לבצע פעולות שהשירות מציע.
- שרתי HAL (קבוצת משנה של שירותי HwBinder) מכילים קוד עם
שיעור המקרים של בעיות אבטחה בהשוואה לרכיבי
system/core
גישה לשכבות התחתונות של המקבץ (עד לחומרה) הזדמנויות הולכות וגדלות של עקיפה של מודל האבטחה של Android.
שירותי כספות
שירותי הכספת כוללים:
same_process_hwservice
השירותים האלה (מהגדרתם) פועלים ב- את התהליך של הלקוח, כך שתהיה להם גישה זהה לזו של דומיין הלקוח שהתהליך מריץ.coredomain_hwservice
השירותים האלה לא יוצרים סיכונים שמשויכת לסיבה מספר 2.hal_configstore_ISurfaceFlingerConfigs
השירות הזה תוכנן במיוחד לשימוש בכל דומיין.hal_graphics_allocator_hwservice
הפעולות האלה מוצע על ידי שירות Binder שלsurfaceflinger
, אילו אפליקציות מותרות כדי לגשת אליה.hal_omx_hwservice
זוהי גרסת HwBinder שלmediacodec
שירות Binder, שאליו יש לאפליקציות גישה.hal_codec2_hwservice
זוהי גרסה חדשה יותר שלhal_omx_hwservice
.
מאפיינים שאפשר להשתמש בהם
לכל hwservices
הלא נחשבים בטוחים יש את המאפיין
untrusted_app_visible_hwservice
. לשרתי HAL התואמים יש
המאפיין untrusted_app_visible_halserver
. המכשירים שמופעלים
עם Android 9 אסור להשתמש באף אחת מהאפשרויות
מאפיין untrusted
.
המלצה:
- אפליקציות לא מהימנות צריכות במקום זאת לדבר עם שירות מערכת שמדבר
הספק HIDL HAL. לדוגמה, אפליקציות יכולות לדבר אל
binderservicedomain
ואז אלmediaserver
(שהואbinderservicedomain
) בתורו מדבר עםhal_graphics_allocator
.או
- אפליקציות שזקוקות לגישה ישירה ל-
vendor
HALs דומיין מדיניות סחף שהוגדר על ידי הספק.
בדיקות של מאפייני קובץ
ב-Android 9 יש בדיקות זמן יצירה שמבטיחות שכל הקבצים
כוללים את המאפיינים המתאימים (כמו כל הקבצים
sysfs
כוללים את מאפיין החובה sysfs_type
).
מדיניות בנושא פלטפורמה ציבורית
מדיניות הפלטפורמה-ציבורית היא הליבה של תאימות ל-Android 8.0
של הארכיטקטורה מבלי לשמור על האיחוד של כללי מדיניות הפלטפורמה
בגרסאות v1 ו-v2. הספקים נחשפים לקבוצת משנה של מדיניות הפלטפורמה,
שכולל סוגים, מאפיינים וכללים שאפשר להשתמש בהם לגבי הסוגים והמאפיינים האלה.
שהופך לאחר מכן לחלק ממדיניות הספק (כלומר
vendor_sepolicy.cil
).
הסוגים והכללים מתורגמים באופן אוטומטי במדיניות שנוצרה על ידי הספק
ל-attribute_vN
, כך שכל הסוגים שמסופקים על ידי הפלטפורמה
הם מאפיינים עם גרסאות (עם זאת, אין גרסאות של מאפיינים). הפלטפורמה היא
היא אחראית למיפוי הסוגים הבטון שהוא מספק
כדי להבטיח שמדיניות הספק תמשיך לפעול,
שסופקו עבור גרסה מסוימת. השילוב של
המדיניות הציבורית והמדיניות בנושא ספקים עומדים בדרישות הארכיטקטורה של Android 8.0
היא לאפשר פיתוחים עצמאיים של פלטפורמות וספקים.
מיפוי לשרשראות של מאפיינים
כשמשתמשים במאפיינים למיפוי לגרסאות מדיניות, סוג ממופה למאפיין או כמה מאפיינים, כדי להבטיח גישה לאובייקטים בעלי התוויות מהסוג הזה דרך שתואמים לסוגים הקודמים.
שמירה על יעד כדי להסתיר פרטי גרסה מכותב המדיניות
יוצרת באופן אוטומטי את המאפיינים בעלי הגרסאות ומקצה אותם
הסוגים המתאימים. במקרה הנפוץ של סוגים סטטיים, קל מאוד לעשות את זה:
type_foo
ממופה לtype_foo_v1
.
בשביל שינוי של תווית אובייקט, כמו sysfs
← sysfs_A
או
mediaserver
← audioserver
, יצירת המיפוי הזה
לא טריוויאלי (ומתואר בדוגמאות למעלה). מנהלים של מדיניות הפלטפורמה
צריך לקבוע איך ליצור את המיפוי של אובייקטים בנקודות מעבר,
נדרשת הבנה של הקשר בין אובייקטים לבין ההקצאות שלהם
תוויות שונות וקבוע מתי זה מתרחש. כדי לשמור על תאימות לאחור,
צריך לנהל את המורכבות בצד הפלטפורמה, שהיא המחיצה היחידה
שעשויים להשתנות.
שדרוג גרסאות
כדי לפשט את הפשטות, פלטפורמת Android מפרסמת גרסת מדיניות כשגרסה חדשה
הסתעפות השחרור נחתך. כפי שתואר קודם, מספר הגרסה כלול
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
ל-Nougat, 25.0
ל-Nougat-MR1,
26.0
ל-Oreo, 27.0
ל-Oreo-MR1, וגם
28.0
ל-Android 9.
ערכי עלייה הם לא תמיד מספרים שלמים. עבור
לדוגמה, אם מעבר MR על גרסה מחייב שינוי לא תואם
system/sepolicy/public
אבל לא עומס ב-API, אז המדיניות הזו
הגרסה יכולה להיות: vN.1
. הגרסה שמופיעה בפיתוח
ההסתעפות היא 10000.0
של מכשירים שאי אפשר להשתמש בהם במשלוח.
יכול להיות שהגרסה הישנה ביותר תצא משימוש ב-Android במהלך ההעברה. לקבלת קלט לגבי מתי להוציא משימוש גרסה, מערכת Android עשויה לאסוף את מספר המכשירים דרך הספק כללי מדיניות שמפעילים את גרסת Android הזו ועדיין מקבלים את הפלטפורמה הראשית אם המספר נמוך מסף מסוים, הגרסה הזו הוצא משימוש.
השפעה על הביצועים של מספר מאפיינים
כפי שמתואר ב-https://github.com/SELinuxProject/cil/issues/9, מספר גדול של מאפיינים שמוקצים לסוג מסוים מובילים לבעיות בביצועים אירוע של השמטת מטמון של מדיניות.
זיהינו שזו בעיה ב-Android, אז שינויים נוצרו ל-Android 8.0 כדי להסיר מאפיינים שנוספו למדיניות על ידי שלנו, וכן להסיר מאפיינים שאינם בשימוש. השינויים האלה נפתרו רגרסיות של הביצועים.
המדיניות הציבורית והציבורית של המוצר System_ext
החל מ-Android 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
.
אם רק מחיצות המוצרים ומחיצות המערכת יעודכנו, נניח
N
אל N+1
(או מאוחר יותר), בזמן
הספק נשאר ב-N
, הספק עלול לאבד את הגישה אל
שונים של system_ext ומחיצות המוצרים. כדי למנוע שבירה,
system_ext ומחיצות מוצרים צריכים לספק קובצי מיפוי מבטון
במאפייני type_N
. כל שותף
אחראי לתחזוקה של קובצי המיפוי, אם הם מתכננים לתמוך
ספק של N
עם N+1
(ואילך)
system_ext ומחיצות מוצרים.
לשם כך, אנחנו מצפים מהשותפים:
- העתקת קובצי מיפוי הבסיס שנוצרו מ-
N
system_ext ומחיצות מוצרים לעץ המקור שלו. - משנים את קובצי המיפוי לפי הצורך.
-
להתקין את
ממפים קבצים אל
N+1
(או גרסה מאוחרת יותר) system_ext וגם מחיצות מוצרים.
לדוגמה, נניח שלמערכת N
system_ext יש מזהה ציבורי אחד
סוג בשם foo_type
. ואז system_ext/etc/selinux/mapping/N.cil
במחיצת system_ext של N
תיראה כך:
(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
יכול להמשיך לגשת אל N+1
foo_type
ו-bar_type
של system_ext.
הוספת תוויות להקשרים של SELinux
כדי לתמוך בהבחנה בין המדיניות בנושא פלטפורמה לבין ספק, המערכת יוצרת קובצי הקשר של SELinux בצורה שונה כדי לשמור אותם בנפרד.
ההקשרים של הקבצים
ב-Android 8.0 בוצעו השינויים הבאים ב-file_contexts
:
- כדי למנוע תקורת הידור נוספת במכשיר במהלך ההפעלה,
file_contexts
יפסיקו להופיע בפורמט הבינארי. במקום זאת, הם קובץ טקסט קריא של ביטויים רגולריים, כמו{property, service}_contexts
(כפי שהיו לפני גרסה 7.0). - הקבצים מסוג
file_contexts
מחולקים בין שני קבצים:plat_file_contexts
- בפלטפורמת Android
file_context
שאין לה תוויות ספציפיות למכשיר, למעט הוספת תוויות לחלקים של מחיצה/vendor
שצריך לתייג במדויק כדי לוודא שקובצי המדיניות פועלים בצורה תקינה. - חייב להימצא במחיצה של
system
בכתובת/system/etc/selinux/plat_file_contexts
במכשיר ו ייטענו על ידיinit
בהתחלה, יחד עם הספקfile_context
.
- בפלטפורמת Android
vendor_file_contexts
file_context
ספציפי למכשיר, שפותח על ידי שילוב האפליקציהfile_contexts
נמצאה בספריות שאליהן הפנוBOARD_SEPOLICY_DIRS
במכשירBoardconfig.mk
קבצים.- חייבת להיות מותקנת ב-
/vendor/etc/selinux/vendor_file_contexts
אינץ' המחיצהvendor
תיטען על ידיinit
בשעה ההתחלה ופלטפורמתfile_context
.
ההקשרים של הנכס
ב-Android 8.0, ה-property_contexts
מחולק בין שני קבצים:
plat_property_contexts
- בפלטפורמת Android
property_context
שאין לה תוויות ספציפיות למכשיר. - חייב להימצא במחיצה של
system
בכתובת/system/etc/selinux/plat_property_contexts
והמכשיר ייטען עדinit
בהתחלה, יחד עם הספקproperty_contexts
- בפלטפורמת Android
vendor_property_contexts
property_context
ספציפי למכשיר, שפותח על ידי שילוב האפליקציהproperty_contexts
נמצאה בספריות שאליהן הפנוBOARD_SEPOLICY_DIRS
במכשירBoardconfig.mk
קבצים.- חייב להימצא במחיצה של
vendor
בכתובת/vendor/etc/selinux/vendor_property_contexts
ולהיות נטען על ידיinit
בהתחלה יחד עם הפלטפורמהproperty_context
ההקשרים של השירות
ב-Android 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
- פלטפורמת Android
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
בהתחלה.
הקשרים ימיים
ב-Android 8.0, ה-seapp_contexts
מחולק בין שני קבצים:
plat_seapp_contexts
- בפלטפורמת Android
seapp_context
ללא סוג ספציפי של מכשיר שינויים. - חייב להימצא במחיצה של
system
בכתובת/system/etc/selinux/plat_seapp_contexts.
- בפלטפורמת Android
vendor_seapp_contexts
- תוסף ספציפי למכשיר לפלטפורמה
seapp_context
שנוצר על ידי שילוב שלseapp_contexts
שנמצא בספריות מצביעים על ידיBOARD_SEPOLICY_DIRS
Boardconfig.mk
קבצים. - חייב להימצא במחיצה של
vendor
בכתובת/vendor/etc/selinux/vendor_seapp_contexts
.
- תוסף ספציפי למכשיר לפלטפורמה
הרשאות MAC
ב-Android 8.0, ה-mac_permissions.xml
מחולק בין שני קבצים:
- פלטפורמה
mac_permissions.xml
- בפלטפורמת Android
mac_permissions.xml
שאין לה ספציפיים למכשיר. - חייב להימצא במחיצה של
system
בכתובת/system/etc/selinux/.
- בפלטפורמת Android
- לא פלטפורמה
mac_permissions.xml
- תוסף לפלטפורמה ספציפי למכשיר
mac_permissions.xml
נוצרו מ- נמצאmac_permissions.xml
בספריות שאליהן מפנותBOARD_SEPOLICY_DIRS
של המכשיר קובציBoardconfig.mk
. - חייב להימצא במחיצה של
vendor
בכתובת/vendor/etc/selinux/.
- תוסף לפלטפורמה ספציפי למכשיר