หน้านี้อธิบายปัญหาสำคัญและการแก้ไขข้อบกพร่องที่พบใน android-mainline ซึ่งอาจมีความสำคัญต่อพาร์ทเนอร์
15 พฤศจิกายน 2024
อัปเดต Clang เป็น 19.0.1 สำหรับ
android-mainlineและandroid16-6.12- สรุป: Clang เวอร์ชันใหม่มีการเพิ่ม Bounds Sanitizer สำหรับอาร์เรย์ ซึ่งขนาดของอาร์เรย์จะจัดเก็บไว้ในตัวแปรแยกต่างหากที่ลิงก์กับอาร์เรย์โดยใช้แอตทริบิวต์
__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 *[]')รายละเอียด: Bounds Sanitizer มีความสำคัญอย่างยิ่งในการปกป้องความสมบูรณ์ของเคอร์เนลด้วยการตรวจหาการเข้าถึงนอกขอบเขต และเมื่อเปิดใช้
CONFIG_UBSAN_TRAPแล้ว Bounds Sanitizer จะทริกเกอร์เคอร์เนลแพนิกเมื่อตรวจพบ- Bounds Sanitizer เวอร์ชันก่อนหน้าตรวจสอบเฉพาะอาร์เรย์ที่มีขนาดคงที่และตรวจสอบอาร์เรย์ที่จัดสรรแบบไดนามิกไม่ได้ เวอร์ชันใหม่ใช้แอตทริบิวต์
__counted_byเพื่อกำหนดขอบเขตของอาร์เรย์ในรันไทม์และตรวจหาการเข้าถึงนอกขอบเขตได้มากขึ้น อย่างไรก็ตาม ในบางกรณี ระบบจะเข้าถึงอาร์เรย์ก่อนที่จะตั้งค่าตัวแปรขนาด ซึ่งจะทริกเกอร์ Bounds Sanitizer และทำให้เกิดเคอร์เนลแพนิก หากต้องการแก้ไขปัญหานี้ ให้ตั้งค่าขนาดของ อาร์เรย์ทันทีหลังจากจัดสรรหน่วยความจำพื้นฐาน ดังที่ แสดงใน aosp/3343204
- Bounds Sanitizer เวอร์ชันก่อนหน้าตรวจสอบเฉพาะอาร์เรย์ที่มีขนาดคงที่และตรวจสอบอาร์เรย์ที่จัดสรรแบบไดนามิกไม่ได้ เวอร์ชันใหม่ใช้แอตทริบิวต์
เกี่ยวกับ
CONFIG_UBSAN_SIGNED_WRAP: Clang เวอร์ชันใหม่จะล้างข้อมูลการล้นและการล้นกลับของจำนวนเต็มที่มีเครื่องหมาย แม้ว่าจะมีแฟล็กคอมไพเลอร์-fwrapvก็ตาม แฟล็ก-fwrapvได้รับการออกแบบมาเพื่อจัดการจำนวนเต็มที่มีเครื่องหมายเป็นจำนวนเต็มที่ไม่มีเครื่องหมายแบบ Two's Complement ที่มีลักษณะการทำงานของการล้นที่กำหนดไว้- แม้ว่าการล้างข้อมูลการล้นของจำนวนเต็มที่มีเครื่องหมายในเคอร์เนล Linux จะช่วยระบุข้อบกพร่องได้ แต่ก็มีบางกรณีที่การล้นเป็นไปโดยเจตนา เช่น ใน
atomic_long_tด้วยเหตุนี้ เราจึงปิดใช้CONFIG_UBSAN_SIGNED_WRAPhas been disabled เพื่อให้ UBSAN ทำงานเป็น Bounds Sanitizer เท่านั้น
- แม้ว่าการล้างข้อมูลการล้นของจำนวนเต็มที่มีเครื่องหมายในเคอร์เนล Linux จะช่วยระบุข้อบกพร่องได้ แต่ก็มีบางกรณีที่การล้นเป็นไปโดยเจตนา เช่น ใน
เกี่ยวกับ
CONFIG_UBSAN_TRAP: เราได้กำหนดค่า UBSAN ให้ทริกเกอร์เคอร์เนลแพนิกเมื่อตรวจพบปัญหาเพื่อปกป้องความสมบูรณ์ของเคอร์เนล อย่างไรก็ตาม เราได้ปิดใช้ลักษณะการทำงานนี้ตั้งแต่วันที่ 23 ตุลาคม ถึง 12 พฤศจิกายน เราดำเนินการเช่นนี้เพื่อปลดบล็อกการอัปเดตคอมไพเลอร์ในขณะที่เราแก้ไขปัญหา__counted_byที่ทราบ
- สรุป: Clang เวอร์ชันใหม่มีการเพิ่ม Bounds Sanitizer สำหรับอาร์เรย์ ซึ่งขนาดของอาร์เรย์จะจัดเก็บไว้ในตัวแปรแยกต่างหากที่ลิงก์กับอาร์เรย์โดยใช้แอตทริบิวต์
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อย่างไม่ถูกต้อง ซึ่งทำให้เกิดข้อผิดพลาดประเภทต่างๆ เช่น หน่วยความจำเสียหาย การใช้งานหลังช่วงใช้ฟรี (Use After Free) และหน่วยความจำรั่วไหล - ต้องตรวจสอบการใช้ API ที่เกี่ยวข้องกับการแยกวิเคราะห์ OF ทั้งหมด รายการต่อไปนี้เป็นเพียงบางส่วน แต่มีกรณีที่เราสังเกตเห็น
- การใช้งานหลังช่วงใช้ฟรี (Use After Free) (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::nameof_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()
- การใช้งานหลังช่วงใช้ฟรี (Use After Free) (UAF):
- เราได้กู้คืนการเปลี่ยนแปลงที่กล่าวถึงก่อนหน้านี้ขณะรวม Linux
6.12-rc4(ดู aosp/3315251) ซึ่งจะเปิดใช้CONFIG_OF_DYNAMICอีกครั้งและอาจทำให้เกิดไดรเวอร์ที่มีข้อบกพร่อง
- สรุป: