UndefinedBehaviorSanitizer

UndefinedBehaviorSanitizer (UBSan) จะทำการวัดผลเมื่อคอมไพล์เพื่อตรวจสอบพฤติกรรมที่ไม่รู้จักประเภทต่างๆ แม้ว่า UBSan จะตรวจพบข้อบกพร่องด้านลักษณะการทำงานที่ไม่ระบุได้มากมาย แต่ Android รองรับสิ่งต่อไปนี้

  • การจัดข้อความ
  • bool
  • ขอบเขต
  • enum
  • float-cast-overflow
  • float-divide-by-zero
  • integer-divide-by-zero
  • nonnull-attribute
  • ค่าว่าง
  • คำสั่ง "return"
  • returns-nonnull-attribute
  • shift-base
  • shift-exponent
  • signed-integer-overflow
  • ไม่สามารถเข้าถึง
  • unsigned-integer-overflow
  • vla-bound

แม้ว่า unsigned-integer-overflow จะไม่ถือว่าเป็นลักษณะการทำงานที่ไม่ระบุในเชิงเทคนิค แต่รวมอยู่ในโปรแกรมตรวจสอบและใช้ในโมดูล Android หลายรายการ รวมถึงคอมโพเนนต์ mediaserver เพื่อขจัดช่องโหว่ที่อาจเกิดขึ้นจาก unsigned-integer-overflow

การใช้งาน

ในระบบการสร้างของ Android คุณสามารถเปิดใช้ UBSan ทั่วโลกหรือในเครื่องได้ หากต้องการเปิดใช้ UBSan ทั่วโลก ให้ตั้งค่า SANITIZE_TARGET ใน Android.mk หากต้องการเปิดใช้ UBSan ที่ระดับแต่ละโมดูล ให้ตั้งค่า LOCAL_SANITIZE และระบุลักษณะการทำงานที่ไม่ระบุซึ่งคุณต้องการค้นหาใน Android.mk เช่น

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0

LOCAL_SRC_FILES:= sanitizer-status.c

LOCAL_MODULE:= sanitizer-status

LOCAL_SANITIZE := alignment bounds null unreachable integer
LOCAL_SANITIZE_DIAG := alignment bounds null unreachable integer

include $(BUILD_EXECUTABLE)

และการกำหนดค่าบิลด์เพลน (Android.bp) ที่เทียบเท่า

cc_binary {

    cflags: [
        "-std=c11",
        "-Wall",
        "-Werror",
        "-O0",
    ],

    srcs: ["sanitizer-status.c"],

    name: "sanitizer-status",

    sanitize: {
        misc_undefined: [
            "alignment",
            "bounds",
            "null",
            "unreachable",
            "integer",
        ],
        diag: {
            misc_undefined: [
                "alignment",
                "bounds",
                "null",
                "unreachable",
                "integer",
            ],
        },
    },

}

แป้นพิมพ์ลัด UBSan

นอกจากนี้ Android ยังมีทางลัด 2 รายการ ได้แก่ integer และ default-ub เพื่อเปิดใช้ชุดโปรแกรมทำความสะอาดพร้อมกัน โดยค่าจำนวนเต็มจะเปิดใช้ integer-divide-by-zero, signed-integer-overflow และ unsigned-integer-overflow default-ub เปิดใช้การตรวจสอบที่มีปัญหาด้านประสิทธิภาพของคอมไพเลอร์น้อยที่สุด bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound คลาสตัวกรองจำนวนเต็มใช้ได้กับ SANITIZE_TARGET และ LOCAL_SANITIZE ส่วน default-ub ใช้ได้กับ SANITIZE_TARGET เท่านั้น

การรายงานข้อผิดพลาดที่ดีขึ้น

