אתחול הספק

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

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

מנגנון

הספק מפעיל תהליך משנה של התחלת אתחול בשלב מוקדם של תהליך האתחול עם הקשר של SELinux u:r:vendor_init:s0. ההקשר של SELinux הזה פחות הרשאות באופן משמעותי מההקשר ההתחלתי שמוגדר כברירת מחדל, והגישה שלו מוגבלים לקבצים, למאפיינים וכו' שהם ספציפיים לספק או חלק את ה-ABI היציב של ספק המערכת.

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

  • לרוב הפקודות שניגשות למערכת הקבצים יש הערות לרוץ בספק init תת-תהליך ולכן כפופים ל-SEPolicy של הספק.
  • רוב הפקודות שמשפיעות על מצב אתחול פנימי (למשל: התחלה ועצירה) שירותים) מופעלים בתהליך האתחול הרגיל. הפקודות האלה הן מודעים לכך שסקריפט של ספק קורא להם לבצע בעצמם קבצים שאינם SELinux לטיפול בהרשאות.

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

שימוש ב-Vendor Init

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

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

type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0
init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied

אם פקודה נכשלת, יש שתי אפשרויות:

  • אם הפקודה נכשלת עקב הגבלה מכוונת (למשל, ניגשת לקובץ מערכת או למאפיין), הפקודה חייבת להיות להיות מוטמעות מחדש באופן ידידותי לטרבל, דרך ממשקים יציבים בלבד. אף פעם לא לאפשר לכללים להוסיף הרשאות גישה לקובצי מערכת שלא חלק מה-ABI היציב של ספק המערכת.
  • אם התווית SELinux חדשה ועדיין לא קיבלה הרשאות מערכת vendor_init.te או הרשאות מוחרגות דרך הכללים, התווית החדשה עשויה לקבל הרשאות vendor_init.te

במכשירים שהושקו לפני Android 9, ניתן לעקוף את הכללים של מעולם לא על ידי הוספת המאפיין typeattribute data_between_core_and_vendor_violators בקובץ vendor_init.te הספציפי למכשיר.

מיקומי קוד

עיקר הלוגיקה של אתחול ה-IPC של הספק נמצאת ב-system/core/init/subcontext.cpp.

טבלת הפקודות נמצאת במחלקה BuiltinFunctionMap ב-system/core/init/builtins.cpp והוא כולל הערות שמציינות אם הפקודה חייבת לרוץ אתחול תהליך משנה.

ה-SEPolicy עבור הפעלת הספק מפוצלת למגזר הפרטי (system/sepolicy/private/vendor_init.te) וציבורי (system/sepolicy/public/vendor_init.te) ספריות במערכת/במדיניות.