הספק Init

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

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

מַנגָנוֹן

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

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

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

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

שימוש בספק Init

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

עם זאת, אם פקודות בסקריפט ספק נתון מפרות את מגבלות הפתיחה של הספק, הפקודות ייכשלו. לפקודות נכשלות יש שורה ביומן הליבה (הנראה עם 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

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

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

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

מיקומי קוד

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

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

ה-SEPolicy עבור init של ספקים מפוצלת בין הספריות הפרטיות ( system/sepolicy/private/vendor_init.te ) והציבוריות ( system/sepolicy/public/vendor_init.te ) ב-system/sepolicy.