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