Google cam kết thúc đẩy công bằng chủng tộc cho Cộng đồng người da đen. Xem cách thực hiện.

AddressSanitizer

AddressSanitizer (ASan) là một công cụ dựa trên trình biên dịch nhanh để phát hiện lỗi bộ nhớ trong mã gốc.

ASan phát hiện:

  • Ngăn xếp và tràn bộ đệm heap / tràn bộ đệm
  • Sử dụng hàng đống sau khi miễn phí
  • Sử dụng ngăn xếp bên ngoài phạm vi
  • Nhân đôi miễn phí / hoang dã miễn phí

ASan chạy trên cả ARM 32-bit và 64-bit, cộng với x86 và x86-64. Chi phí CPU của ASan là khoảng 2x, chi phí kích thước mã từ 50% đến 2x và chi phí bộ nhớ lớn (phụ thuộc vào các mẫu phân bổ của bạn, nhưng theo thứ tự là 2x).

Android 10 và các chi nhánh chủ AOSP trên AArch64 hỗ trợ tăng tốc phần cứng Asan (Hwasan) , một công cụ tương tự với chi phí thấp hơn RAM và một loạt lớn các lỗi phát hiện. HWASan phát hiện việc sử dụng ngăn xếp sau khi trả về, ngoài các lỗi được phát hiện bởi ASan.

HWASan có chi phí CPU và kích thước mã tương tự, nhưng chi phí RAM nhỏ hơn nhiều (15%). HWASan là không xác định. Chỉ có 256 giá trị thẻ có thể có, vì vậy xác suất bỏ sót bất kỳ lỗi nào là 0,4% cố định. HWASan không có các vùng màu đỏ có kích thước giới hạn của ASan để phát hiện tràn và vùng cách ly dung lượng hạn chế để phát hiện sử dụng sau khi hết, vì vậy không quan trọng HWASan mức độ tràn lớn như thế nào hoặc bộ nhớ đã được phân bổ cách đây bao lâu. Điều này làm cho HWASan tốt hơn ASan. Bạn có thể đọc thêm về các thiết kế của Hwasan hoặc về việc sử dụng Hwasan trên Android .

ASan phát hiện tràn ngăn xếp / toàn cục ngoài việc tràn đống và nhanh chóng với chi phí bộ nhớ tối thiểu.

Tài liệu này mô tả cách xây dựng và chạy các phần / tất cả Android với ASan. Nếu bạn đang xây dựng một SDK / app NDK với Asan, xem Địa chỉ Sanitizer để thay thế.

Dọn dẹp các tệp thi hành riêng lẻ bằng ASan

Thêm LOCAL_SANITIZE:=address hoặc sanitize: { address: true } cho quy tắc xây dựng cho thực thi. Bạn có thể tìm kiếm mã cho các ví dụ hiện có hoặc để tìm các chất khử trùng có sẵn khác.

Khi một lỗi được phát hiện, Asan in một tiết báo cáo cả hai đến đầu ra tiêu chuẩn và logcat và sau đó bị treo quá trình này.

Dọn dẹp các thư viện được chia sẻ với ASan

Do cách hoạt động của ASan, một thư viện được xây dựng bằng ASan chỉ có thể được sử dụng bởi một tệp thực thi được xây dựng bằng ASan.

Để khử trùng một thư viện được chia sẻ được sử dụng trong nhiều tệp thực thi, không phải tất cả đều được xây dựng bằng ASan, bạn cần hai bản sao của thư viện. Cách khuyến khích để làm điều này là để thêm phần sau đây để Android.mk cho các mô-đun trong câu hỏi:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

Puts này thư viện trong /system/lib/asan thay vì /system/lib . Sau đó, chạy tệp thực thi của bạn với:

LD_LIBRARY_PATH=/system/lib/asan

Đối với daemon hệ thống, thêm sau vào phần thích hợp của /init.rc hoặc /init.$device$.rc .

setenv LD_LIBRARY_PATH /system/lib/asan

Xác minh rằng quá trình này được sử dụng thư viện từ /system/lib/asan khi có mặt bằng cách đọc /proc/$PID/maps . Nếu không, bạn có thể cần phải tắt SELinux:

adb root
adb shell setenforce 0
# restart the process with adb shell kill $PID
# if it is a system service, or may be adb shell stop; adb shell start.

Dấu vết ngăn xếp tốt hơn

ASan sử dụng một trình giải nén nhanh, dựa trên con trỏ khung để ghi lại một dấu vết ngăn xếp cho mọi sự kiện phân bổ và phân bổ bộ nhớ trong chương trình. Hầu hết Android được xây dựng mà không có con trỏ khung. Kết quả là bạn thường chỉ nhận được một hoặc hai khung hình có ý nghĩa. Để khắc phục điều này, hãy xây dựng lại thư viện bằng ASan (được khuyến nghị!) Hoặc bằng:

LOCAL_CFLAGS:=-fno-omit-frame-pointer
LOCAL_ARM_MODE:=arm

Hoặc thiết lập ASAN_OPTIONS=fast_unwind_on_malloc=0 trong môi trường quá trình. Sau này có thể rất tốn CPU, tùy thuộc vào tải.

Biểu tượng

