AddressSanitizer hỗ trợ phần cứng

Hãy xem bài viết Tìm hiểu báo cáo HWASan để biết thông tin về cách đọc các sự cố HWASan!

AddressSanitizer (HWASan) có phần cứng hỗ trợ là một công cụ phát hiện lỗi bộ nhớ tương tự như AddressSanitizer. HWASan sử dụng ít RAM hơn nhiều so với ASan, nhờ đó phù hợp để dọn dẹp toàn bộ hệ thống. HWASan chỉ có trên Android 10 trở lên và chỉ trên phần cứng AArch64.

Mặc dù chủ yếu hữu ích cho mã C/C++, nhưng HWASan cũng có thể giúp gỡ lỗi mã Java gây ra sự cố trong C/C++ dùng để triển khai giao diện Java. Việc này rất hữu ích vì nó phát hiện được lỗi bộ nhớ khi chúng xảy ra, hướng dẫn bạn trực tiếp đến mã chịu trách nhiệm.

Bạn có thể truyền nhanh hình ảnh HWASan tạo sẵn sang các thiết bị Pixel được hỗ trợ từ ci.android.com (hướng dẫn thiết lập chi tiết).

So với ASan cũ, HWASan có:

  • Mức hao tổn CPU tương tự (~2x)
  • Mức hao tổn kích thước mã tương tự (40 – 50%)
  • Mức hao tổn RAM nhỏ hơn nhiều (10% – 35%)

HWASan phát hiện cùng một nhóm lỗi như ASan:

  • Chặn tràn (overflow)/chặn trống (underflow) cho ngăn xếp (stack) và bộ nhớ khối xếp (heap)
  • Sử dụng bộ nhớ khối xếp sau khi giải phóng
  • Sử dụng ngăn xếp bên ngoài phạm vi
  • Giải phóng hai lần/giải phóng bộ nhớ chưa được cấp phát trước đó

Ngoài ra, HWASan còn phát hiện việc sử dụng ngăn xếp sau khi trả về.

HWASan (tương tự như ASan) tương thích với UBSan, cả hai đều có thể được bật trên một mục tiêu cùng một lúc.

Thông tin chi tiết về việc triển khai và các giới hạn

HWASan dựa trên phương pháp gắn thẻ bộ nhớ, trong đó một giá trị thẻ ngẫu nhiên nhỏ được liên kết với cả con trỏ và phạm vi địa chỉ bộ nhớ. Để quyền truy cập vào bộ nhớ hợp lệ, con trỏ và thẻ bộ nhớ phải khớp với nhau. HWASan dựa vào tính năng bỏ qua byte hàng đầu của tính năng ARMv8 (TBI), còn được gọi là gắn thẻ địa chỉ ảo, để lưu trữ thẻ con trỏ trong các bit cao nhất của địa chỉ.

Bạn có thể đọc thêm về thiết kế của HWASan trên trang web tài liệu của Clang.

Theo thiết kế, HWASan không có vùng màu đỏ có kích thước hạn chế của ASan để phát hiện tình trạng tràn bộ nhớ hoặc vùng cách ly có dung lượng hạn chế của ASan để phát hiện lỗi sử dụng sau khi giải phóng. Vì lý do này, HWASan có thể phát hiện lỗi bất kể mức độ tràn bộ nhớ hay thời gian giải phóng bộ nhớ. Điều này mang lại cho HWASan một lợi thế lớn so với ASan.

Tuy nhiên, HWASan có số lượng giá trị thẻ có thể có hạn (256), nghĩa là có 0,4% khả năng bỏ lỡ lỗi trong một lần thực thi chương trình.

Yêu cầu

Các phiên bản gần đây (4.14 trở lên) của nhân hệ điều hành Android phổ biến hỗ trợ HWASan ngay từ đầu. Các nhánh cụ thể trên Android 10 không hỗ trợ HWASan.

Tính năng hỗ trợ không gian người dùng dành cho HWASan hiện có từ Android 11.

Nếu bạn đang làm việc với một hạt nhân khác, HWASan yêu cầu hạt nhân Linux chấp nhận con trỏ được gắn thẻ trong các đối số lệnh gọi hệ thống. Hỗ trợ cho việc này đã được triển khai trong các nhóm bản vá ngược sau:

Nếu bạn đang tạo bằng một chuỗi công cụ tuỳ chỉnh, hãy đảm bảo rằng chuỗi công cụ đó bao gồm mọi thứ cho đến thay đổi c336557f của LLVM.

Sử dụng HWASan

Sử dụng các lệnh sau để tạo toàn bộ nền tảng bằng HWASan:

lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j

Để thuận tiện, bạn có thể thêm chế độ cài đặt SANITIZE_TARGET vào định nghĩa sản phẩm, tương tự như aosp_coral_hwasan.