การใช้งาน UBSan เริ่มต้นของ Android จะเรียกใช้ฟังก์ชันที่ระบุเมื่อพบลักษณะการทำงานที่ไม่รู้จัก โดยค่าเริ่มต้น ฟังก์ชันนี้จะยกเลิก อย่างไรก็ตาม ตั้งแต่เดือนตุลาคม 2016 UBSan ใน Android มีไลบรารีรันไทม์ที่ไม่บังคับซึ่งให้การรายงานข้อผิดพลาดที่ละเอียดยิ่งขึ้น รวมถึงประเภทของลักษณะการทำงานที่ไม่รู้จักที่พบ ข้อมูลไฟล์ และบรรทัดโค้ดต้นทาง หากต้องการเปิดใช้การรายงานข้อผิดพลาดนี้ด้วยการตรวจสอบจำนวนเต็ม ให้เพิ่มข้อมูลต่อไปนี้ลงในไฟล์ Android.mk

LOCAL_SANITIZE:=integer
LOCAL_SANITIZE_DIAG:=integer

ค่า LOCAL_SANITIZE จะเปิดใช้โปรแกรมตรวจสอบระหว่างการสร้าง LOCAL_SANITIZE_DIAG เปิดโหมดการวินิจฉัยสำหรับโปรแกรมฆ่าเชื้อที่ระบุ คุณตั้งค่า LOCAL_SANITIZE และ LOCAL_SANITIZE_DIAG เป็นค่าที่แตกต่างกันได้ แต่ระบบจะเปิดใช้เฉพาะการตรวจสอบใน LOCAL_SANITIZE เท่านั้น หากไม่ได้ระบุการตรวจสอบใน LOCAL_SANITIZE แต่ระบุไว้ใน LOCAL_SANITIZE_DIAG ระบบจะไม่เปิดใช้การตรวจสอบและจะไม่แสดงข้อความการวินิจฉัย

ต่อไปนี้คือตัวอย่างข้อมูลที่ได้จากไลบรารีรันไทม์ UBSan

pixel-xl:/ # sanitizer-status ubsan
sanitizer-status/sanitizer-status.c:53:6: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long')

การดูแลจำนวนเต็มที่เกิน

การล้นจำนวนเต็มโดยไม่ตั้งใจอาจทำให้หน่วยความจำเสียหายหรือมีช่องโหว่ในการเปิดเผยข้อมูลในตัวแปรที่เชื่อมโยงกับการเข้าถึงหน่วยความจำหรือการจัดสรรหน่วยความจำ ในการรับมือกับปัญหานี้ เราได้เพิ่มโปรแกรมตรวจสอบจำนวนเต็มที่มีค่าเกินแบบมีและไม่มีเครื่องหมายของ UndefinedBehaviorSanitizer (UBSan) ของ Clang เพื่อเพิ่มความแข็งแกร่งให้กับเฟรมเวิร์กสื่อใน Android 7.0 ใน Android 9 เราได้ขยายการรองรับ USan ให้ครอบคลุมคอมโพเนนต์เพิ่มเติมและปรับปรุงการรองรับระบบบิลด์สำหรับ USan

ซึ่งออกแบบมาเพื่อเพิ่มการตรวจสอบการดำเนินการทางคณิตศาสตร์ / คำสั่ง ซึ่งอาจทำให้เกิดการสําคัญเกิน เพื่อยกเลิกกระบวนการอย่างปลอดภัยหากเกิดสําคัญเกินขึ้น โปรแกรมตรวจสอบเหล่านี้สามารถลดช่องโหว่การละเมิดข้อมูลและหน่วยความจำที่เสียหายทั้งคลาสได้ โดยสาเหตุหลักคือจำนวนเต็มที่เกินขอบเขต เช่น ช่องโหว่ Stagefright เดิม

ตัวอย่างและแหล่งที่มา

คอมไพเลอร์จะจัดเตรียมการตรวจสอบจำนวนเต็มที่มีค่าเกิน (IntSan) และเพิ่มเครื่องมือวัดลงในไบนารีระหว่างเวลาคอมไพล์เพื่อตรวจหาจำนวนที่เกินค่าที่อนุญาตในการคำนวณ ซึ่งจะเปิดใช้โดยค่าเริ่มต้นในคอมโพเนนต์ต่างๆ ทั่วทั้งแพลตฟอร์ม เช่น /platform/external/libnl/Android.bp

