GKI 16-6.12 android-mainline errata

इस पेज पर, android-mainline में मिली अहम समस्याओं और बग को ठीक करने के बारे में बताया गया है. ये समस्याएं, पार्टनर के लिए अहम हो सकती हैं.

15 नवंबर, 2024

  • 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 फ़्लैग को, साइन किए गए इंटिजर को दो के पूरक अनसाइन किए गए इंटिजर के तौर पर ट्रीट करने के लिए डिज़ाइन किया गया है. इसमें ओवरफ़्लो के लिए तय किया गया व्यवहार शामिल है.

      • Linux कर्नल में साइन किए गए इंटिजर ओवरफ़्लो को सैनिटाइज़ करने से, बग की पहचान करने में मदद मिल सकती है. हालांकि, ऐसे उदाहरण भी हैं जहां ओवरफ़्लो जान-बूझकर किया जाता है. जैसे, atomic_long_t के साथ. इसलिए, CONFIG_UBSAN_SIGNED_WRAP को बंद कर दिया गया है ताकि UBSAN सिर्फ़ बाउंड सैनिटाइज़र के तौर पर काम कर सके.
    • CONFIG_UBSAN_TRAP के बारे में जानकारी: UBSAN को इस तरह कॉन्फ़िगर किया गया है कि कर्नल की इंटिग्रिटी को सुरक्षित रखने के लिए, कोई समस्या मिलने पर कर्नल पैनिक ट्रिगर हो. हालांकि, हमने 23 अक्टूबर से 12 नवंबरतक इस सुविधा को बंद कर दिया था. हमने ऐसा इसलिए किया, ताकि कंपाइलर अपडेट को अनब्लॉक किया जा सके. साथ ही, हमने __counted_by से जुड़ी जानी-मानी समस्याओं को ठीक किया.

1 नवंबर, 2024

  • Linux 6.12-rc4 लॉन्च किया गया
    • खास जानकारी: 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 के लिए रेफ़रंस-काउंटिंग को गलत तरीके से लागू करने वाले ड्राइवर में समस्याएं दिखती हैं. इससे कई तरह की गड़बड़ियां होती हैं. जैसे, मेमोरी करप्ट होना, यूज़-आफ़्टर-फ़्री, और मेमोरी लीक.
    • 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()
        • 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 पाना और उसे अनरेफ़ करना (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 फिर से चालू हो गया और खराब ड्राइवर की समस्याएं सामने आ सकती हैं.