Ban đầu, các báo cáo ASan chứa các tham chiếu đến các hiệu số trong các tệp nhị phân và các thư viện được chia sẻ. Có hai cách để lấy thông tin về dòng và tệp nguồn:

  • Đảm bảo rằng các llvm-symbolizer nhị phân có mặt trong /system/bin . llvm-symbolizer được xây dựng từ các nguồn trong third_party/llvm/tools/llvm-symbolizer .
  • Lọc báo cáo thông qua external/compiler-rt/lib/asan/scripts/symbolize.py kịch bản.

Cách tiếp cận thứ hai có thể cung cấp nhiều dữ liệu hơn (có nghĩa là, file:line địa điểm) vì sự sẵn có của các thư viện biểu tượng trên máy chủ.

ASan trong ứng dụng

ASan không thể nhìn thấy mã Java, nhưng nó có thể phát hiện lỗi trong thư viện JNI. Cho rằng, bạn cần phải xây dựng thực thi với Asan, mà trong trường hợp này là /system/bin/app_process( 32|64 ) . Điều này cho phép ASan trong tất cả các ứng dụng trên thiết bị cùng một lúc, đây là một tải nặng, nhưng thiết bị có RAM 2 GB sẽ có thể xử lý điều này.

Thêm LOCAL_SANITIZE:=address để các app_process xây dựng quy tắc trong frameworks/base/cmds/app_process . Bỏ qua các app_process__asan mục tiêu trong cùng một tập tin cho bây giờ (nếu nó vẫn còn đó tại thời điểm bạn đọc này).

Chỉnh sửa các service zygote phần của hợp system/core/rootdir/init.zygote( 32|64 ).rc tập tin để thêm các dòng sau vào khối dòng thụt vào có chứa class main , cũng thụt vào bởi số lượng giống nhau:

    setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
    setenv ASAN_OPTIONS allow_user_segv_handler=true

Xây dựng, đồng bộ hóa adb, khởi động flash fastboot và khởi động lại.

Sử dụng thuộc tính bọc

Cách tiếp cận trong phần trước đặt ASan vào mọi ứng dụng trong hệ thống (trên thực tế, vào mọi hậu duệ của quy trình Zygote). Có thể chỉ chạy một (hoặc một số) ứng dụng với ASan, giao dịch một số chi phí bộ nhớ để khởi động ứng dụng chậm hơn.

Điều này có thể được thực hiện bằng cách bắt đầu ứng dụng của bạn với wrap. bất động sản. Ví dụ sau chạy ứng dụng Gmail trong ASan:

adb root
adb shell setenforce 0  # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"

Trong bối cảnh này, asanwrapper viết lại /system/bin/app_process để /system/bin/asan/app_process , được xây dựng với Asan. Nó cũng cho biết thêm /system/lib/asan vào lúc bắt đầu của con đường tìm kiếm động thư viện. Bằng cách này, Asan-instrumented thư viện từ /system/lib/asan được ưa thích đến thư viện bình thường trong /system/lib khi chạy với asanwrapper .

Nếu một lỗi được tìm thấy, ứng dụng sẽ bị treo và báo cáo sẽ được in vào nhật ký.

SANITIZE_TARGET

Android 7.0 trở lên bao gồm hỗ trợ xây dựng toàn bộ nền tảng Android với ASan cùng một lúc. (Nếu bạn đang xây dựng một bản phát hành cao hơn Android 9, HWASan là một lựa chọn tốt hơn.)

Chạy các lệnh sau trong cùng một cây xây dựng.

make -j42
SANITIZE_TARGET=address make -j42

Trong chế độ này, userdata.img chứa các thư viện thêm và phải được chiếu cho các thiết bị là tốt. Sử dụng dòng lệnh sau:

fastboot flash userdata && fastboot flashall

Này được xây dựng hai bộ thư viện chia sẻ: bình thường trong /system/lib (người đầu tiên làm cho invocation), và Asan-instrumented trong /data/asan/lib (thứ hai làm cho invocation). Các tệp thực thi từ bản dựng thứ hai sẽ ghi đè lên các tệp thực thi từ bản dựng đầu tiên. Thực thi Asan-instrumented có được một đường dẫn tìm kiếm thư viện khác nhau trong đó bao gồm /data/asan/lib trước /system/lib qua việc sử dụng các /system/bin/linker_asan trong PT_INTERP .

Các clobbers xây dựng hệ thống trung gian thư mục đối tượng khi $SANITIZE_TARGET giá trị đã thay đổi. Lực lượng này xây dựng lại của tất cả các mục tiêu trong khi vẫn giữ mã nhị phân được cài đặt dưới /system/lib .

Một số mục tiêu không thể được tạo bằng ASan:

  • Các tệp thực thi được liên kết tĩnh
  • LOCAL_CLANG:=false mục tiêu
  • LOCAL_SANITIZE:=false không ASan'd cho SANITIZE_TARGET=address

Thực thi như thế này được bỏ qua trong SANITIZE_TARGET xây dựng, và các phiên bản từ make gọi đầu tiên còn lại trong /system/bin .

Các thư viện như thế này được xây dựng mà không có ASan. Chúng có thể chứa một số mã ASan từ các thư viện tĩnh mà chúng phụ thuộc vào.

Tài liệu hỗ trợ