जीकेआई 16-6.12 Android-मेनलाइन की गड़बड़ी

इस पेज पर, 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 kernel में साइन वाले पूर्णांक के ओवरफ़्लो को साफ़ करने से, गड़बड़ियों की पहचान करने में मदद मिल सकती है. हालांकि, कुछ मामलों में ओवरफ़्लो जान-बूझकर किया जाता है. उदाहरण के लिए, atomic_long_t के साथ. इसलिए, UBSAN को सिर्फ़ बाउंड सैनिटाइज़र के तौर पर काम करने की अनुमति देने के लिए, CONFIG_UBSAN_SIGNED_WRAP को बंद कर दिया गया है.
    • 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 पार्सिंग से जुड़े सभी एपीआई के इस्तेमाल की जांच की जानी चाहिए. यहां दी गई सूची में कुछ ही उदाहरण दिए गए हैं. हालांकि, इनमें वे मामले शामिल हैं जिन पर हम नज़र बनाए हुए हैं:
      • मुफ़्त में आज़माने के बाद इस्तेमाल करें (यूएफ़):
        • एक ही 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()
      • लूप के किसी Iteration से 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 फिर से चालू हो गया और गड़बड़ी वाले ड्राइवर दिखने लगे.