สกูโด้

Scudo เป็นแบบไดนามิกโหมดผู้จัดสรรหน่วยความจำหรือจัดสรรกองออกแบบมาให้มีความยืดหยุ่นกับช่องโหว่กองที่เกี่ยวข้อง (เช่น กองตามหน่วยความจำล้น , การใช้งานหลังจากฟรี และ คู่ฟรี ) ขณะที่ยังคงประสิทธิภาพการทำงาน มันมีมาตรฐานการจัดสรรซีและ deallocation พื้นฐาน (เช่น malloc และฟรี) เช่นเดียวกับ c ++ พื้นฐาน (เช่นใหม่และลบ)

Scudo มีมากขึ้นของการบรรเทาผลกระทบกว่าเครื่องตรวจจับข้อผิดพลาดของหน่วยความจำเต็มเปี่ยมเหมือน AddressSanitizer (Asan)

เริ่มต้นใน Android 11 เวอร์ชัน scudo ใช้สำหรับโค้ดเนทีฟทั้งหมด (ยกเว้นในอุปกรณ์ที่มีหน่วยความจำเหลือน้อย ซึ่งยังคงใช้ jemalloc อยู่) ในขณะรันไทม์ การจัดสรรฮีปดั้งเดิมและการจัดสรรคืนจะได้รับบริการโดย Scudo สำหรับไฟล์เรียกทำงานทั้งหมดและการพึ่งพาไลบรารี และกระบวนการจะถูกยกเลิกหากตรวจพบความเสียหายหรือพฤติกรรมที่น่าสงสัยในฮีป

ใน Android 10 Scudo จะต้องมีการเปิดใช้งานบนพื้นฐานต่อไบนารีโดยการตั้งค่า LOCAL_SANITIZE := scudo ตัวเลือกในแฟ้ม .mk หรือ sanitize: { scudo: true, } ในแฟ้ม .bp

Scudo เป็น โอเพนซอร์ส และเป็นส่วนหนึ่งของโครงการคอมไพเลอร์-RT LLVM ของ เอกสารที่มีอยู่ใน https://llvm.org/docs/ScudoHardenedAllocator.html เรือรันไทม์ Scudo เป็นส่วนหนึ่งของ toolchain Android และสนับสนุนถูกบันทึกอยู่ใน Soong และสร้าง เพื่อให้ง่ายต่อการเปิดใช้งานของจัดสรรในไบนารี

คุณสามารถเปิดหรือปิดใช้งานการลดพิเศษภายในตัวจัดสรรได้โดยใช้ตัวเลือกที่อธิบายไว้ด้านล่าง

การปรับแต่ง

พารามิเตอร์บางตัวของตัวจัดสรรสามารถกำหนดตามพื้นฐานต่อกระบวนการได้หลายวิธี:

  • แบบคงที่: กำหนด __scudo_default_options ฟังก์ชั่นในโปรแกรมที่สตริงผลตอบแทนที่ตัวเลือกที่จะแยกวิเคราะห์ ฟังก์ชั่นนี้ต้องมีต้นแบบต่อไปนี้: extern "C" const char *__scudo_default_options()
  • แบบไดนามิก: ใช้ตัวแปรสภาพแวดล้อม SCUDO_OPTIONS มีสตริงตัวเลือกที่จะแยกวิเคราะห์ ตัวเลือกการกำหนดวิธีนี้แทนที่ความหมายใด ๆ ที่ทำผ่าน __scudo_default_options

มีตัวเลือกดังต่อไปนี้

ตัวเลือก ค่าเริ่มต้น 64 บิต ค่าเริ่มต้น 32 บิต คำอธิบาย
QuarantineSizeKb 256 64 ขนาด (ในหน่วย KB) ของการกักกันที่ใช้เพื่อชะลอการจัดสรรคืนที่แท้จริงของกลุ่ม ค่าที่ต่ำกว่าอาจลดการใช้หน่วยความจำ แต่ลดประสิทธิภาพของการบรรเทาลง ค่าลบจะกลับไปเป็นค่าเริ่มต้น การตั้งค่าทั้งสองนี้และ ThreadLocalQuarantineSizeKb ไปที่ศูนย์กักกันคนพิการทั้งหมด
QuarantineChunksUpToSize 2048 512 ขนาด (เป็นไบต์) สูงสุดที่สามารถกักเก็บชิ้นส่วนได้
ThreadLocalQuarantineSizeKb 64 16 ขนาด (เป็น KB) ของการใช้แคชต่อเธรดเพื่อออฟโหลดการกักกันส่วนกลาง ค่าที่ต่ำกว่าอาจลดการใช้หน่วยความจำแต่อาจเพิ่มการโต้แย้งในการกักกันส่วนกลาง การตั้งค่าทั้งสองนี้และ QuarantineSizeKb ไปที่ศูนย์กักกันคนพิการทั้งหมด
DeallocationTypeMismatch false false เปิดใช้งานการรายงานข้อผิดพลาดใน malloc/delete, new/free, new/delete[]
DeleteSizeMismatch true true เปิดใช้งานการรายงานข้อผิดพลาดเกี่ยวกับขนาดที่ไม่ตรงกันระหว่างขนาดใหม่และการลบ
ZeroContents false false เปิดใช้งานเนื้อหาที่เป็นศูนย์ในการจัดสรรและการจัดสรรคืน
allocator_may_return_null false false ระบุว่าตัวจัดสรรสามารถคืนค่า null เมื่อเกิดข้อผิดพลาดที่กู้คืนได้ แทนที่จะยุติกระบวนการ
hard_rss_limit_mb 0 0 เมื่อ RSS ของกระบวนการถึงขีดจำกัดนี้ กระบวนการจะสิ้นสุดลง
soft_rss_limit_mb 0 0 เมื่อ RSS ของกระบวนการถึงขีด จำกัด นี้การจัดสรรเพิ่มเติมล้มเหลวหรือการกลับมา null (ขึ้นอยู่กับมูลค่าของ allocator_may_return_null ) จนกว่า RSS ไปกลับลงมาเพื่อให้การจัดสรรใหม่
allocator_release_to_os_interval_ms ไม่มี 5000 มีผลกับตัวจัดสรร 64 บิตเท่านั้น หากตั้งค่าไว้ จะพยายามปล่อยหน่วยความจำที่ไม่ได้ใช้ไปยังระบบปฏิบัติการ แต่ไม่บ่อยกว่าช่วงเวลานี้ (หน่วยเป็นมิลลิวินาที) หากค่าเป็นลบ หน่วยความจำจะไม่ถูกปล่อยไปยังระบบปฏิบัติการ
abort_on_error true true หากตั้งสายเครื่องมือ abort() แทน _exit() หลังจากพิมพ์ข้อความข้อผิดพลาด

