כתיבת מדיניות SELinux

פרויקט הקוד הפתוח של Android (AOSP) מספק מדיניות בסיס מוצקה עבור היישומים והשירותים הנפוצים בכל מכשירי האנדרואיד. התורמים ל-AOSP משכללים מדיניות זו באופן קבוע. מדיניות הליבה צפויה להוות כ-90-95% מהמדיניות הסופית במכשיר, כאשר התאמות אישיות ספציפיות למכשיר יהוו את ה-5-10% הנותרים. מאמר זה מתמקד בהתאמות אישיות ספציפיות למכשיר, כיצד לכתוב מדיניות ספציפית למכשיר, וכמה מהמלכודות שיש להימנע מהן בדרך.

העלאת מכשיר

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

הפעל במצב מתירני

כאשר מכשיר נמצא במצב מתירני , הכחשות נרשמות אך לא נאכפות. מצב מתירני חשוב משתי סיבות:

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

הדרך הפשוטה ביותר להעביר מכשיר למצב מתירני היא שימוש בשורת הפקודה של הליבה . ניתן להוסיף זאת לקובץ BoardConfig.mk של המכשיר: platform/device/<vendor>/<target>/BoardConfig.mk . לאחר שינוי שורת הפקודה, בצע make clean , ולאחר מכן make bootimage , והבהב את תמונת האתחול החדשה.

לאחר מכן, אשר את המצב המתיר באמצעות:

adb shell getenforce

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

לאכוף מוקדם

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

הסר או מחק מדיניות קיימת

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

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

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

avc: denied { open } for pid=1003 comm=”mediaserver” path="/dev/kgsl-3d0”
dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0
tclass=chr_file permissive=1
avc: denied { read write } for pid=1003 name="kgsl-3d0" dev="tmpfs"
scontext=u:r:mediaserver:s0
tcontext=u:object_r:device:s0 tclass=chr_file permissive=1

מטופל לחלוטין על ידי תיוג נכון של /dev/kgsl-3d0 . בדוגמה זו, tcontext הוא device . זה מייצג הקשר ברירת מחדל שבו כל דבר ב- /dev מקבל את התווית " מכשיר " אלא אם מוקצית תווית ספציפית יותר. עצם קבלת הפלט מ- audit2allow כאן תגרום לכלל שגוי ומתירני מדי.

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

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

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

תווי שירותים חדשים וכתוב דחיות

שירותים שהושקו ב-Init נדרשים לפעול בדומיינים של SELinux משלהם. הדוגמה הבאה מכניסה את השירות "foo" לדומיין SELinux משלו ומעניקה לו הרשאות.

השירות מושק ב- init. device .rc קובץ init. device .rc כ:

service foo /system/bin/foo
    class core
  1. צור דומיין חדש "foo"

    צור את הקובץ device/ manufacturer / device-name /sepolicy/foo.te עם התוכן הבא:

    # foo service
    type foo, domain;
    type foo_exec, exec_type, file_type;
    
    init_daemon_domain(foo)
    

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

  2. תווית /system/bin/foo

    הוסף את הדברים הבאים למכשיר device/ manufacturer / device-name /sepolicy/file_contexts :

    /system/bin/foo   u:object_r:foo_exec:s0
    

    זה מוודא שקובץ ההפעלה מסומן כראוי כך ש-SELinux מפעיל את השירות בדומיין המתאים.

  3. בנה והבזק את תמונות האתחול והמערכת.
  4. שפר את כללי SELinux עבור התחום.

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

עבור חזרה למצב אכיפה

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

טעויות נפוצות

להלן מספר פתרונות עבור טעויות נפוצות שקורות בעת כתיבת מדיניות ספציפית למכשיר.

שימוש יתר בשלילה

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

allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms

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

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

איתור באגים בייצור

תכונות ניפוי באגים לא אמורות להיות נוכחות בבניית ייצור וגם לא מדיניות שלהן.

האלטרנטיבה הפשוטה ביותר היא לאפשר את תכונת ניפוי הבאגים רק כאשר SELinux מושבת ב-eng/userdebug builds, כגון adb root ו- adb shell setenforce 0 .

חלופה בטוחה נוספת היא לצרף הרשאות ניפוי באגים במשפט userdebug_or_eng .

פיצוץ גודל מדיניות

אפיון מדיניות SAndroid בטבע מתאר מגמה מדאיגה בצמיחה של התאמות אישיות של מדיניות מכשירים. מדיניות ספציפית למכשיר צריכה להוות 5-10% מהמדיניות הכוללת הפועלת במכשיר. התאמות אישיות בטווח של 20%+ מכילות כמעט בוודאות דומיינים מועדפים ומדיניות מתה.

פוליסה גדולה שלא לצורך:

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

הדוגמה הבאה מציגה שני מכשירים שבהם המדיניות הספציפית ליצרן כללה 50% ו-40% מהמדיניות במכשיר. שכתוב של המדיניות הניב שיפורי אבטחה משמעותיים ללא אובדן פונקציונליות, כפי שמוצג להלן. (מכשירי AOSP Shamu ו- Flounder כלולים לצורך השוואה.)

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

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

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

הענקת יכולת dac_override

הכחשה dac_override פירושה שהתהליך הפוגע מנסה לגשת לקובץ עם הרשאות משתמש/קבוצה/עולם שגוי של יוניקס. הפתרון המתאים הוא כמעט אף פעם לא להעניק הרשאת dac_override . במקום זאת שנה את הרשאות יוניקס בקובץ או בתהליך . כמה תחומים כגון init , vold ו- installd באמת זקוקים ליכולת לעקוף הרשאות קבצי יוניקס כדי לגשת לקבצים של תהליכים אחרים. עיין בבלוג של דן וולש להסבר מעמיק יותר.