خطای خط اصلی اندروید GKI 16-6.12

این صفحه مشکلات مهم و رفع اشکالات موجود در 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 برای تعیین محدوده‌های آرایه در زمان اجرا و تشخیص موارد بیشتر دسترسی خارج از محدوده استفاده می‌کند. با این حال، در برخی موارد، آرایه قبل از تنظیم متغیر size مورد دسترسی قرار می‌گیرد و باعث فعال شدن ابزار سنجش محدوده‌ها و ایجاد اختلال در هسته می‌شود. برای رفع این مشکل، اندازه آرایه را بلافاصله پس از تخصیص حافظه زیرین، همانطور که در aosp/3343204 نشان داده شده است، تنظیم کنید.
    • درباره CONFIG_UBSAN_SIGNED_WRAP : نسخه جدید Clang با وجود پرچم کامپایلر -fwrapv سرریز و سرریز زیرین عدد صحیح امضا شده را پاکسازی می‌کند. پرچم -fwrapv به گونه‌ای طراحی شده است که با اعداد صحیح امضا شده به عنوان اعداد صحیح بدون علامت مکمل دو با رفتار سرریز تعریف شده رفتار کند.

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

۱ نوامبر ۲۰۲۴

  • فرود لینوکس ۶.۱۲-rc۴
    • خلاصه: 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 به اشتباه پیاده‌سازی می‌کنند، آشکار می‌کند. این باعث انواع مختلفی از خطاها مانند خرابی حافظه، استفاده پس از آزادسازی و نشت حافظه می‌شود.
    • تمام کاربردهای APIهای مرتبط با تجزیه 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 و فراموش کردن unref کردن آن ( 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 از تکرار حلقه. اگر از داخل کد زیر return یا break می‌کنید، باید در مقطعی ارجاع باقی‌مانده را حذف کنید:
        • for_each_available_child_of_node()
        • for_each_child_of_node()
        • for_each_node_by_type()
        • for_each_compatible_node()
        • of_for_each_phandle()
    • تغییر ذکر شده قبلی هنگام نصب لینوکس 6.12-rc4 (به aosp/۳۳۱۵۲۵۱ مراجعه کنید) بازیابی شد و دوباره CONFIG_OF_DYNAMIC را فعال کرد و به طور بالقوه درایورهای معیوب را در معرض نمایش قرار داد.