การตรวจสอบความถูกต้อง

ปัจจุบันไม่มีการทดสอบ CTS สำหรับ Scudo โดยเฉพาะ ตรวจสอบให้แน่ใจว่าการทดสอบ CTS ผ่านโดยมีหรือไม่มี Scudo ที่เปิดใช้งานสำหรับไบนารีที่กำหนดเพื่อตรวจสอบว่าไม่ส่งผลกระทบต่ออุปกรณ์

การแก้ไขปัญหา

หากตรวจพบปัญหาที่ไม่สามารถกู้คืนได้ ตัวจัดสรรจะแสดงข้อความแสดงข้อผิดพลาดไปยังตัวบอกข้อผิดพลาดมาตรฐาน จากนั้นจึงยุติกระบวนการ การติดตามสแต็กที่นำไปสู่การยุติจะถูกเพิ่มในบันทึกของระบบ เอาท์พุทมักจะเริ่มต้นด้วยการ Scudo ERROR: ตามด้วยสรุปสั้น ๆ ของปัญหาพร้อมกับคำแนะนำใด ๆ

นี่คือรายการข้อความแสดงข้อผิดพลาดปัจจุบันและสาเหตุที่เป็นไปได้:

  • corrupted chunk header : การตรวจสอบการตรวจสอบของส่วนหัวอันล้มเหลว อาจเป็นเพราะหนึ่งในสองสิ่ง: ส่วนหัวถูกเขียนทับ (บางส่วนหรือทั้งหมด) หรือตัวชี้ที่ส่งไปยังฟังก์ชันไม่ใช่ส่วนย่อย
  • race on chunk header : สองหัวข้อที่แตกต่างกำลังพยายามที่จะจัดการกับส่วนหัวเดียวกันในเวลาเดียวกัน ซึ่งมักจะเป็นอาการของสภาวะการแข่งขันหรือขาดการล็อคโดยทั่วไปเมื่อดำเนินการกับกลุ่มนั้น
  • invalid chunk state : อันไม่ได้อยู่ในสถานะที่คาดว่าจะได้รับการดำเนินการเช่นนี้ก็ไม่ได้จัดสรรเมื่อพยายามที่จะเป็นอิสระมันหรือมันไม่ได้กักกันเมื่อพยายามที่จะรีไซเคิล การดับเบิ้ลฟรีเป็นสาเหตุทั่วไปของข้อผิดพลาดนี้
  • misaligned pointer : ข้อกำหนดการจัดตำแหน่งพื้นฐานมีการบังคับใช้อย่างยิ่ง: 8 ไบต์บนแพลตฟอร์ม 32 บิตและ 16 ไบต์บนแพลตฟอร์ม 64 บิต หากตัวชี้ที่ส่งไปยังฟังก์ชันของเราไม่ตรงกับตัวชี้ แสดงว่าตัวชี้ที่ส่งไปยังฟังก์ชันใดฟังก์ชันหนึ่งไม่อยู่ในแนวเดียวกัน
  • allocation type mismatch : เมื่อตัวเลือกนี้จะเปิดใช้งานฟังก์ชั่นที่เรียกว่า deallocation บนก้อนมีให้ตรงกับชนิดของฟังก์ชั่นที่ถูกเรียกตัวไปจัดสรร ความไม่ตรงกันประเภทนี้อาจทำให้เกิดปัญหาด้านความปลอดภัยได้
  • invalid sized delete : เมื่อ C ++ 14 ผู้ประกอบการขนาดลบถูกนำมาใช้และการตรวจสอบตัวเลือกถูกเปิดใช้งานมีความไม่ตรงกันระหว่างขนาดที่ถูกส่งผ่านไปเมื่อ deallocating ก้อนและขนาดที่ได้รับการร้องขอเมื่อจัดสรรมัน นี้มักจะเป็นปัญหาคอมไพเลอร์หรือ ความสับสนชนิด บนวัตถุที่ถูก deallocated
  • RSS limit exhausted : ผู้ RSS สูงสุดที่ระบุเลือกที่ได้รับเกิน

หากคุณกำลังแก้จุดบกพร่องผิดพลาดในระบบปฏิบัติการของตัวเองคุณสามารถใช้ HWASan OS สร้าง หากคุณกำลังแก้จุดบกพร่องผิดพลาดในแอปก็เป็นไปได้ที่จะใช้ HWASan แอปสร้าง เกินไป