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

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

1 בנובמבר 2024

  • השקה של Linux 6.12-rc4
    • סיכום: CONFIG_OF_DYNAMIC עלול לגרום לנסיגה חמורה בנהגים הפגומים.
    • הפרטים: במהלך המיזוג של Linux 6.12-rc1 ל-android-mainline, שמנו לב לבעיות בחיבור של מנהלי התקנים מחוץ לעץ. השינוי שחשף את הבאגים בנהג זוהה כ-commit 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. כתוצאה מכך מתרחשות שגיאות מסוגים שונים, כמו פגיעה בזיכרון, שימוש לאחר שחרור (use-after-free) ודליפות זיכרון.
    • יש לבדוק את כל השימושים של OF לניתוח של ממשקי API קשורים. הרשימה הבאה היא חלקית, אבל היא כוללת מקרים שזיהינו:
      • שימוש לאחר תקופת הניסיון בחינם (UAF):
        • שימוש חוזר באותו ארגומנט device_node: הפונקציות האלה קוראות ל-of_node_put() בצומת שצוין. יכול להיות שתצטרכו להוסיף 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 וחשיפה פוטנציאלית של מנהלי התקנים פגומים.