GKI 16-6.12 android-mainline errata

این صفحه مشکلات مهم و رفع اشکالات یافت‌شده در android-mainline را که ممکن است برای شرکا مهم باشد شرح می‌دهد.

۱۵ نوامبر ۲۰۲۴

  • Clang برای 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 برای رفتار با اعداد صحیح علامت‌دار به‌عنوان مکمل دو اعداد صحیح بدون علامت با رفتار سرریز تعریف‌شده طراحی شده است.

      • اگرچه پاک‌سازی سرریز عدد صحیح علامت‌دار در هسته Linux می‌تواند به شناسایی اشکالات کمک کند، مواردی وجود دارد که سرریز عمدی است، برای مثال، با atomic_long_t. درنتیجه، CONFIG_UBSAN_SIGNED_WRAP غیرفعال شده است تا UBSAN بتواند صرفاً به‌عنوان پاک‌کننده مرزها عمل کند.
    • درباره CONFIG_UBSAN_TRAP: UBSAN به‌گونه‌ای پیکربندی شده است که وقتی مشکلی را برای محافظت از یکپارچگی هسته شناسایی می‌کند، کرنل پنیک را راه‌اندازی کند. بااین‌حال، این رفتار را از ۲۳ اکتبر تا ۱۲ نوامبر غیرفعال کردیم. این کار را برای رفع انسداد به‌روزرسانی کامپایلر انجام دادیم و درعین‌حال مشکلات شناخته‌شده __counted_by را برطرف کردیم.

۱ نوامبر ۲۰۲۴

  • Linux 6.12-rc4 landing
    • خلاصه: 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 به‌اشتباه پیاده‌سازی می‌کنند دوباره آشکار می‌کند. این امر باعث بروز انواع مختلفی از خطاها مانند خرابی حافظه، استفاده پس‌از آزاد کردن، و نشت حافظه می‌شود.
    • همه موارد استفاده از میاناهای برنامه‌سازی کاربردی مرتبط با تجزیه OF باید بازرسی شود. فهرست زیر جزئی است، اما شامل مواردی است که تحت نظر داشته‌ایم:
      • استفاده پس‌از رایگان (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 را دوباره فعال کرد و احتمالاً درایورهای معیوب را آشکار کرد.