การใช้งาน

IntSan ใช้โปรแกรมแก้ไขจำนวนเต็มที่มีค่าเกินแบบมีและไม่มีเครื่องหมายของ UBSan การลดความเสี่ยงนี้เปิดใช้งานในระดับโมดูล ซึ่งช่วยรักษาคอมโพเนนต์ที่สำคัญของ Android ให้ปลอดภัยและไม่ควรปิดใช้

เราขอแนะนําอย่างยิ่งให้คุณเปิดใช้ "การกรองค่าจำนวนเต็มที่มีค่าเกิน" สําหรับคอมโพเนนต์เพิ่มเติม โค้ดเนทีฟที่มีสิทธิ์หรือโค้ดเนทีฟที่แยกวิเคราะห์อินพุตของผู้ใช้ที่ไม่น่าเชื่อถือเหมาะที่จะใช้ Sanitizer จะมีโอเวอร์เฮดด้านประสิทธิภาพเล็กน้อย ซึ่งขึ้นอยู่กับการใช้งานโค้ดและความถี่ของการดำเนินการทางคณิตศาสตร์ คาดว่าจะมีเปอร์เซ็นต์การสูญเสียเล็กน้อยและทดสอบว่าประสิทธิภาพเป็นปัญหาหรือไม่

รองรับ IntSan ในไฟล์ make

หากต้องการเปิดใช้ IntSan ในไฟล์ make ให้เพิ่ม

LOCAL_SANITIZE := integer_overflow
    # Optional features
    LOCAL_SANITIZE_DIAG := integer_overflow
    LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
  • LOCAL_SANITIZE ใช้รายการตัวกรองที่แยกด้วยคอมมา โดย integer_overflow คือชุดตัวเลือกที่รวมไว้ล่วงหน้าสำหรับตัวกรองจำนวนเต็มที่มีค่าเกินแบบมีและไม่มีเครื่องหมายของแต่ละรายการที่มีรายการที่บล็อกเริ่มต้น
  • LOCAL_SANITIZE_DIAG เปิดโหมดการวินิจฉัยสำหรับเครื่องฆ่าเชื้อ ใช้โหมดการวินิจฉัยระหว่างการทดสอบเท่านั้น เนื่องจากโหมดนี้จะไม่หยุดทำงานเมื่อเกิดค่าที่เกิน ซึ่งจะลบล้างข้อได้เปรียบด้านความปลอดภัยของการบรรเทาปัญหาโดยสิ้นเชิง ดูรายละเอียดเพิ่มเติมได้ที่การแก้ปัญหา
  • LOCAL_SANITIZE_BLOCKLIST ให้คุณระบุไฟล์ BLOCKLIST เพื่อป้องกันไม่ให้ระบบกรองฟังก์ชันและไฟล์ต้นทาง ดูรายละเอียดเพิ่มเติมที่หัวข้อการแก้ปัญหา

หากต้องการการควบคุมที่ละเอียดยิ่งขึ้น ให้เปิดใช้โปรแกรมตรวจสอบทีละรายการโดยใช้แฟล็กอย่างใดอย่างหนึ่งหรือทั้ง 2 รายการต่อไปนี้

LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow
    LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow

รองรับ IntSan ในไฟล์พิมพ์เขียว

หากต้องการเปิดใช้การดูแลจำนวนเต็มที่ล้นเกินในไฟล์พิมพ์เขียว เช่น /platform/external/libnl/Android.bp ให้เพิ่ม

   sanitize: {
          integer_overflow: true,
          diag: {
              integer_overflow: true,
          },
          BLOCKLIST: "modulename_BLOCKLIST.txt",
       },

เช่นเดียวกับไฟล์ make พร็อพเพอร์ตี้ integer_overflow คือชุดตัวเลือกที่แพ็กเกจไว้ล่วงหน้าสำหรับโปรแกรมตรวจสอบจำนวนเต็มที่มีค่าเกินแบบมีและไม่มีเครื่องหมายของแต่ละรายการที่มี BLOCKLIST เริ่มต้น

