תיקון שגיאה של GKI 16-6.12 android-mainline

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

‫15 בנובמבר 2024

  • Clang עודכן לגרסה 19.0.1 עבור android-mainline ו-android16-6.12

    • סיכום: בגרסה החדשה של Clang מוצגת תכונה לניקוי גבולות למערכים, שבה הגודל של המערך מאוחסן במשתנה נפרד שמקושר למערך באמצעות המאפיין __counted_by. התכונה הזו עלולה לגרום לתגובה לשגיאת ליבה קריטית אם גודל המערך לא יעודכן כראוי. הודעת השגיאה נראית כך:
    UBSAN: array-index-out-of-bounds in common/net/wireless/nl80211.c
    index 0 is out of range for type 'struct ieee80211_channel *[] __counted_by(n_channels)' (aka 'struct ieee80211_channel *[]')
    
    • פרטים: אמצעי הניקוי של הגבולות חיוני להגנה על שלמות ליבת המערכת על ידי זיהוי גישה מחוץ לגבולות. אם האפשרות CONFIG_UBSAN_TRAP מופעלת, מנגנון ניקוי הגבולות מפעיל תגובה לשגיאת ליבה קריטית בכל ממצא.

      • בגרסה הקודמת של הכלי לניקוי גבולות נבדקו רק מערכים בגודל קבוע ולא הייתה אפשרות לבדוק מערכים שהוקצו באופן דינמי. בגרסה החדשה נעשה שימוש במאפיין __counted_by כדי לקבוע את גבולות המערך בזמן הריצה ולזהות יותר מקרים של גישה מחוץ לגבולות. עם זאת, במקרים מסוימים, מתבצעת גישה למערך לפני שמשתנה הגודל מוגדר, מה שמפעיל את אמצעי הניקוי של הגבולות וגורם לתגובה לשגיאת ליבה קריטית. כדי לפתור את הבעיה הזו, צריך להגדיר את גודל המערך מיד אחרי הקצאת הזיכרון הבסיסי, כמו שמוסבר במאמר aosp/3343204.
    • מידע על CONFIG_UBSAN_SIGNED_WRAP: הגרסה החדשה של Clang מבצעת סניטציה של הצפת מספרים שלמים עם סימן ושל חוסר מספרים שלמים עם סימן, למרות דגל הקומפיילר -fwrapv. הדגל -fwrapv נועד לטפל במספרים שלמים עם סימן כמספרים שלמים ללא סימן בשיטת "המשלים ל-2" עם התנהגות מוגדרת של הצפת נתונים.

      • ניקוי של הצפת מספרים שלמים עם סימן בקרנל של Linux יכול לעזור לזהות באגים, אבל יש מקרים שבהם ההצפה היא מכוונת, למשל ב-atomic_long_t. לכן, CONFIG_UBSAN_SIGNED_WRAP הושבת כדי לאפשר ל-UBSAN לפעול רק ככלי לניקוי גבולות.
    • מידע על CONFIG_UBSAN_TRAP: המערכת מוגדרת להפעיל תגובה לשגיאת ליבה קריטית (kernel panic) כשמתגלה בעיה, כדי להגן על שלמות הליבה. עם זאת, השבתנו את ההתנהגות הזו מ-23 באוקטובר עד 12 בנובמבר. עשינו את זה כדי לבטל את החסימה של עדכון הקומפיילר בזמן שתיקנו בעיות ידועות.__counted_by

‫1 בנובמבר 2024

  • Linux 6.12-rc4 landing
    • סיכום: CONFIG_OF_DYNAMIC עלול לגרום לרגרסיות חמורות בדרייברים פגומים.
    • הפרטים: במהלך מיזוג של Linux 6.12-rc1 לתוך android-mainline, שמנו לב לבעיות בטעינה של מנהלי התקנים שלא נמצאים בעץ. השינוי שחשף את הבאגים בדרייבר זוהה כקומט 274aff8711b2 ("clk: Add KUnit tests for clks registered with struct clk_parent_data"), וביטלנו אותו באופן זמני ב-aosp/3287735. השינוי בוחר ב-CONFIG_OF_OVERLAY, שבוחר ב-CONFIG_OF_DYNAMIC. ב-!OF_DYNAMIC, ספירת ההפניות ב-of_node_get() וב-of_node_put() מושבתת למעשה כי היא מיושמת כ-noops. הפעלה חוזרת של OF_DYNAMIC חושפת בעיות במנהלי התקנים שמיישמים בצורה שגויה ספירת הפניות ל-struct device_node. הדבר גורם לסוגים שונים של שגיאות כמו פגיעה בזיכרון, שימוש בזיכרון אחרי שחרורו ודליפות זיכרון.
    • צריך לבדוק את כל השימושים בממשקי API שקשורים לניתוח OF. הרשימה הבאה היא חלקית, אבל היא כוללת מקרים שזיהינו:
      • שימוש אחרי שחרור (UAF):
        • שימוש חוזר באותו ארגומנט device_node: הפונקציות האלה קוראות ל-of_node_put() בצומת שצוין, ויכול להיות שצריך להוסיף of_node_get() לפני שקוראים להן (לדוגמה, כשקוראים ל-of_node_get() שוב ושוב עם אותו צומת כארגומנט):
          • of_find_compatible_node()
          • of_find_node_by_name()
          • of_find_node_by_path()
          • of_find_node_by_type()
          • of_get_next_cpu_node()
          • of_get_next_parent()
          • of_get_next_child()
          • of_get_next_available_child()
          • of_get_next_reserved_child()
          • of_find_node_with_property()
          • of_find_matching_node_and_match()
        • שימוש ב-device_node אחרי כל סוג של יציאה מלולאות מסוימות:
          • for_each_available_child_of_node_scoped()
          • for_each_available_child_of_node()
          • for_each_child_of_node_scoped()
          • for_each_child_of_node()
        • שמירה של מצביעים ישירים לנכסי char * מ-device_node, למשל, באמצעות:
          • const char *foo = struct device_node::name
          • of_property_read_string()
          • of_property_read_string_array()
          • of_property_read_string_index()
          • of_get_property()
      • דליפות זיכרון:
        • קבלת device_node ושכחת לבטל את ההפניה (of_node_put()). צריך לשחרר בשלב מסוים את הצמתים שמוחזרים מהפעולות האלה:
          • of_find_compatible_node()
          • of_find_node_by_name()
          • of_find_node_by_path()
          • of_find_node_by_type()
          • of_find_node_by_phandle()
          • of_parse_phandle()
          • of_find_node_opts_by_path()
          • of_get_next_cpu_node()
          • of_get_compatible_child()
          • of_get_child_by_name()
          • of_get_parent()
          • of_get_next_parent()
          • of_get_next_child()
          • of_get_next_available_child()
          • of_get_next_reserved_child()
          • of_find_node_with_property()
          • of_find_matching_node_and_match()
      • שמירת device_node מאיטרציה של לולאה. אם אתם חוזרים או יוצאים מאחת מהפעולות הבאות, אתם צריכים להפסיק את ההפניה שנותרה בשלב מסוים:
        • for_each_available_child_of_node()
        • for_each_child_of_node()
        • for_each_node_by_type()
        • for_each_compatible_node()
        • of_for_each_phandle()
    • השינוי שצוין קודם שוחזר בזמן ההפעלה של Linux 6.12-rc4 (ראו aosp/3315251) ההפעלה של CONFIG_OF_DYNAMIC שוב עלולה לחשוף מנהלי התקנים פגומים.