Xem Tìm hiểu HWASan báo cáo để biết thông tin về cách đọc các sự cố HWASan!
Hardware-assisted AddressSanitizer (HWASan) 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 với việc 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 các giao diện Java. Công cụ này hữu ích vì phát hiện lỗi bộ nhớ khi chúng xảy ra, hướng bạn trực tiếp đến mã chịu trách nhiệm.
So với phiên bản 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 thấp 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 lúc.
Thông tin chi tiết và hạn chế về việc triển khai
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à các dải địa chỉ bộ nhớ. Để truy cập bộ nhớ hợp lệ, con trỏ và thẻ bộ nhớ phải khớp nhau. HWASan dựa vào tính năng bỏ qua byte quan trọng nhất (TBI) của ARMv8 (còn gọi là gắn thẻ địa chỉ ảo) để lưu trữ thẻ con trỏ ở 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 tài liệu Clang.
Theo thiết kế, HWASan không có các vùng đỏ có kích thước giới hạn của ASan để phát hiện tình trạng tràn hoặc vùng cách ly có dung lượng giới hạn của ASan để phát hiện việc 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ể tình trạng tràn lớn đến mức nào hoặc bộ nhớ đã được giải phóng bao lâu. Đ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ó giới hạn (256), nghĩa là có 0,4% khả năng bỏ sót bất kỳ lỗi nào 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+) của nhân Android phổ biến hỗ trợ HWASan ngay khi cài đặt. Các nhánh cụ thể của Android 10 không hỗ trợ HWASan.
Tính năng hỗ trợ không gian người dùng cho HWASan bắt đầu từ Android 11.
Nếu bạn đang làm việc với một nhân khác, thì HWASan yêu cầu nhân Linux chấp nhận các con trỏ được gắn thẻ trong các đối số lệnh gọi hệ thống. Tính năng hỗ trợ này đã được triển khai trong các bộ bản vá thượng nguồn sau:
- ABI địa chỉ được gắn thẻ arm64
- arm64: bỏ gắn thẻ con trỏ người dùng được truyền đến nhân
- mm: Tránh tạo bí danh địa chỉ ảo trong brk()/mmap()/mremap()
- arm64: Xác thực các địa chỉ được gắn thẻ trong access_ok() được gọi từ các luồng nhân
Nếu bạn đang xây dựng 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 cam kết LLVM c336557f.
Sử dụng HWASan
Sử dụng các lệnh sau để xây dựng toàn bộ nền tảng bằng HWASan:
lunch aosp_walleye-userdebug # (or any other product)export SANITIZE_TARGET=hwaddressm -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 sự phức tạp trong bản dựng đã biến mất:
- Không cần chạy make hai lần.
- Các bản dựng gia tăng hoạt động ngay khi cài đặt.
- Không cần flash dữ liệu người dùng.
Một số hạn chế của AddressSanitizer cũng biến mất:
- Các tệp thực thi tĩnh được hỗ trợ.
- Bạn có thể bỏ qua việc dọn dẹp mọi mục tiêu 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à hình ảnh thông thường ở cùng số bản dựng (hoặc cao hơn) có thể được thực hiện một cách tự do. Bạn không cần phải xoá dữ liệu trên thiết bị.
Để bỏ qua việ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).
Dọn dẹp các mục tiêu riêng lẻ
Bạn có thể bật HWASan cho từng 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.
Xin lưu ý rằng việc dọn dẹp libc cho phép gắn thẻ các lượt phân bổ bộ nhớ khối xếp trên toàn hệ thống, cũng như việc
kiểm tra các thẻ cho các thao tác bộ nhớ bên trong libc.so. Điều 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 hoạt động truy cập bộ nhớ xấu nằm trong libc.so
(ví dụ: pthread_mutex_unlock() trên một mutex delete()ed).
Bạn không cần thay đổi bất kỳ tệp bản dựng nào nếu toàn bộ nền tảng được xây dựng bằng HWASan.
Dấu vết ngăn xếp tốt hơn
HWASan sử dụng một bộ 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, điều này hoạt động rất tốt trong thực tế. Nếu bạn cần tháo dỡ 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 dấu vết ngăn xếp truy cập bộ nhớ xấu sử dụng bộ tháo dỡ "chậm" theo mặc định; chế độ cài đặt này chỉ ảnh hưởng đến dấu vết phân bổ và giải phóng. Tuỳ chọn này có thể tiêu tốn rất nhiều
CPU, tuỳ thuộc vào mức tải.
Ký hiệu hoá
Xem phần Ký hiệu hoá trong "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 các thư viện JNI. Cho đến Android 14, việc chạy các ứ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 các ứng dụng bằng HWASan bằng cách xây dựng mã của chúng 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 cho nhà phát triển ứng dụng để biết thêm thông tin chi tiết.