ชุดพร็อพเพอร์ตี้ diag เปิดใช้โหมดการวินิจฉัยสำหรับโปรแกรมฆ่าเชื้อ ใช้โหมดการวินิจฉัยระหว่างการทดสอบเท่านั้น โหมดการวินิจฉัยจะไม่หยุดทำงานเมื่อเกิดค่าที่เกิน ซึ่งจะลบล้างข้อได้เปรียบด้านความปลอดภัยของการบรรเทาในบิลด์ของผู้ใช้โดยสิ้นเชิง ดูรายละเอียดเพิ่มเติมที่หัวข้อการแก้ปัญหา

พร็อพเพอร์ตี้ BLOCKLIST อนุญาตให้ระบุไฟล์ BLOCKLIST ซึ่งช่วยให้นักพัฒนาแอปป้องกันไม่ให้ระบบกรองฟังก์ชันและไฟล์ต้นฉบับได้ ดูรายละเอียดเพิ่มเติมที่หัวข้อการแก้ปัญหา

หากต้องการเปิดใช้น้ำยาฆ่าเชื้อทีละรายการ ให้ใช้คำสั่งต่อไปนี้

   sanitize: {
          misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"],
          diag: {
              misc_undefined: ["signed-integer-overflow",
                               "unsigned-integer-overflow",],
          },
          BLOCKLIST: "modulename_BLOCKLIST.txt",
       },

การแก้ปัญหา

หากคุณเปิดใช้การดูแลจัดการจำนวนเต็มที่มีค่าเกินในคอมโพเนนต์ใหม่ หรือใช้ไลบรารีแพลตฟอร์มที่มีการดูแลจัดการจำนวนเต็มที่มีค่าเกิน คุณอาจพบปัญหาบางอย่างเกี่ยวกับจำนวนเต็มที่มีค่าเกินซึ่งไม่เป็นอันตรายซึ่งทำให้เกิดการหยุดทำงาน คุณควรทดสอบคอมโพเนนต์ที่เปิดใช้การกรองข้อมูลเพื่อดูว่าระบบแสดงค่าที่เกินมาซึ่งไม่เป็นอันตรายได้

หากต้องการค้นหาการหยุดทำงานที่เกิดจากการทำให้ข้อมูลไม่เป็นอันตรายในบิลด์ของผู้ใช้ ให้ค้นหาSIGABRTข้อขัดข้องที่มีข้อความ "หยุดทำงาน" ซึ่งบ่งบอกถึงการที่ UBSan ตรวจพบการล้น เช่น

pid: ###, tid: ###, name: Binder:###  >>> /system/bin/surfaceflinger <<<
    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'ubsan: sub-overflow'

ข้อมูลสแต็กเทรซควรมีฟังก์ชันที่ทำให้เกิดการหยุดทำงาน อย่างไรก็ตาม การล้นที่เกิดขึ้นในฟังก์ชันอินไลน์อาจไม่ปรากฏในข้อมูลสแต็กเทรซ

หากต้องการระบุสาเหตุของปัญหาได้ง่ายขึ้น ให้เปิดใช้การวินิจฉัยในคลัง ซึ่งจะทริกเกอร์การยกเลิกและพยายามจำลองข้อผิดพลาด เมื่อเปิดใช้การวินิจฉัย กระบวนการจะไม่หยุดกลางคันและจะทำงานต่อไป การไม่หยุดกลางคันจะช่วยเพิ่มจำนวนการล้นที่ไม่อันตรายในเส้นทางการดําเนินการหนึ่งๆ ให้ได้สูงสุดโดยไม่ต้องคอมไพล์อีกครั้งหลังจากแก้ไขข้อบกพร่องแต่ละข้อ ในการวินิจฉัย ระบบจะแสดงข้อความแสดงข้อผิดพลาดซึ่งมีหมายเลขบรรทัดและไฟล์ต้นทางที่ทําให้ยกเลิก

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')

