GKI 16-6.12 অ্যান্ড্রয়েড-মেইনলাইন ত্রুটি

এই পৃষ্ঠায় android-mainline এ পাওয়া গুরুত্বপূর্ণ সমস্যা এবং সেগুলোর সমাধান সম্পর্কে বর্ণনা করা হয়েছে, যা পার্টনারদের জন্য তাৎপর্যপূর্ণ হতে পারে।

১৫ নভেম্বর, ২০২৪

  • android-mainline এবং android16-6.12 এর জন্য Clang 19.0.1 সংস্করণে আপডেট করা হয়েছে।

    • সারসংক্ষেপ: 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 ফ্ল্যাগটি সাইনড ইন্টিজারগুলোকে একটি নির্দিষ্ট ওভারফ্লো আচরণসহ টু'স কমপ্লিমেন্ট আনসাইনড ইন্টিজার হিসেবে বিবেচনা করার জন্য ডিজাইন করা হয়েছে।

      • লিনাক্স কার্নেলে সাইনড ইন্টিজার ওভারফ্লো স্যানিটাইজ করা বাগ শনাক্ত করতে সাহায্য করলেও, এমন কিছু ক্ষেত্র আছে যেখানে ওভারফ্লো ইচ্ছাকৃত, যেমন atomic_long_t এর ক্ষেত্রে। ফলস্বরূপ, UBSAN-কে শুধুমাত্র একটি বাউন্ডস স্যানিটাইজার হিসেবে কাজ করার সুযোগ দিতে CONFIG_UBSAN_SIGNED_WRAP নিষ্ক্রিয় করা হয়েছে
    • CONFIG_UBSAN_TRAP সম্পর্কে: কার্নেলের অখণ্ডতা রক্ষা করার জন্য, UBSAN কোনো সমস্যা শনাক্ত করলে একটি কার্নেল প্যানিক ট্রিগার করার জন্য কনফিগার করা থাকে। তবে, আমরা ২৩শে অক্টোবর থেকে ১২ই নভেম্বর পর্যন্ত এই আচরণটি নিষ্ক্রিয় করে রেখেছিলাম। পরিচিত __counted_by সমস্যাগুলো সমাধান করার সময় কম্পাইলার আপডেটকে বাধামুক্ত রাখতে আমরা এটি করেছিলাম।

১ নভেম্বর, ২০২৪

  • লিনাক্স ৬.১২-আরসি৪ ল্যান্ডিং
    • সারসংক্ষেপ: CONFIG_OF_DYNAMIC সম্ভবত ত্রুটিপূর্ণ ড্রাইভারগুলির জন্য গুরুতর রিগ্রেশন ঘটাতে পারে।
    • বিস্তারিত: android-mainline এ Linux 6.12-rc1 মার্জ করার সময় আমরা লক্ষ্য করি যে আউট-অফ-ট্রি ড্রাইভারগুলো লোড হতে ব্যর্থ হচ্ছে। যে পরিবর্তনটি ড্রাইভারের এই বাগগুলো প্রকাশ করেছিল, সেটি 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 পার্সিং সম্পর্কিত 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()
        • device_node থেকে char * প্রোপার্টিগুলোর সরাসরি পয়েন্টার রেখে দেওয়ার জন্য, উদাহরণস্বরূপ, ব্যবহার করা যেতে পারে:
          • 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() )। এ থেকে ফেরত আসা নোডগুলোকে কোনো এক সময়ে free করতে হয়:
          • 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()
    • লিনাক্স 6.12-rc4 ল্যান্ড করার সময় পূর্বে উল্লিখিত পরিবর্তনটি পুনরুদ্ধার করা হয়েছিল (দেখুন aosp/3315251 ), যা CONFIG_OF_DYNAMIC পুনরায় সক্রিয় করে এবং সম্ভবত ত্রুটিপূর্ণ ড্রাইভারগুলিকে প্রকাশ করে দেয়।