Đối với những người dùng quen thuộc với AddressSanitizer, nhiều vấn đề phức tạp về bản dựng đã không còn nữa:

  • Không cần chạy make hai lần.
  • Các bản dựng gia tăng hoạt động ngay từ đầu.
  • Không cần phải cài đặt ROM dữ liệu người dùng.

Một số hạn chế của AddressSanitizer cũng sẽ biến mất:

  • Hỗ trợ các tệp thực thi tĩnh.
  • Bạn có thể bỏ qua việc dọn dẹp bất kỳ mục tiêu nào khác ngoài libc. Không giống như ASan, không có yêu cầu nào về việc nếu một thư viện được dọn dẹp thì mọi tệp thực thi liên kết với thư viện đó cũng phải được dọn dẹp.

Bạn có thể thoải mái chuyển đổi giữa HWASan và các hình ảnh thông thường ở cùng số bản dựng (hoặc cao hơn). Bạn không cần phải xoá sạch thiết bị.

Để bỏ qua bước dọn dẹp một mô-đun, hãy sử dụng LOCAL_NOSANITIZE := hwaddress (Android.mk) hoặc sanitize: { hwaddress: false } (Android.bp).

Xoá dữ liệu rác khỏi từng mục tiêu

Bạn có thể bật HWASan cho mỗi mục tiêu trong một bản dựng thông thường (chưa được dọn dẹp), miễn là libc.so cũng được dọn dẹp. Thêm hwaddress: true vào khối dọn dẹp trong "libc_defaults" trong bionic/libc/Android.bp. Sau đó, hãy làm tương tự trong mục tiêu mà bạn đang làm việc.

Hãy lưu ý rằng tính năng dọn dẹp libc cho phép gắn thẻ cơ chế phân bổ bộ nhớ vùng nhớ khối xếp trên toàn hệ thống, cũng như khả năng kiểm tra thẻ cho các hoạt động bộ nhớ bên trong libc.so. Việc này có thể phát hiện lỗi ngay cả trong các tệp nhị phân mà HWASan không được bật nếu quyền truy cập không hợp lệ vào bộ nhớ nằm trong libc.so (ví dụ: pthread_mutex_unlock() trên một mutex delete()).

Bạn không cần thay đổi tệp bản dựng nào nếu toàn bộ nền tảng được tạo bằng HWASan.

FlashStation

Đối với mục đích phát triển, bạn có thể cài đặt ROM bản dựng AOSP hỗ trợ HWASan trên một thiết bị Pixel có trình tải khởi động đã mở khoá bằng Flashstation. Chọn mục tiêu _hwasan, ví dụ: aosp_flame_hwasan-userdebug. Hãy xem tài liệu về NDK dành cho HWASan dành cho nhà phát triển ứng dụng để biết thêm thông tin.

Dấu vết ngăn xếp chính xác hơn

HWASan sử dụng một trình tháo dỡ nhanh dựa trên con trỏ khung để ghi lại dấu vết ngăn xếp cho mọi sự kiện phân bổ và giải phóng bộ nhớ trong chương trình. Theo mặc định, Android bật con trỏ khung trong mã AArch64, vì vậy, cách này hoạt động rất hiệu quả trong thực tế. Nếu bạn cần giải phóng thông qua mã được quản lý, hãy đặt HWASAN_OPTIONS=fast_unwind_on_malloc=0 trong môi trường quy trình. Xin lưu ý rằng theo mặc định, các dấu vết ngăn xếp truy cập bộ nhớ không hợp lệ sẽ sử dụng trình tháo dỡ "chậm"; chế độ cài đặt này chỉ ảnh hưởng đến các dấu vết phân bổ và giải phóng. Tuỳ chọn này có thể dùng rất nhiều CPU, tuỳ thuộc vào tải.

Biểu tượng

Xem phần Biểu tượng hoá trong bài viết "Tìm hiểu báo cáo HWASan".

HWASan trong ứng dụng

Tương tự như AddressSanitizer, HWASan không thể xem mã Java, nhưng có thể phát hiện lỗi trong thư viện JNI. Cho đến Android 14, việc chạy ứng dụng HWASan trên thiết bị không phải HWASan không được hỗ trợ.

Trên thiết bị HWASan, bạn có thể kiểm tra ứng dụng bằng HWASan bằng cách tạo mã bằng SANITIZE_TARGET:=hwaddress trong Make hoặc -fsanitize=hwaddress trong cờ trình biên dịch. Trên thiết bị không phải HWASan (chạy Android 14 trở lên), bạn phải thêm chế độ cài đặt tệp wrap.sh LD_HWASAN=1. Hãy xem tài liệu dành cho nhà phát triển ứng dụng để biết thêm thông tin chi tiết.