เมื่อพบการดำเนินการทางคณิตศาสตร์ที่เป็นปัญหาแล้ว ให้ตรวจสอบว่าจำนวนที่เกินมานั้นไม่เป็นอันตรายและเป็นไปตามที่ต้องการ (เช่น ไม่มีผลกระทบด้านความปลอดภัย) คุณจัดการกับการหยุดทำงานของโปรแกรมตรวจสอบได้ดังนี้

  • การจัดระเบียบโค้ดใหม่เพื่อหลีกเลี่ยงการเกินค่า (ตัวอย่าง)
  • แสดงค่าที่เกินขีดจำกัดอย่างชัดเจนผ่านฟังก์ชัน __builtin_*_overflow ของ Clang (ตัวอย่าง)
  • การปิดใช้การกรองข้อมูลในฟังก์ชันโดยระบุแอตทริบิวต์ no_sanitize (ตัวอย่าง)
  • การปิดใช้การกรองฟังก์ชันหรือไฟล์ต้นทางผ่านไฟล์ BLOCKLIST (ตัวอย่าง)

คุณควรใช้โซลูชันที่ละเอียดที่สุดเท่าที่จะเป็นไปได้ ตัวอย่างเช่น ฟังก์ชันขนาดใหญ่ที่มีการดำเนินการทางคณิตศาสตร์หลายรายการและการดำเนินการที่เกิดการล้นเพียงรายการเดียว ควรได้รับการปรับโครงสร้างการดำเนินการเพียงรายการเดียวแทนการบล็อกทั้งฟังก์ชัน

รูปแบบทั่วไปที่อาจส่งผลให้เกิดการแสดงผลที่เกินขีดจำกัดแบบไม่มีอันตรายมีดังนี้

  • การแคสต์โดยนัยที่เกิดการล้นแบบไม่ลงนามก่อนที่จะแคสต์เป็นประเภทที่มีค่าลงนาม (ตัวอย่าง)
  • การลบลิงค์ลิสต์ซึ่งจะลดตัวชี้ของลูปเมื่อลบ (ตัวอย่าง)
  • การกำหนดประเภท unsigned เป็น -1 แทนการระบุค่าสูงสุดจริง (ตัวอย่าง)
  • ลูปที่ลดจํานวนเต็มแบบไม่ลงนามในเงื่อนไข (example, example)

เราขอแนะนำให้นักพัฒนาแอปตรวจสอบว่ากรณีที่โปรแกรมตรวจสอบพบว่ามีการรับค่าเกินนั้นไม่ก่อให้เกิดอันตรายใดๆ โดยไม่มีผลข้างเคียงหรือผลกระทบด้านความปลอดภัยที่ไม่ตั้งใจก่อนที่จะปิดใช้การตรวจสอบ

ปิดใช้ IntSan

คุณสามารถปิดใช้ IntSan ได้ด้วย BLOCKLIST หรือแอตทริบิวต์ฟังก์ชัน ปิดใช้อย่างประหยัดและเฉพาะในกรณีที่การแยกส่วนโค้ดไม่สมเหตุสมผลหรือมีค่าใช้จ่ายเพิ่มเติมด้านประสิทธิภาพที่ทำให้เกิดปัญหา

ดูข้อมูลเพิ่มเติมเกี่ยวกับการปิดใช้ IntSan ด้วยแอตทริบิวต์ฟังก์ชันและการจัดรูปแบบไฟล์ BLOCKLIST ในเอกสารประกอบ Clang เวอร์ชัน upstream การบล็อกควรกําหนดขอบเขตให้เฉพาะตัวกรองข้อมูลโดยใช้ชื่อส่วนซึ่งระบุตัวกรองข้อมูลเป้าหมายเพื่อหลีกเลี่ยงการส่งผลกระทบต่อตัวกรองข้อมูลอื่นๆ

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

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

การดูแลขอบเขต

