Bộ nhớ chỉ thực thi (XOM) cho nhị phân AArch64

Các phần mã có thể thực thi cho các tệp nhị phân của hệ thống AArch64 theo mặc định được đánh dấu là chỉ thực thi (không thể đọc được) như một biện pháp giảm thiểu tăng cường chống lại các cuộc tấn công tái sử dụng mã đúng lúc. Mã kết hợp dữ liệu và mã với nhau cũng như mã kiểm tra có mục đích các phần này (không ánh xạ lại các phân đoạn bộ nhớ trước để có thể đọc được) sẽ không còn hoạt động nữa. Các ứ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ố đọ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ớ mà không đánh dấu phần đó là có thể đọc được trước.

Để hưởng lợi đầy đủ từ việc giảm thiểu này, cần có sự hỗ trợ cả phần cứng và kernel. Nếu không có sự hỗ trợ này, việc giảm nhẹ chỉ có thể được thực thi một phần. Nhân chung của Android 4.9 chứa các bản vá thích hợp để cung cấp hỗ trợ đầy đủ cho điều này trên các thiết bị ARMv8.2.

Thực hiện

Các tệp nhị phân AArch64 do trình biên dịch tạo ra giả định rằng mã và dữ liệu không được trộn lẫn với nhau. 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 mã phải thực hiện việc xem xét nội bộ bộ nhớ có chủ ý trên các phân đoạn thực thi của nó, bạn nên gọi mprotect trên các phân đoạn mã cần kiểm tra để cho phép chúng có thể đọc được, sau đó loại bỏ khả năng đọc khi quá trình kiểm tra hoàn tất.
Việc triển khai này khiến việc đọc vào các phân đoạn bộ nhớ được đánh dấu là chỉ thực thi và 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 bị trộn lẫn với mã (gộp chung theo nghĩa đen) hoặc do cố ý xem xét nội bộ bộ nhớ.

Hỗ trợ và tác động của thiết bị

Các thiết bị có phần cứng cũ hơn hoặc hạt nhân cũ hơn (thấp hơn 4,9) không có các bản vá bắt buộc có thể không được hỗ trợ đầy đủ hoặc không được hưởng lợi từ tính năng này. Các thiết bị không hỗ trợ kernel 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ã kernel kiểm tra rõ ràng xem một trang có thể đọc được hay không vẫn có thể thực thi thuộc tính này, chẳng hạn như process_vm_readv() .

Cờ kernel CONFIG_ARM64_UAO phải được đặt trong kernel để đảm bảo rằng kernel tôn trọng các trang vùng người dùng được đánh dấu chỉ thực thi. Các thiết bị ARMv8 trước đó hoặc các thiết bị ARMv8.2 đã bị tắt Ghi đè truy cập người dùng (UAO) có thể không được hưởng lợi đầy đủ từ điều này và vẫn có thể đọc được các trang chỉ thực thi bằng cách sử dụng lệnh gọi chung.

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

Mã đã được chuyển từ AArch32 có thể chứa dữ liệu và mã trộn lẫn, gây ra sự cố. Trong nhiều trường hợp, việc khắc phục những sự cố này cũng đơn giản như việc di chuyển các hằng số sang phần .data trong tệp hợp ngữ.

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

Ví dụ:

Các 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 trộn lẫn trong mã. Nếu bao gồm mã được tạo bởi bộ sưu tập trình biên dịch GNU (GCC) (từ thư viện tĩnh), hãy kiểm tra tệp nhị phân đầu ra để đảm bảo rằng các hằng số chưa được gộp vào các phần mã.

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

Cho phép

Theo mặc định, chỉ thực thi được bật cho tất cả các tệp nhị phân 64 bit trong hệ thống xây dựng.

Vô hiệu hóa

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

XOM có thể bị vô hiệu hóa đối với các mô-đun riêng lẻ không thể cấu trúc lại hoặc cần đọc mã thực thi của chúng bằng cách đặt các biến 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 điều này 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, .

Để tắt 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ị cho XOM_EXCLUDE_PATHS .

make -j XOM_EXCLUDE_PATHS=foo/bar

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

Bạn có thể vô hiệu hóa các tệp nhị phân chỉ thực thi trên toàn cầu bằng cách chuyển ENABLE_XOM=false vào lệnh make của mình.

make -j ENABLE_XOM=false

Thẩm định

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