Kernel AddressSanitizer

Tương tự như các trình dọn dẹp dựa trên LLVM cho các thành phần không gian người dùng, Android bao gồm Kernel AddressSanitizer (KASan). KASan là sự kết hợp giữa các sửa đổi về thời gian biên dịch và nhân, dẫn đến một hệ thống được đo lường cho phép phát hiện lỗi và phân tích nguyên nhân gốc rễ một cách đơn giản hơn.

KASan có thể phát hiện nhiều loại lỗi vi phạm bộ nhớ trong nhân. Công cụ này cũng có thể phát hiện các hoạt động đọc và ghi ngoài phạm vi trên ngăn xếp, bộ nhớ khối xếp và các biến toàn cục, đồng thời có thể phát hiện các lỗi sử dụng sau khi giải phóng và giải phóng hai lần.

Tương tự như ASan, KASan sử dụng kết hợp giữa tính năng đo lường chức năng bộ nhớ tại thời gian biên dịch và bộ nhớ ảo để theo dõi các hoạt động truy cập bộ nhớ tại thời gian chạy. Trong KASan, 1/8 dung lượng bộ nhớ của nhân được dành riêng cho bộ nhớ ảo. Bộ nhớ này xác định xem một hoạt động truy cập bộ nhớ có hợp lệ hay không.

KASan được hỗ trợ trên các cấu trúc x86_64 và arm64. Đây là một phần của nhân nguồn mở kể từ phiên bản 4.0 và đã được chuyển ngược về các nhân dựa trên Android 3.18.

Ngoài KASan, kcov là một chế độ sửa đổi kernel khác hữu ích cho việc kiểm thử. kcov được phát triển để cho phép kiểm thử fuzz có hướng dẫn về mức độ phù hợp trong kernel. Công cụ này đo lường mức độ phù hợp về đầu vào syscall và hữu ích với các hệ thống kiểm thử ngẫu nhiên, chẳng hạn như syzkaller.

Triển khai

Để biên dịch một nhân có KASan và kcov đã bật, hãy thêm các cờ bản dựng sau vào cấu hình bản dựng nhân của bạn:

CONFIG_KASAN
CONFIG_KASAN_INLINE
CONFIG_TEST_KASAN
CONFIG_KCOV
CONFIG_SLUB
CONFIG_SLUB_DEBUG
CONFIG_CC_OPTIMIZE_FOR_SIZE

Và xoá những nội dung sau:

CONFIG_SLUB_DEBUG_ON
CONFIG_SLUB_DEBUG_PANIC_ON
CONFIG_KASAN_OUTLINE
CONFIG_KERNEL_LZ4

Sau đó, hãy tạo và nạp kernel như bình thường. Nhân KASan lớn hơn đáng kể so với nhân ban đầu. Nếu cần, hãy sửa đổi mọi thông số khởi động và chế độ cài đặt trình tải khởi động để cân nhắc điều này.

Sau khi flash kernel, hãy kiểm tra nhật ký khởi động kernel để xem KASan có được bật và đang chạy hay không. Nhân khởi động bằng thông tin về bản đồ bộ nhớ cho KASan, chẳng hạn như:

...
[    0.000000] c0      0 Virtual kernel memory layout:
[    0.000000] c0      0     kasan   : 0xffffff8000000000 - 0xffffff9000000000   (    64 GB)
[    0.000000] c0      0     vmalloc : 0xffffff9000010000 - 0xffffffbdbfff0000   (   182 GB)
[    0.000000] c0      0     vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000   (     8 GB maximum)
[    0.000000] c0      0               0xffffffbdc0000000 - 0xffffffbdc3f95400   (    63 MB actual)
[    0.000000] c0      0     PCI I/O : 0xffffffbffa000000 - 0xffffffbffb000000   (    16 MB)
[    0.000000] c0      0     fixed   : 0xffffffbffbdfd000 - 0xffffffbffbdff000   (     8 KB)
[    0.000000] c0      0     modules : 0xffffffbffc000000 - 0xffffffc000000000   (    64 MB)
[    0.000000] c0      0     memory  : 0xffffffc000000000 - 0xffffffc0fe550000   (  4069 MB)
[    0.000000] c0      0       .init : 0xffffffc001d33000 - 0xffffffc001dce000   (   620 KB)
[    0.000000] c0      0       .text : 0xffffffc000080000 - 0xffffffc001d32284   ( 29385 KB)
...

Và đây là hình ảnh minh hoạ về lỗi:

[   18.539668] c3      1 ==================================================================
[   18.547662] c3      1 BUG: KASAN: null-ptr-deref on address 0000000000000008
[   18.554689] c3      1 Read of size 8 by task swapper/0/1
[   18.559988] c3      1 CPU: 3 PID: 1 Comm: swapper/0 Tainted: G        W      3.18.24-xxx #1
[   18.569275] c3      1 Hardware name: Android Device
[   18.577433] c3      1 Call trace:
[   18.580739] c3      1 [<ffffffc00008b32c>] dump_backtrace+0x0/0x2c4
[   18.586985] c3      1 [<ffffffc00008b600>] show_stack+0x10/0x1c
[   18.592889] c3      1 [<ffffffc001481194>] dump_stack+0x74/0xc8
[   18.598792] c3      1 [<ffffffc000202ee0>] kasan_report+0x11c/0x4d0
[   18.605038] c3      1 [<ffffffc00020286c>] __asan_load8+0x20/0x80
[   18.611115] c3      1 [<ffffffc000bdefe8>] android_verity_ctr+0x8cc/0x1024
[   18.617976] c3      1 [<ffffffc000bcaa2c>] dm_table_add_target+0x3dc/0x50c
[   18.624832] c3      1 [<ffffffc001bdbe60>] dm_run_setup+0x50c/0x678
[   18.631082] c3      1 [<ffffffc001bda8c0>] prepare_namespace+0x44/0x1ac
[   18.637676] c3      1 [<ffffffc001bda170>] kernel_init_freeable+0x328/0x364
[   18.644625] c3      1 [<ffffffc001478e20>] kernel_init+0x10/0xd8
[   18.650613] c3      1 ==================================================================

Ngoài ra, nếu các mô-đun được bật trong nhân, bạn có thể tải mô-đun nhân test_kasan để kiểm thử thêm. Mô-đun này cố gắng truy cập vào bộ nhớ ngoài phạm vi và sử dụng sau khi giải phóng, đồng thời hữu ích trong việc đảm bảo bạn đã bật KASan đúng cách trên một thiết bị mục tiêu.