BoundsSanitizer (BoundSan) จะเพิ่มเครื่องมือวัดผลลงในไบนารีเพื่อแทรกการตรวจสอบขอบเขตรอบการเข้าถึงอาร์เรย์ ระบบจะเพิ่มการตรวจสอบเหล่านี้หากคอมไพเลอร์ไม่สามารถพิสูจน์ได้เมื่อคอมไพล์ว่าสิทธิ์เข้าถึงจะปลอดภัย และหากทราบขนาดของอาร์เรย์ขณะรันไทม์เพื่อให้ตรวจสอบได้ Android 10 ใช้ BoundSan ในบลูทูธและตัวแปลงรหัส BoundSan มาจากคอมไพเลอร์และเปิดใช้โดยค่าเริ่มต้นในคอมโพเนนต์ต่างๆ ทั่วทั้งแพลตฟอร์ม

การใช้งาน

BoundSan ใช้โปรแกรมตรวจสอบขอบเขตของ UBSan การลดความเสี่ยงนี้จะเปิดใช้งานในระดับโมดูล ซึ่งช่วยรักษาคอมโพเนนต์ที่สำคัญของ Android ให้ปลอดภัยและไม่ควรปิดใช้

เราขอแนะนําอย่างยิ่งให้คุณเปิดใช้ BoundSan สําหรับคอมโพเนนต์เพิ่มเติม โค้ดที่เหมาะสมคือโค้ดเนทีฟที่มีสิทธิ์หรือโค้ดเนทีฟที่ซับซ้อนซึ่งแยกวิเคราะห์ข้อมูลที่ผู้ใช้ป้อนซึ่งไม่น่าเชื่อถือ ค่าใช้จ่ายเพิ่มเติมด้านประสิทธิภาพที่เชื่อมโยงกับการเปิดใช้ BoundSan จะขึ้นอยู่กับจํานวนการเข้าถึงอาร์เรย์ที่ไม่สามารถพิสูจน์ได้ว่าปลอดภัย คาดว่าจะมีเปอร์เซ็นต์ค่าใช้จ่ายเพิ่มเติมเล็กน้อยโดยเฉลี่ย และทดสอบว่าประสิทธิภาพเป็นปัญหาหรือไม่

เปิดใช้ BoundSan ในไฟล์พิมพ์เขียว

