Việc tràn số nguyên ngoài ý muốn có thể gây ra hỏng bộ nhớ hoặc lỗ hổng tiết lộ thông tin trong các biến liên quan đến truy cập bộ nhớ hoặc cấp phát bộ nhớ. Để chống lại điều này, chúng tôi đã thêm trình vệ sinh tràn số nguyên có dấu và không dấu của Clang UndefinedBehaviorSanitizer (UBSan) để làm cứng khung phương tiện trong Android 7.0. Trong Android 9, chúng tôi đã mở rộng UBSan để bao gồm nhiều thành phần hơn và cải thiện hỗ trợ hệ thống xây dựng cho nó.
Điều này được thiết kế để thêm các kiểm tra xung quanh các phép toán / hướng dẫn số học — có thể bị tràn — để hủy bỏ quy trình một cách an toàn nếu xảy ra tràn. Các chất khử trùng này có thể giảm thiểu toàn bộ lớp lỗi bộ nhớ và lỗ hổng tiết lộ thông tin trong đó nguyên nhân gốc rễ là do tràn số nguyên, chẳng hạn như lỗ hổng Stagefright ban đầu.
Ví dụ và nguồn
Integer Overflow Sanitization (IntSan) được cung cấp bởi trình biên dịch và thêm thiết bị vào hệ nhị phân trong thời gian biên dịch để phát hiện các lỗi tràn số học. Nó được bật theo mặc định trong các thành phần khác nhau trong toàn bộ nền tảng, ví dụ /platform/external/libnl/Android.bp
.
Thực hiện
IntSan sử dụng trình vệ sinh chống tràn số nguyên có dấu và không dấu của UBSan. Giảm thiểu này được kích hoạt ở cấp độ mỗi mô-đun. Nó giúp giữ an toàn cho các thành phần quan trọng của Android và không bị vô hiệu hóa.
Chúng tôi đặc biệt khuyến khích bạn bật Tính năng Vệ sinh Tràn Số nguyên cho các thành phần bổ sung. Các ứng cử viên lý tưởng là mã gốc đặc quyền hoặc mã gốc phân tích cú pháp đầu vào của người dùng không đáng tin cậy. Có một chi phí hiệu suất nhỏ liên quan đến trình vệ sinh phụ thuộc vào việc sử dụng mã và mức độ phổ biến của các phép toán số học. Mong đợi một tỷ lệ phần trăm chi phí nhỏ và kiểm tra xem hiệu suất có phải là vấn đề đáng lo ngại hay không.
Hỗ trợ IntSan trong makefiles
Để bật IntSan trong makefile, hãy thêm:
LOCAL_SANITIZE := integer_overflow # Optional features LOCAL_SANITIZE_DIAG := integer_overflow LOCAL_SANITIZE_BLACKLIST := modulename_blacklist.txt
-
LOCAL_SANITIZE
lấy một danh sách các chất khử trùng được phân tách bằng dấu phẩy, vớiinteger_overflow
là một tập hợp các tùy chọn được đóng gói sẵn cho các chất khử trùng tràn số nguyên có dấu và chưa ký riêng lẻ có danh sách đen mặc định . -
LOCAL_SANITIZE_DIAG
bật chế độ chẩn đoán cho chất khử trùng. Chỉ sử dụng chế độ chẩn đoán trong quá trình thử nghiệm vì chế độ này sẽ không bị hủy bỏ khi tràn, phủ nhận hoàn toàn lợi thế bảo mật của việc giảm thiểu. Xem phần Khắc phục sự cố để biết thêm chi tiết. -
LOCAL_SANITIZE_BLACKLIST
cho phép bạn chỉ định tệp danh sách đen để ngăn các chức năng và tệp nguồn bị khử trùng. Xem phần Khắc phục sự cố để biết thêm chi tiết.
Nếu bạn muốn kiểm soát chi tiết hơn, hãy bật các chất khử trùng riêng lẻ bằng cách sử dụng một hoặc cả hai cờ:
LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow
Hỗ trợ IntSan trong các tệp kế hoạch chi tiết
Để bật tính năng khử trùng tràn số nguyên trong tệp kế hoạch chi tiết, chẳng hạn như /platform/external/libnl/Android.bp
, hãy thêm:
sanitize: { integer_overflow: true, diag: { integer_overflow: true, }, blacklist: "modulename_blacklist.txt", },
Cũng giống như tạo tệp, thuộc tính integer_overflow
là một tập hợp các tùy chọn được đóng gói sẵn cho các trình vệ sinh tràn số nguyên có dấu và không dấu riêng lẻ có danh sách đen mặc định .
Tập hợp các thuộc tính diag
đoán bật chế độ chẩn đoán cho các chất khử trùng. Chỉ sử dụng chế độ chẩn đoán trong quá trình thử nghiệm. Chế độ chẩn đoán không bị hủy bỏ khi tràn, điều này hoàn toàn phủ nhận lợi thế bảo mật của việc giảm thiểu trong các bản dựng của người dùng. Xem phần Khắc phục sự cố để biết thêm chi tiết.
Thuộc tính blacklist
cho phép đặc tả tệp danh sách đen cho phép các nhà phát triển ngăn chặn các chức năng và tệp nguồn bị khử trùng. Xem phần Khắc phục sự cố để biết thêm chi tiết.
Để bật các chất khử trùng riêng lẻ, hãy sử dụng:
sanitize: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"], diag: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow",], }, blacklist: "modulename_blacklist.txt", },
Xử lý sự cố
Nếu bạn đang bật tính năng khử trùng tràn số nguyên trong các thành phần mới hoặc dựa vào các thư viện nền tảng đã làm vệ sinh tràn số nguyên, bạn có thể gặp phải một số vấn đề với lỗi tràn số nguyên lành tính gây ra hủy bỏ. Bạn nên kiểm tra các thành phần có bật tính năng khử trùng để đảm bảo có thể xuất hiện các vết tràn lành tính.
Để tìm, hủy bỏ do làm sạch trong bản dựng của người dùng, tìm kiếm sự cố SIGABRT
với thông báo Hủy bỏ cho biết tràn do UBSan bắt được, chẳng hạn như:
pid: ###, tid: ###, name: Binder:### >>> /system/bin/surfaceflinger <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: sub-overflow'
Dấu vết ngăn xếp nên bao gồm chức năng gây ra sự hủy bỏ, tuy nhiên, lỗi tràn xảy ra trong các hàm nội tuyến có thể không hiển thị trong dấu vết ngăn xếp.
Để dễ dàng xác định nguyên nhân gốc rễ hơn, hãy bật chẩn đoán trong thư viện để kích hoạt hủy bỏ và cố gắng tái tạo lỗi. Khi bật chẩn đoán, quá trình sẽ không bị hủy bỏ và thay vào đó sẽ tiếp tục chạy. Không hủy bỏ giúp tối đa hóa số lần tràn lành tính trong một đường dẫn thực thi cụ thể mà không cần phải biên dịch lại sau khi sửa mỗi lỗi. Chẩn đoán tạo ra một thông báo lỗi bao gồm số dòng và tệp nguồn gây ra việc hủy bỏ:
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Khi hoạt động số học có vấn đề được định vị, hãy đảm bảo rằng tràn là lành tính và đúng mục đích (ví dụ: không có ý nghĩa bảo mật). Bạn có thể giải quyết việc hủy bỏ chất khử trùng bằng cách:
- Cấu trúc lại mã để tránh tràn ( ví dụ )
- Tràn rõ ràng thông qua các hàm tràn __builtin _ * _ của Clang ( ví dụ )
- Tắt tính năng khử trùng trong hàm bằng cách chỉ định thuộc tính
no_sanitize
( ví dụ ) - Tắt tính năng làm sạch một hàm hoặc tệp nguồn qua tệp danh sách đen ( ví dụ )
Bạn nên sử dụng dung dịch dạng hạt nhất có thể. Ví dụ, một hàm lớn có nhiều phép toán số học và một phép toán tràn đơn lẻ nên có một phép toán duy nhất được cấu trúc lại thay vì toàn bộ hàm bị đưa vào danh sách đen.
Các mẫu phổ biến có thể dẫn đến tràn lành tính bao gồm:
- Truyền ngầm trong đó xảy ra tràn không dấu trước khi được truyền sang kiểu có dấu ( ví dụ )
- Xóa danh sách được liên kết làm giảm chỉ số vòng lặp khi xóa ( ví dụ )
- Gán một loại chưa được chỉ định cho -1 thay vì chỉ định giá trị tối đa thực tế ( ví dụ )
- Vòng lặp làm giảm một số nguyên không dấu trong điều kiện ( ví dụ , ví dụ )
Các nhà phát triển nên đảm bảo rằng các trường hợp mà chất vệ sinh phát hiện tràn rằng nó thực sự lành tính mà không có tác dụng phụ hoặc tác dụng bảo mật ngoài ý muốn trước khi tắt tính năng vệ sinh.
Tắt IntSan
Bạn có thể tắt IntSan bằng danh sách đen hoặc thuộc tính chức năng. Vô hiệu hóa một cách ít và chỉ khi cấu trúc lại mã không hợp lý hoặc nếu có vấn đề về chi phí hiệu suất.
Xem tài liệu Clang ngược dòng để biết thêm thông tin về cách tắt IntSan với các thuộc tính hàm và định dạng tệp danh sách đen . Danh sách đen nên được xác định đối với chất vệ sinh cụ thể bằng cách sử dụng tên phần chỉ định chất vệ sinh mục tiêu để tránh ảnh hưởng đến chất vệ sinh khác.
Thẩm định
Hiện tại, không có bài kiểm tra CTS nào dành riêng cho tính năng Làm sạch tràn số nguyên. Thay vào đó, hãy đảm bảo rằng các bài kiểm tra CTS vượt qua khi có hoặc không bật IntSan để xác minh rằng nó không ảnh hưởng đến thiết bị.