תקינות התהליך של בקרת הליבה

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

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

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

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

הטמעה

התיקונים של kCFI נמצאים בכל הגרסאות הנתמכות של ליבה של Android. האפשרות CONFIG_CFI_CLANG מפעילה את kCFI והיא מוגדרת כברירת מחדל ב-GKI.

פתרון בעיות

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

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

אימות

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