คุณเปิดใช้ BoundSan ในไฟล์พิมพ์เขียวได้โดยเพิ่ม "bounds" ลงในพร็อพเพอร์ตี้ misc_undefined sanitize สำหรับโมดูลไบนารีและไลบรารี ดังนี้

    sanitize: {
       misc_undefined: ["bounds"],
       diag: {
          misc_undefined: ["bounds"],
       },
       BLOCKLIST: "modulename_BLOCKLIST.txt",
diag

พร็อพเพอร์ตี้ diag เปิดใช้โหมดการวินิจฉัยสำหรับเครื่องฆ่าเชื้อ ใช้โหมดการวินิจฉัยระหว่างการทดสอบเท่านั้น โหมดการวินิจฉัยจะไม่หยุดทำงานเมื่อเกิดข้อผิดพลาดในการรับค่าที่เกิน ซึ่งจะลบล้างข้อได้เปรียบด้านความปลอดภัยของการบรรเทาปัญหาและทำให้เกิดค่าใช้จ่ายเพิ่มเติมด้านประสิทธิภาพที่สูงขึ้น ดังนั้นจึงไม่แนะนำสำหรับบิลด์ที่ใช้งานจริง

รายการที่บล็อก

พร็อพเพอร์ตี้ BLOCKLIST อนุญาตให้ระบุไฟล์ BLOCKLIST ที่นักพัฒนาแอปสามารถใช้เพื่อป้องกันไม่ให้ระบบกรองฟังก์ชันและไฟล์ต้นฉบับ ใช้พร็อพเพอร์ตี้นี้เฉพาะในกรณีที่ประสิทธิภาพเป็นข้อกังวลและไฟล์/ฟังก์ชันเป้าหมายมีส่วนเกี่ยวข้องอย่างมาก ตรวจสอบไฟล์/ฟังก์ชันเหล่านี้ด้วยตนเองเพื่อให้แน่ใจว่าการเข้าถึงอาร์เรย์นั้นปลอดภัย ดูรายละเอียดเพิ่มเติมที่หัวข้อการแก้ปัญหา

เปิดใช้ BoundSan ในไฟล์ make

คุณสามารถเปิดใช้ BoundSan ในไฟล์ make ได้โดยเพิ่ม "bounds" ลงในตัวแปร LOCAL_SANITIZE สำหรับโมดูลไบนารีและไลบรารี

    LOCAL_SANITIZE := bounds
    # Optional features
    LOCAL_SANITIZE_DIAG := bounds
    LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt

LOCAL_SANITIZE ยอมรับรายการตัวกรองที่แยกด้วยคอมมา

LOCAL_SANITIZE_DIAG เปิดโหมดวิเคราะห์ ใช้โหมดการวินิจฉัยระหว่างการทดสอบเท่านั้น โหมดการวินิจฉัยจะไม่หยุดทำงานเมื่อเกิดค่าที่เกิน ซึ่งจะลบล้างข้อได้เปรียบด้านความปลอดภัยของการบรรเทาและทำให้ประสิทธิภาพการทำงานเพิ่มขึ้น ดังนั้นจึงไม่แนะนำสำหรับบิลด์ที่ใช้งานจริง

LOCAL_SANITIZE_BLOCKLIST อนุญาตให้ระบุไฟล์ BLOCKLIST ซึ่งช่วยให้นักพัฒนาซอฟต์แวร์ป้องกันไม่ให้ระบบกรองฟังก์ชันและไฟล์ต้นฉบับ ใช้พร็อพเพอร์ตี้นี้เฉพาะในกรณีที่ประสิทธิภาพเป็นข้อกังวลและไฟล์/ฟังก์ชันเป้าหมายมีส่วนเกี่ยวข้องอย่างมาก ตรวจสอบไฟล์/ฟังก์ชันเหล่านี้ด้วยตนเองเพื่อให้แน่ใจว่าการเข้าถึงอาร์เรย์นั้นปลอดภัย ดูรายละเอียดเพิ่มเติมที่หัวข้อการแก้ปัญหา

ปิดใช้ BoundSan

คุณสามารถปิดใช้ BoundSan ในฟังก์ชันและไฟล์ต้นฉบับได้ด้วย BLOCKLIST หรือแอตทริบิวต์ฟังก์ชัน เราขอแนะนำให้เปิดใช้ BoundSan ไว้เสมอ ดังนั้นให้ปิดใช้ก็ต่อเมื่อฟังก์ชันหรือไฟล์สร้างภาระงานด้านประสิทธิภาพจำนวนมากและแหล่งที่มาได้รับการตรวจสอบโดยเจ้าหน้าที่แล้ว

ดูข้อมูลเพิ่มเติมเกี่ยวกับการปิดใช้ BoundSan ด้วยแอตทริบิวต์ฟังก์ชันและการจัดรูปแบบไฟล์ BLOCKLIST ได้ที่เอกสารประกอบ Clang LLVM กําหนดขอบเขตการบล็อกรายการไปยังโปรแกรมตรวจสอบที่เฉพาะเจาะจงโดยใช้ชื่อส่วนซึ่งระบุโปรแกรมตรวจสอบเป้าหมายเพื่อหลีกเลี่ยงการส่งผลกระทบต่อโปรแกรมตรวจสอบอื่นๆ

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

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

การแก้ปัญหา

ทดสอบคอมโพเนนต์อย่างละเอียดหลังจากเปิดใช้ BoundSan เพื่อให้แน่ใจว่าการเข้าถึงที่อยู่นอกขอบเขตที่ตรวจไม่พบก่อนหน้านี้ได้รับการแก้ไขแล้ว

ข้อผิดพลาด BoundSan จะระบุได้ง่ายเนื่องจากมีข้อความยกเลิกการลบไฟล์ต่อไปนี้

    pid: ###, tid: ###, name: Binder:###  >>> /system/bin/foobar <<<
    signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
    Abort message: 'ubsan: out-of-bounds'

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

    external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'