Bộ nhớ chỉ thực thi (XOM) đối với tệp nhị phân AArch64

Các phần mã có thể thực thi cho tệp nhị phân hệ thống AArch64 được đánh dấu theo mặc định chỉ thực thi (không đọc được) như một biện pháp giảm thiểu tăng cường chống lại mã đúng thời điểm sử dụng lại các cuộc tấn công. Loại mã kết hợp dữ liệu và mã với nhau rồi mã có chủ đích kiểm tra những phần này (mà không cần ánh xạ lại các phân đoạn bộ nhớ trước là có thể đọc được) không còn hoạt động nữa. Ứng dụng có SDK mục tiêu là 10 (API cấp 29 trở lên) sẽ bị ảnh hưởng nếu ứng dụng cố gắng đọc các phần mã của Thư viện hệ thống hỗ trợ bộ nhớ chỉ thực thi (XOM) trong bộ nhớ không có trước đánh dấu phần này là có thể đọc được.

Để hưởng lợi tối đa từ giải pháp giảm thiểu này, cả khả năng hỗ trợ cả phần cứng và nhân hệ điều hành đều: là bắt buộc. Nếu không có sự hỗ trợ này, biện pháp giảm thiểu có thể chỉ được thực thi một phần. Chiến lược phát hành đĩa đơn Nhân hệ điều hành phổ biến của Android 4.9 chứa các bản vá thích hợp để cung cấp đầy đủ khả năng hỗ trợ cho quy trình này trên các thiết bị ARMv8.2.

Triển khai

Các tệp nhị phân AArch64 do trình biên dịch tạo giả định rằng mã và dữ liệu kết hợp. Việc bật tính năng này không ảnh hưởng tiêu cực đến hiệu suất của thiết bị.

Đối với đoạn mã phải chủ ý xem xét bộ nhớ trên phân đoạn có thể thực thi, bạn nên gọi mprotect trên các đoạn mã cần kiểm tra để đảm bảo chúng dễ đọc, sau đó sẽ xoá khả năng đọc khi quá trình kiểm tra hoàn tất.
Phương thức triển khai này dẫn đến việc đọc các phân đoạn bộ nhớ được đánh dấu là chỉ thực thi để dẫn đến lỗi phân đoạn (SEGFAULT). Điều này có thể xảy ra do lỗi, lỗ hổng bảo mật, dữ liệu kết hợp với mã (phân tách theo nghĩa đen) hoặc chủ ý xem xét bộ nhớ.

Mức độ hỗ trợ và tác động đối với thiết bị

Thiết bị có phần cứng cũ hơn hoặc các nhân phiên bản cũ hơn (thấp hơn 4.9) mà không có các bản vá cần thiết có thể không hỗ trợ đầy đủ hoặc hưởng lợi từ tính năng này. Thiết bị không có hỗ trợ nhân hệ điều hành có thể không thực thi quyền truy cập của người dùng vào bộ nhớ chỉ thực thi, tuy nhiên, mã hạt nhân kiểm tra rõ ràng xem một trang có thể đọc được hay không thực thi thuộc tính này, chẳng hạn như process_vm_readv().

Cờ nhân CONFIG_ARM64_UAO phải được đặt trong nhân thành đảm bảo rằng hạt nhân tuân thủ các trang miền người dùng được đánh dấu là chỉ thực thi. ARMv8 cũ hơn hoặc các thiết bị ARMv8.2 đã tắt tính năng Ghi đè quyền truy cập của người dùng (UAO) có thể không khai thác tối đa tính năng này và vẫn có thể đọc các trang chỉ thực thi bằng cách sử dụng gọi hệ thống.

Tái cấu trúc mã hiện có

Mã được chuyển từ AArch32 có thể chứa dữ liệu hỗn hợp và khiến phát sinh vấn đề. Trong nhiều trường hợp, việc khắc phục những vấn đề này rất đơn giản khi di chuyển các hằng số sang phần .data trong tệp tập hợp.

Cấu trúc viết tay có thể cần được tái cấu trúc để tách riêng các tập hợp được gộp cục bộ hằng số.

Ví dụ:

Tệp nhị phân do trình biên dịch Clang tạo ra sẽ không gặp vấn đề gì với dữ liệu được kết hợp trong mã. Nếu mã do bộ sưu tập trình biên dịch GNU (GCC) tạo là được đưa vào (từ một thư viện tĩnh), kiểm tra tệp nhị phân đầu ra để đảm bảo rằng các hằng số không được gộp vào các phần mã.

Nếu cần phải xem xét mã trên các phần mã có thể thực thi, đầu tiên, hãy gọi mprotect để đánh dấu mã có thể đọc được. Sau đó, sau thao tác đã hoàn tất, hãy gọi lại mprotect để đánh dấu là không đọc được.

Bật XOM

Chế độ chỉ thực thi được bật theo mặc định cho tất cả tệp nhị phân 64 bit trong bản dựng hệ thống.

Tắt XOM

Bạn có thể tắt chế độ chỉ thực thi ở cấp mô-đun, theo toàn bộ cây thư mục con, hoặc cho toàn bộ bản dựng.

Bạn có thể tắt XOM cho từng mô-đun riêng lẻ không tái cấu trúc được hoặc cần đọc các mô-đun đó mã thực thi bằng cách đặt giá trị LOCAL_XOMxom thành false.

// Android.mk
LOCAL_XOM := false

// Android.bp
cc_binary { // or other module types
   ...
   xom: false,
}

Nếu bộ nhớ chỉ thực thi bị tắt trong thư viện tĩnh, hệ thống xây dựng sẽ áp dụng cho tất cả các mô-đun phụ thuộc của thư viện tĩnh đó. Bạn có thể ghi đè điều này bằng cách sử dụng xom: true,.

Để vô hiệu hoá bộ nhớ chỉ thực thi trong một thư mục con cụ thể (ví dụ: foo/bar/), hãy chuyển giá trị đến XOM_EXCLUDE_PATHS.

make -j XOM_EXCLUDE_PATHS=foo/bar

Ngoài ra, bạn có thể đặt PRODUCT_XOM_EXCLUDE_PATHS trong cấu hình sản phẩm của bạn.

Bạn có thể vô hiệu hoá các tệp nhị phân chỉ thực thi trên toàn cục bằng cách truyền ENABLE_XOM=false vào lệnh make.

make -j ENABLE_XOM=false

Xác nhận kết quả

Không có chương trình kiểm thử xác minh hoặc CTS nào dành cho chỉ thực thi bộ nhớ. Bạn có thể xác minh tệp nhị phân theo cách thủ công bằng readelf và kiểm tra cờ phân đoạn.