精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

內存檢測工具KASAN:精準定位內存越界的“幽靈”

開發 開發工具
直到 KASAN(Kernel Address Sanitizer,內核地址清理器)的出現,為這一難題帶來了曙光。它憑借強大的功能和獨特的機制,成為精準定位內存越界 “幽靈” 的得力武器。那么,KASAN 究竟是如何做到在復雜的內核環境中,敏銳地捕捉到內存越界錯誤,并將其精準定位的呢?接下來,讓我們一同深入探尋 KASAN 的奧秘。

在Linux 內核這片廣袤而復雜的 “代碼叢林” 中,內存管理無疑是最為關鍵且棘手的領域之一。內存越界錯誤,就像隱匿其中的 “幽靈”,神出鬼沒,難以捉摸。它可能在系統運行的任何時刻悄然現身,一個不經意間,就可能引發系統崩潰、數據損壞等嚴重后果,令無數開發人員和運維工程師頭疼不已。

以往,開發人員面對內存越界錯誤時,常常陷入困境。傳統的檢測手段猶如在黑暗中摸索,效率低下且準確性欠佳。例如,一些簡單的內存檢測工具,雖能發現部分明顯的錯誤,但對于那些隱藏在復雜代碼邏輯深處、間歇性出現的內存越界問題,往往無能為力。而人工排查,不僅耗費大量時間和精力,還極易遺漏關鍵線索。

直到 KASAN(Kernel Address Sanitizer,內核地址清理器)的出現,為這一難題帶來了曙光。它憑借強大的功能和獨特的機制,成為精準定位內存越界 “幽靈” 的得力武器。那么,KASAN 究竟是如何做到在復雜的內核環境中,敏銳地捕捉到內存越界錯誤,并將其精準定位的呢?接下來,讓我們一同深入探尋 KASAN 的奧秘。

一、KASAN概述

KASAN,即 Kernel Address Sanitizer,是 Linux內核中用于檢測內存錯誤的重要工具。它如同一位嚴謹的 “內存管家”,時刻監督著內核內存的使用情況,主要負責檢查內存越界訪問和使用已釋放的內存等問題。

內存越界訪問,就像是你在自己的房子里隨意擴建,超出了原本合法的土地邊界;而使用已釋放的內存,則類似于你把房子賣了之后,還想著回去住。這些錯誤在程序運行中可能會導致難以預測的后果,如程序崩潰、數據損壞,甚至可能引發安全漏洞,讓惡意攻擊者有機可乘。

在 Linux 內核開發的龐大體系中,KASAN 占據著舉足輕重的地位。隨著內核代碼的不斷增長和功能的日益復雜,內存管理變得愈發困難,內存錯誤也更容易隱藏其中。KASAN 的出現,為內核開發者提供了一雙 “火眼金睛”,能夠快速、準確地發現這些內存錯誤,大大提高了內核的穩定性和安全性。它就像是在黑暗中為開發者照亮前行道路的明燈,讓他們在復雜的內核代碼中能夠及時發現并修復內存問題,保障整個 Linux 系統的穩定運行。

二、KASAN的強大功能

KASAN 之所以能在 Linux 內核開發中備受青睞,源于其強大且實用的功能,特別是在內存越界檢測、釋放后使用檢測以及未初始化內存檢測等方面表現卓越。

2.1內存越界檢測

內存越界是內核開發中常見的 “陷阱”。當程序訪問的內存地址超出了已分配內存塊的邊界,就會發生內存越界,這可能導致數據被破壞,甚至引發系統崩潰。KASAN 利用 “影子內存” 技術來實現對內存越界的精準檢測。它為每 8 字節的內存分配 1 字節的影子內存,通過影子內存中的標記來記錄對應內存區域的訪問權限。當程序嘗試訪問內存時,KASAN 會檢查影子內存中的標記,判斷該訪問是否合法。

舉個例子,在一個網絡驅動程序中,假設需要接收網絡數據包并存儲到已分配的內存緩沖區中。如果代碼中對數據包長度的檢查不嚴格,就可能導致寫入操作超出緩沖區的邊界,從而引發內存越界。使用 KASAN 后,一旦發生這種情況,它會立即捕獲到異常,并輸出詳細的錯誤信息,包括越界的地址、訪問的大小以及相關的調用棧信息。這使得開發者能夠快速定位到問題代碼所在,及時進行修復。就好像在一個倉庫中,KASAN 為每個存儲區域都設置了明確的邊界標識,一旦有人試圖超出邊界存放物品,它就能馬上發出警報。

2.2釋放后使用檢測

釋放后使用錯誤也是內存管理中的一大 “頑疾”。當內存塊被釋放后,程序卻仍然嘗試訪問它,這就如同使用已經歸還的物品一樣,會導致不可預測的后果。KASAN 通過維護內存的分配和釋放狀態來檢測這類錯誤。當內存被釋放時,KASAN 會將其對應的影子內存標記為不可訪問狀態。如果程序后續嘗試訪問已釋放的內存,KASAN 便能及時發現并報告錯誤。

例如,在一個設備驅動程序中,當設備關閉時,相關的內存資源會被釋放。但如果在釋放后,代碼中還有部分邏輯試圖訪問這些已釋放的內存,KASAN 就能敏銳地察覺到這個問題,并提供詳細的錯誤報告,幫助開發者找出錯誤的根源。這一功能極大地提高了系統的穩定性,避免了因釋放后使用錯誤而導致的系統崩潰或數據丟失問題,就像一個嚴謹的管家,時刻確保歸還的物品不會被再次使用。

2.3未初始化內存檢測

未初始化內存的使用同樣會給程序帶來潛在風險。當程序使用未初始化的內存時,可能會讀取到隨機值,從而導致程序行為異常。KASAN 通過特殊的機制來檢測這類問題。它會在內存分配時對其進行初始化標記,當程序訪問內存時,KASAN 會檢查該內存是否已經被正確初始化。

比如,在一個文件系統驅動程序中,如果在讀取文件數據時,使用了未初始化的緩沖區來存儲數據,KASAN 就能夠檢測到這一錯誤,并給出相應的提示。通過這種方式,開發者可以及時發現并解決未初始化內存的使用問題,確保程序的正確性和穩定性,如同為程序的內存使用加上了一把 “安全鎖”,防止因未初始化內存而引發的各種問題。

三、KASAN的工作原理

Kasan 的原理是利用“額外”的內存來標記那些可以被使用的內存的狀態。這些做標記的區域被稱為影子區域(shadow region)。了解 Linux 內存管理的讀者知道,內存中的每個物理頁在內存中都會有一個 struct page 這樣的結構體來表示,即每 4KB 的頁需要 40B 的結構體,大約 1% 的內存用來表示內存本身。Kasan 與其類似但“浪費”更為嚴重,影子區域的比例是 1:8,即總內存的九分之一會被“浪費”。用官方文檔中的例子,如果有 128TB 的可用內存,需要有額外 16TB 的內存用來做標記。

做標記的方法比較簡單,將可用內存按照 8 子節的大小分組,如果每組中所有 8 個字節都可以訪問,則影子內存中相應的地方用全零(0x00)表示;如果可用內存的前 N(1 到 7 范圍之間)個字節可用,則影子內存中響應的位置用 N 表示;其它情況影子內存用負數表示該內存不可用。

填充值定義:

#define KASAN_FREE_PAGE         0xFF  /* page was freed */
 #define KASAN_PAGE_REDZONE      0xFE  /* redzone for kmalloc_large allocations */
 #define KASAN_KMALLOC_REDZONE   0xFC  /* redzone inside slub object */
 #define KASAN_KMALLOC_FREE      0xFB  /* object was freed (kmem_cache_free/kfree) */
 #define KASAN_GLOBAL_REDZONE    0xFA  /* redzone for global variable */

內核配置選項:

CONFIG_HAVE_ARCH_KASAN=y
CONFIG_KASAN=y

3.1影子內存機制

KASAN的核心技術之一是影子內存(Shadow Memory)機制。影子內存就像是實際內存的 “影子分身”,它與實際內存存在著緊密的對應關系。具體來說,KASAN 會為每 8 字節的實際內存分配1字節的影子內存。這 1 字節的影子內存就像是一個 “小賬本”,用來記錄對應的 8 字節實際內存的訪問權限和狀態信息 。

當實際內存中的某個區域被分配使用時,對應的影子內存會被標記為特定的值,表示該區域是可訪問的。比如,如果 8 字節的實際內存都可以正常訪問,那么對應的影子內存值就會被設置為 0x00。相反,如果實際內存中的某個區域已經被釋放或者是非法訪問區域,影子內存會被標記為其他特定的值,如 0xFC 表示這是一個紅區(Redzone),0xFB 表示該內存已經被釋放。通過這種方式,KASAN 在程序運行過程中,每當進行內存訪問操作時,都會先查看影子內存的標記,以此來判斷此次內存訪問是否合法。

3.2紅區(Redzone)的作用

紅區是 KASAN 內存管理中的一個重要概念。在內存分配時,紅區會被放置在已分配內存塊的邊界之外,它就像是在內存區域周圍設置的一圈 “警戒線”。

當程序申請內存時,內核會在分配的內存塊前后額外劃出一些空間作為紅區。這些紅區在正常情況下是不應該被程序訪問到的。如果程序不小心訪問到了紅區,就說明可能發生了內存越界的情況。例如,當一個程序申請了一塊大小為 100 字節的內存,內核可能會在這 100 字節的前后各劃出幾個字節作為紅區。假設紅區大小為 4 字節,那么實際分配的內存空間就變成了 108 字節,而程序只能合法訪問中間的 100 字節。如果程序試圖訪問第 101 字節到第 104 字節,或者第 0 字節到第 - 4 字節(在內存地址上表現為低地址方向),就會觸發 KASAN 的檢測機制,因為這些區域屬于紅區。

紅區的存在大大提高了 KASAN 檢測內存越界錯誤的能力,它就像一個敏感的 “報警器”,一旦被觸發,就能及時發現內存訪問異常,幫助開發者快速定位問題。

3.3檢測流程詳解

KASAN 的檢測流程是一個嚴謹而高效的過程,它貫穿于程序運行的每一個內存訪問操作中。

當程序執行內存訪問指令時,無論是讀取數據(load)還是寫入數據(store),編譯器都會自動在指令前后插入 KASAN 的檢測代碼。這些檢測代碼首先會根據訪問的內存地址計算出對應的影子內存地址。由于影子內存與實際內存是按照 8:1 的比例映射,所以計算過程就是將實際內存地址右移 3 位(因為 2^3 = 8),再加上一個固定的偏移量,從而得到影子內存地址。

接著,檢測代碼會讀取影子內存中對應位置的值。根據這個值,檢測代碼判斷當前的內存訪問是否合法。如果影子內存的值表明該內存區域是可訪問的,程序會繼續正常執行內存訪問操作;但如果影子內存的值顯示該區域不可訪問,例如是紅區標記或者已釋放內存的標記,KASAN 就會立即捕獲這個錯誤,并生成詳細的錯誤報告。

錯誤報告中會包含豐富的信息,如發生錯誤的內存地址、訪問的類型(讀或寫)、訪問的大小以及相關的調用棧信息。調用棧信息就像是一個 “錯誤路徑導航圖”,它展示了從程序入口開始到發生錯誤時的函數調用順序,開發者可以根據這些信息快速定位到出錯的代碼位置,進而進行修復。

四、如何使用KASAN?

4.1編譯內核啟用 KASAN

要使用 KASAN,首先需要在編譯內核時啟用它。這一過程需要一些特定的配置選項和命令。

①準備編譯環境:確保系統中安裝了必要的編譯工具,如 GCC、make、flex、bison 等。如果是在 Ubuntu 系統中,可以使用以下命令安裝:

sudo apt-get update
sudo apt-get install build-essential libncurses-dev bison flex libssl-dev libelf-dev

②獲取內核源碼:從官方 Linux 內核網站(https://www.kernel.org/ )下載所需版本的內核源碼,然后解壓到指定目錄。例如,下載并解壓 Linux 5.10 內核源碼:

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.tar.xz
tar -xf linux-5.10.tar.xz
cd linux-5.10

③配置內核選項:進入內核源碼目錄后,執行以下命令進入內核配置界面:

make menuconfig

在配置界面中,找到 “Kernel Hacking” -> “Memory Debugging”,然后啟用 “Kernel Address Sanitizer (KASAN)” 選項。此外,還可以根據需求選擇 “KASAN: Inline Allocation”(CONFIG_KASAN_INLINE)選項,它能提供更高效的檢測性能,但可能會增加內核二進制文件的大小;或者選擇 “KASAN: Outlined Allocation”(CONFIG_KASAN_OUTLINE)選項,它生成的二進制文件較小,但檢測速度相對較慢 。

④ 編譯內核:完成配置后,退出配置界面并執行編譯命令。為了加快編譯速度,可以利用多核處理器并行編譯,命令如下:

make -j$(nproc)

這里$(nproc)會自動獲取系統的 CPU 核心數,從而確定并行編譯的任務數。

⑤ 安裝內核:編譯完成后,安裝新編譯的內核和內核模塊:

sudo make modules_install
sudo make install

安裝完成后,重啟系統,新的內核就會生效,此時 KASAN 已經被成功啟用。

4.2運行時檢測與錯誤報告

當系統運行在啟用了 KASAN 的內核上時,KASAN 會自動檢測內存錯誤。一旦檢測到錯誤,它會生成詳細的錯誤報告。

  • 錯誤檢測:KASAN 在程序運行過程中,對每一次內存訪問進行檢查。當發現內存越界訪問、使用已釋放內存等錯誤時,KASAN 會立即捕獲到這些異常。
  • 查看錯誤報告:KASAN 將錯誤信息輸出到系統日志中,通常可以通過dmesg命令查看。例如,執行以下命令查看最近的系統日志:
dmesg | grep -i kasan

這個命令會過濾出包含 “kasan” 關鍵字的日志信息,這些信息就是 KASAN 生成的錯誤報告。

  • 分析錯誤報告:錯誤報告中包含了豐富的信息,如錯誤類型、發生錯誤的內存地址、訪問的大小、相關的調用棧信息等。

以一個內存越界的錯誤報告為例:

BUG: KASAN: slab-out-of-bounds in some_function+0x58/0x88 at addr ffffffdabc0a2a96
Write of size 1 by task some_task/1234
CPU: 3 PID: 1234 Comm: some_task Tainted: G        W  O    4.19.0-10-amd64 #1
Hardware name: Some Hardware (DT)
Call trace:
 [<ffffffffc088b4e8>] dump_backtrace+0x0/0x358
 [<ffffffffc088b8dc>] show_stack+0x14/0x20
 [<ffffffffc0cde118>] dump_stack+0xa8/0xd0
 [<ffffffffc06933c4>] kasan_object_err+0x24/0x80
 [<ffffffffc0693654>] kasan_report.part.1+0x1dc/0x498
 [<ffffffffc0693b98>] qlist_move_cache+0x0/0xc0
 [<ffffffffc0691fe4>] __asan_store1+0x4c/0x58
 [<ffffffffc0ec13a8>] some_function+0x58/0x88

從這個報告中,可以得知錯誤類型是 “slab-out-of-bounds”(內存越界),發生錯誤的函數是 “some_function”,錯誤發生的地址是 “fffffdabc0a2a96”,寫入的大小是 1 字節,以及詳細的調用棧信息。通過分析這些信息,開發者可以快速定位到出錯的代碼位置,進而進行修復。

五、KASAN實例源碼分析

KASAN實例分析,在內存訪問中有很多種錯誤類型:

  • 越界訪問(out-of-bounds)。
  • 訪問已經釋放的內存(use-after-free)。
  • 重復釋放。(double-free)。

5.1越界訪問(out-of-bounds)

實例源碼(實例包括):

  • kmalloc_oob_right:右側數組越界訪問。
  • kmalloc_oob_left:左側數組越界訪問。
  • kmalloc_node_oob_right:右側節點越界訪問。
  • kmalloc_pagealloc_oob_right:右側頁越界訪問。
  • kmalloc_large_oob_right:右側kmalloc最大分配越界訪問。
  • kmalloc_oob_krealloc_more:krealloc擴大后越界訪問。
  • kmalloc_oob_krealloc_less:krealloc縮小后越界訪問。
  • kmalloc_oob_16:申請小于賦值內存塊導致越界訪問。
  • kmalloc_oob_memset_2:memset越界訪問。
  • kmalloc_oob_memset_4:memset越界訪問。
  • kmalloc_oob_memset_8:memset越界訪問。
  • kmalloc_oob_memset_16:memset越界訪問。
  • kmalloc_oob_in_memset:memset越界訪問。
  • kmem_cache_oob:其他cache域賦值導致越界訪問。
  • kasan_global_oob:全局變量越界訪問。
  • kasan_stack_oob:堆棧越界訪問。
  • ksize_unpoisons_memory:ksize后右側越界訪問。
  • copy_user_test:內核態與用戶態傳遞類越界訪問。
  • kasan_alloca_oob_left:左側alloca越界訪問。
  • kasan_alloca_oob_right:右側alloca越界訪問。
#define pr_fmt(fmt) "kasan test: %s " fmt, __func__

#include <linux/kernel.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/kasan.h>

static noinline void __init kmalloc_oob_right(void)
{
        char *ptr;
        size_t size = 123;

        pr_info("out-of-bounds to right\n");
        ptr = kmalloc(size, GFP_KERNEL);
        if (!ptr) {
                pr_err("Allocation failed\n");
                return;
        }

        ptr[size] = 'x';
        kfree(ptr);
}

static noinline void __init kmalloc_oob_left(void)
{
        char *ptr;
        size_t size = 15;

        pr_info("out-of-bounds to left\n");
        ptr = kmalloc(size, GFP_KERNEL);
        if (!ptr) {
                pr_err("Allocation failed\n");
                return;
        }

        *ptr = *(ptr - 1);
        kfree(ptr);
}

static noinline void __init kmalloc_node_oob_right(void)
{
        char *ptr;
        size_t size = 4096;

        pr_info("kmalloc_node(): out-of-bounds to right\n");
        ptr = kmalloc_node(size, GFP_KERNEL, 0);
        if (!ptr) {
                pr_err("Allocation failed\n");
                return;
        }

        ptr[size] = 0;
        kfree(ptr);
}

#ifdef CONFIG_SLUB
static noinline void __init kmalloc_pagealloc_oob_right(void)
{
        char *ptr;
        size_t size = KMALLOC_MAX_CACHE_SIZE + 10;

        /* Allocate a chunk that does not fit into a SLUB cache to trigger
         * the page allocator fallback.
         */
        pr_info("kmalloc pagealloc allocation: out-of-bounds to right\n");
        ptr = kmalloc(size, GFP_KERNEL);
        if (!ptr) {
                pr_err("Allocation failed\n");
                return;
        }

        ptr[size] = 0;
        kfree(ptr);
}
#endif

static noinline void __init kmalloc_large_oob_right(void)
{
        char *ptr;
        size_t size = KMALLOC_MAX_CACHE_SIZE - 256;
        /* Allocate a chunk that is large enough, but still fits into a slab
         * and does not trigger the page allocator fallback in SLUB.
         */
        pr_info("kmalloc large allocation: out-of-bounds to right\n");
        ptr = kmalloc(size, GFP_KERNEL);
        if (!ptr) {
                pr_err("Allocation failed\n");
                return;
        }

        ptr[size] = 0;
        kfree(ptr);
}

static noinline void __init kmalloc_oob_krealloc_more(void)
{
        char *ptr1, *ptr2;
        size_t size1 = 17;
        size_t size2 = 19;

        pr_info("out-of-bounds after krealloc more\n");
        ptr1 = kmalloc(size1, GFP_KERNEL);
        ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
        if (!ptr1 || !ptr2) {
                pr_err("Allocation failed\n");
                kfree(ptr1);
                return;
        }

        ptr2[size2] = 'x';
        kfree(ptr2);
}

static noinline void __init kmalloc_oob_krealloc_less(void)
{
        char *ptr1, *ptr2;
        size_t size1 = 17;
        size_t size2 = 15;

        pr_info("out-of-bounds after krealloc less\n");
        ptr1 = kmalloc(size1, GFP_KERNEL);
        ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
        if (!ptr1 || !ptr2) {
                pr_err("Allocation failed\n");
                kfree(ptr1);
                return;
        }
        ptr2[size2] = 'x';
        kfree(ptr2);
}

static noinline void __init kmalloc_oob_16(void)
{
        struct {
                u64 words[2];
        } *ptr1, *ptr2;

        pr_info("kmalloc out-of-bounds for 16-bytes access\n");
        ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
        ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
        if (!ptr1 || !ptr2) {
                pr_err("Allocation failed\n");
                kfree(ptr1);
                kfree(ptr2);
                return;
        }
        *ptr1 = *ptr2;
        kfree(ptr1);
        kfree(ptr2);
}

static noinline void __init kmalloc_oob_memset_2(void)
{
        char *ptr;
        size_t size = 8;

        pr_info("out-of-bounds in memset2\n");
        ptr = kmalloc(size, GFP_KERNEL);
        if (!ptr) {
                pr_err("Allocation failed\n");
                return;
        }

        memset(ptr+7, 0, 2);
        kfree(ptr);
}

static noinline void __init kmalloc_oob_memset_4(void)
{
        char *ptr;
        size_t size = 8;

        pr_info("out-of-bounds in memset4\n");
        ptr = kmalloc(size, GFP_KERNEL);
        if (!ptr) {
                pr_err("Allocation failed\n");
                return;
        }

        memset(ptr+5, 0, 4);
        kfree(ptr);
}


static noinline void __init kmalloc_oob_memset_8(void)
{
        char *ptr;
        size_t size = 8;

        pr_info("out-of-bounds in memset8\n");
        ptr = kmalloc(size, GFP_KERNEL);
        if (!ptr) {
                pr_err("Allocation failed\n");
                return;
        }

        memset(ptr+1, 0, 8);
        kfree(ptr);
}

static noinline void __init kmalloc_oob_memset_16(void)
{
        char *ptr;
        size_t size = 16;

        pr_info("out-of-bounds in memset16\n");
        ptr = kmalloc(size, GFP_KERNEL);
        if (!ptr) {
                pr_err("Allocation failed\n");
                return;
        }

        memset(ptr+1, 0, 16);
        kfree(ptr);
}

static noinline void __init kmalloc_oob_in_memset(void)
{
        char *ptr;
        size_t size = 666;

        pr_info("out-of-bounds in memset\n");
        ptr = kmalloc(size, GFP_KERNEL);
        if (!ptr) {
                pr_err("Allocation failed\n");
                return;
        }

        memset(ptr, 0, size+5);
        kfree(ptr);
}


static int __init kmalloc_tests_init(void)
{
        /*
         * Temporarily enable multi-shot mode. Otherwise, we'd only get a
         * report for the first case.
         */
        bool multishot = kasan_save_enable_multi_shot();

        kmalloc_oob_right();
        kmalloc_oob_left();
        kmalloc_node_oob_right();
#ifdef CONFIG_SLUB
        kmalloc_pagealloc_oob_right();
#endif
        kmalloc_large_oob_right();
        kmalloc_oob_krealloc_more();
        kmalloc_oob_krealloc_less();
        kmalloc_oob_16();
        kmalloc_oob_in_memset();
        kmalloc_oob_memset_2();
        kmalloc_oob_memset_4();
        kmalloc_oob_memset_8();
        kmalloc_oob_memset_16();
        kasan_restore_multi_shot(multishot);
		return -EAGAIN;
}
module_init(kmalloc_tests_init);
MODULE_LICENSE("GPL");

5.2訪問已經釋放的內存(use-after-free)

實例源碼(實例包括)

  • kmalloc_uaf:向釋放已內存賦值。
  • kmalloc_uaf_memset:用memset向釋放已內存賦值。
  • kmalloc_uaf2:向釋放已內存賦值。
#define pr_fmt(fmt) "kasan test: %s " fmt, __func__

#include <linux/kernel.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/kasan.h>

static noinline void __init kmalloc_uaf(void)
{
	char *ptr;
	size_t size = 10;

	pr_info("use-after-free\n");
	ptr = kmalloc(size, GFP_KERNEL);
	if (!ptr) {
		pr_err("Allocation failed\n");
		return;
	}

	kfree(ptr);
	*(ptr + 8) = 'x';
}

static noinline void __init kmalloc_uaf_memset(void)
{
	char *ptr;
	size_t size = 33;

	pr_info("use-after-free in memset\n");
	ptr = kmalloc(size, GFP_KERNEL);
	if (!ptr) {
		pr_err("Allocation failed\n");
		return;
	}

	kfree(ptr);
	memset(ptr, 0, size);
}

static noinline void __init kmalloc_uaf2(void)
{
	char *ptr1, *ptr2;
	size_t size = 43;

	pr_info("use-after-free after another kmalloc\n");
	ptr1 = kmalloc(size, GFP_KERNEL);
	if (!ptr1) {
		pr_err("Allocation failed\n");
		return;
	}

	kfree(ptr1);
	ptr2 = kmalloc(size, GFP_KERNEL);
	if (!ptr2) {
		pr_err("Allocation failed\n");
		return;
	}

	ptr1[40] = 'x';
	if (ptr1 == ptr2)
		pr_err("Could not detect use-after-free: ptr1 == ptr2\n");
	kfree(ptr2);
}
static int __init kmalloc_tests_init(void)
{
	/*
	 * Temporarily enable multi-shot mode. Otherwise, we'd only get a
	 * report for the first case.
	 */
	bool multishot = kasan_save_enable_multi_shot();
	kmalloc_uaf();
	kmalloc_uaf_memset();
	kmalloc_uaf2();
	kasan_restore_multi_shot(multishot);

	return -EAGAIN;
}

module_init(kmalloc_tests_init);
MODULE_LICENSE("GPL");

輸出log

/ # insmod lib/modules/4.9.191/test_kasan.ko
[  110.109605] kasan test: kmalloc_uaf use-after-free
[  110.124350] ==================================================================
[  110.132481] BUG: KASAN: use-after-free in kmalloc_uaf+0x84/0xb8 [test_kasan]
[  110.140365] Write of size 1 at addr ffffffc0336d9208 by task insmod/1204
[  110.147856]
[  110.149540] CPU: 0 PID: 1204 Comm: insmod Tainted: G    B           4.9.191 #4
[  110.157613] Hardware name: sun50iw10 (DT)
[  110.162098] Call trace:
[  110.164853] [<ffffff900808ba74>] dump_backtrace+0x0/0x318
[  110.170900] [<ffffff900808bda0>] show_stack+0x14/0x1c
[  110.176563] [<ffffff90083ae758>] dump_stack+0xb0/0xe8
[  110.182225] [<ffffff90081f7ad4>] print_address_description+0x60/0x228
[  110.189436] [<ffffff90081f8140>] kasan_report+0x250/0x27c
[  110.195485] [<ffffff90081f695c>] __asan_store1+0x44/0x4c
[  110.201473] [<ffffff90007b87d4>] kmalloc_uaf+0x84/0xb8 [test_kasan]
[  110.208528] [<ffffff90007b955c>] kmalloc_tests_init+0x4c/0x90 [test_kasan]
[  110.216227] [<ffffff9008083a8c>] do_one_initcall+0xe4/0x1b0
[  110.222471] [<ffffff9008190ce4>] do_init_module+0xf0/0x2ac
[  110.228615] [<ffffff900815bd40>] load_module+0x2690/0x2dcc
[  110.234762] [<ffffff900815c614>] SyS_init_module+0x198/0x224
[  110.241095] [<ffffff9008083200>] el0_svc_naked+0x34/0x38
[  110.247032]
[  110.248704] Allocated by task 1204:
[  110.252619]  save_stack_trace_tsk+0x0/0x1f4
[  110.257307]  save_stack_trace+0x18/0x20
[  110.261607]  kasan_kmalloc.part.1+0x44/0xec
[  110.266295]  kasan_kmalloc+0x88/0x9c
[  110.270338]  kmalloc_uaf+0x60/0xb8 [test_kasan]
[  110.275450]  kmalloc_tests_init+0x4c/0x90 [test_kasan]
[  110.281204]  do_one_initcall+0xe4/0x1b0
[  110.285504]  do_init_module+0xf0/0x2ac
[  110.289701]  load_module+0x2690/0x2dcc
[  110.293902]  SyS_init_module+0x198/0x224
[  110.298294]  el0_svc_naked+0x34/0x38
[  110.302293]
[  110.303962] Freed by task 1204:
[  110.307486]  save_stack_trace_tsk+0x0/0x1f4
[  110.312173]  save_stack_trace+0x18/0x20
[  110.316470]  kasan_slab_free+0x90/0x15c
[  110.320767]  kfree+0xc8/0x258
[  110.324133]  kmalloc_uaf+0x7c/0xb8 [test_kasan]
[  110.329245]  kmalloc_tests_init+0x4c/0x90 [test_kasan]
[  110.334999]  do_one_initcall+0xe4/0x1b0
[  110.339304]  do_init_module+0xf0/0x2ac
[  110.343503]  load_module+0x2690/0x2dcc
[  110.347702]  SyS_init_module+0x198/0x224
[  110.352098]  el0_svc_naked+0x34/0x38
[  110.356096]
[  110.357773] The buggy address belongs to the object at ffffffc0336d9200
[  110.357773]  which belongs to the cache kmalloc-128 of size 128
[  110.371780] The buggy address is located 8 bytes inside of
[  110.371780]  128-byte region [ffffffc0336d9200, ffffffc0336d9280)
[  110.384708] The buggy address belongs to the page:
[  110.390073] page:ffffffbf00cdb600 count:1 mapcount:0 mapping:          (null) index:0xffffffc0336dab00 compound_mapcount: 0
[  110.402539] flags: 0x10200(slab|head)
[  110.406635] page dumped because: kasan: bad access detected
[  110.412860]
[  110.414530] Memory state around the buggy address:
[  110.419901]  ffffffc0336d9100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  110.427984]  ffffffc0336d9180: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  110.436064] >ffffffc0336d9200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  110.444138]                       ^
[  110.448045]  ffffffc0336d9280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  110.456125]  ffffffc0336d9300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  110.464202] ==================================================================
[  110.489110] kasan test: kmalloc_uaf_memset use-after-free in memset
[  110.496258] ==================================================================
[  110.504390] BUG: KASAN: use-after-free in kmalloc_uaf_memset+0x8c/0xb8 [test_kasan]
[  110.512953] Write of size 33 at addr ffffffc0336dab00 by task insmod/1204
[  110.520540]
[  110.522221] CPU: 0 PID: 1204 Comm: insmod Tainted: G    B           4.9.191 #4
[  110.530298] Hardware name: sun50iw10 (DT)
[  110.534783] Call trace:
[  110.537541] [<ffffff900808ba74>] dump_backtrace+0x0/0x318
[  110.543590] [<ffffff900808bda0>] show_stack+0x14/0x1c
[  110.549252] [<ffffff90083ae758>] dump_stack+0xb0/0xe8
[  110.554917] [<ffffff90081f7ad4>] print_address_description+0x60/0x228
[  110.562131] [<ffffff90081f8140>] kasan_report+0x250/0x27c
[  110.568182] [<ffffff90081f6d8c>] check_memory_region+0x20/0x144
[  110.574812] [<ffffff90081f72f0>] memset+0x2c/0x4c
[  110.580118] [<ffffff90007b8ef4>] kmalloc_uaf_memset+0x8c/0xb8 [test_kasan]
[  110.587853] [<ffffff90007b9560>] kmalloc_tests_init+0x50/0x90 [test_kasan]
[  110.595550] [<ffffff9008083a8c>] do_one_initcall+0xe4/0x1b0
[  110.601794] [<ffffff9008190ce4>] do_init_module+0xf0/0x2ac
[  110.607937] [<ffffff900815bd40>] load_module+0x2690/0x2dcc
[  110.614080] [<ffffff900815c614>] SyS_init_module+0x198/0x224
[  110.620417] [<ffffff9008083200>] el0_svc_naked+0x34/0x38
[  110.626354]
[  110.628027] Allocated by task 1204:
[  110.631940]  save_stack_trace_tsk+0x0/0x1f4
[  110.636628]  save_stack_trace+0x18/0x20
[  110.640930]  kasan_kmalloc.part.1+0x44/0xec
[  110.645617]  kasan_kmalloc+0x88/0x9c
[  110.649661]  kmalloc_uaf_memset+0x60/0xb8 [test_kasan]
[  110.655454]  kmalloc_tests_init+0x50/0x90 [test_kasan]
[  110.661209]  do_one_initcall+0xe4/0x1b0
[  110.665506]  do_init_module+0xf0/0x2ac
[  110.669708]  load_module+0x2690/0x2dcc
[  110.673909]  SyS_init_module+0x198/0x224
[  110.678304]  el0_svc_naked+0x34/0x38
[  110.682303]
[  110.683975] Freed by task 1204:
[  110.687500]  save_stack_trace_tsk+0x0/0x1f4
[  110.692189]  save_stack_trace+0x18/0x20
[  110.696489]  kasan_slab_free+0x90/0x15c
[  110.700784]  kfree+0xc8/0x258
[  110.704152]  kmalloc_uaf_memset+0x7c/0xb8 [test_kasan]
[  110.709943]  kmalloc_tests_init+0x50/0x90 [test_kasan]
[  110.715694]  do_one_initcall+0xe4/0x1b0
[  110.719995]  do_init_module+0xf0/0x2ac
[  110.724198]  load_module+0x2690/0x2dcc
[  110.728398]  SyS_init_module+0x198/0x224
[  110.732793]  el0_svc_naked+0x34/0x38
[  110.736791]
[  110.738468] The buggy address belongs to the object at ffffffc0336dab00
[  110.738468]  which belongs to the cache kmalloc-128 of size 128
[  110.752478] The buggy address is located 0 bytes inside of
[  110.752478]  128-byte region [ffffffc0336dab00, ffffffc0336dab80)
[  110.765407] The buggy address belongs to the page:
[  110.770772] page:ffffffbf00cdb600 count:1 mapcount:0 mapping:          (null) index:0xffffffc0336dbc80 compound_mapcount: 0
[  110.783238] flags: 0x10200(slab|head)
[  110.787334] page dumped because: kasan: bad access detected
[  110.793561]
[  110.795231] Memory state around the buggy address:
[  110.800602]  ffffffc0336daa00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  110.808687]  ffffffc0336daa80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  110.816769] >ffffffc0336dab00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  110.824845]                    ^
[  110.828463]  ffffffc0336dab80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  110.836546]  ffffffc0336dac00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  110.844621] ==================================================================
[  110.861989] kasan test: kmalloc_uaf2 use-after-free after another kmalloc
[  110.889739] ==================================================================
[  110.897890] BUG: KASAN: use-after-free in kmalloc_uaf2+0xc8/0x118 [test_kasan]
[  110.905972] Write of size 1 at addr ffffffc02fc52da8 by task insmod/1204
[  110.913462]
[  110.915144] CPU: 0 PID: 1204 Comm: insmod Tainted: G    B           4.9.191 #4
[  110.923218] Hardware name: sun50iw10 (DT)
[  110.927702] Call trace:
[  110.930462] [<ffffff900808ba74>] dump_backtrace+0x0/0x318
[  110.936512] [<ffffff900808bda0>] show_stack+0x14/0x1c
[  110.942174] [<ffffff90083ae758>] dump_stack+0xb0/0xe8
[  110.947840] [<ffffff90081f7ad4>] print_address_description+0x60/0x228
[  110.955057] [<ffffff90081f8140>] kasan_report+0x250/0x27c
[  110.961103] [<ffffff90081f695c>] __asan_store1+0x44/0x4c
[  110.967092] [<ffffff90007b88d0>] kmalloc_uaf2+0xc8/0x118 [test_kasan]
[  110.974341] [<ffffff90007b9564>] kmalloc_tests_init+0x54/0x90 [test_kasan]
[  110.982040] [<ffffff9008083a8c>] do_one_initcall+0xe4/0x1b0
[  110.988286] [<ffffff9008190ce4>] do_init_module+0xf0/0x2ac
[  110.994435] [<ffffff900815bd40>] load_module+0x2690/0x2dcc
[  111.000578] [<ffffff900815c614>] SyS_init_module+0x198/0x224
[  111.006916] [<ffffff9008083200>] el0_svc_naked+0x34/0x38
[  111.012854]
[  111.014524] Allocated by task 1204:
[  111.018433]  save_stack_trace_tsk+0x0/0x1f4
[  111.023119]  save_stack_trace+0x18/0x20
[  111.027419]  kasan_kmalloc.part.1+0x44/0xec
[  111.032106]  kasan_kmalloc+0x88/0x9c
[  111.036152]  kmalloc_uaf2+0x68/0x118 [test_kasan]
[  111.041463]  kmalloc_tests_init+0x54/0x90 [test_kasan]
[  111.047214]  do_one_initcall+0xe4/0x1b0
[  111.051516]  do_init_module+0xf0/0x2ac
[  111.055717]  load_module+0x2690/0x2dcc
[  111.059917]  SyS_init_module+0x198/0x224
[  111.064312]  el0_svc_naked+0x34/0x38
[  111.068309]
[  111.069981] Freed by task 1204:
[  111.073505]  save_stack_trace_tsk+0x0/0x1f4
[  111.078191]  save_stack_trace+0x18/0x20
[  111.082490]  kasan_slab_free+0x90/0x15c
[  111.086790]  kfree+0xc8/0x258
[  111.090157]  kmalloc_uaf2+0x84/0x118 [test_kasan]
[  111.095465]  kmalloc_tests_init+0x54/0x90 [test_kasan]
[  111.101217]  do_one_initcall+0xe4/0x1b0
[  111.105518]  do_init_module+0xf0/0x2ac
[  111.109716]  load_module+0x2690/0x2dcc
[  111.113918]  SyS_init_module+0x198/0x224
[  111.118311]  el0_svc_naked+0x34/0x38
[  111.122307]
[  111.123984] The buggy address belongs to the object at ffffffc02fc52d80
[  111.123984]  which belongs to the cache kmalloc-128 of size 128
[  111.137989] The buggy address is located 40 bytes inside of
[  111.137989]  128-byte region [ffffffc02fc52d80, ffffffc02fc52e00)
[  111.151016] The buggy address belongs to the page:
[  111.156383] page:ffffffbf00bf1400 count:1 mapcount:0 mapping:          (null) index:0xffffffc02fc53c80 compound_mapcount: 0
[  111.168852] flags: 0x10200(slab|head)
[  111.172950] page dumped because: kasan: bad access detected
[  111.179177]
[  111.180848] Memory state around the buggy address:
[  111.186217]  ffffffc02fc52c80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  111.194301]  ffffffc02fc52d00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  111.202384] >ffffffc02fc52d80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  111.210459]                                   ^
[  111.215532]  ffffffc02fc52e00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  111.223610]  ffffffc02fc52e80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  111.231683] ==================================================================

分析

從上述log,kasan提示這時一個訪問已釋放內存的錯誤類型(BUG: KASAN: use-after-free xxx),并顯示出錯的函數名稱,出錯信息提示,出錯附近內存狀況和出錯位置。

可以利用gdb+符號表查看源碼,以kmalloc_uaf為例:

$ ./out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gdb ~/link/kernel/linux-4.9/lib/test_kasan.ko
GNU gdb (Linaro_GDB-2016.05) 7.11.1.20160702-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=aarch64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /home1/weidonghui/link/kernel/linux-4.9/lib/test_kasan.ko...done.
(gdb) list *kmalloc_uaf+0x84
0x7d4 is in kmalloc_uaf (lib/test_kasan.c:267).
warning: Source file is more recent than executable.
262                     pr_err("Allocation failed\n");
263                     return;
264             }
265
266             kfree(ptr);
267             *(ptr + 8) = 'x';
268     }
269
270     static noinline void __init kmalloc_uaf_memset(void)
271     {
(gdb)

5.3重復釋放(double-free)

實例源碼(實例包括)

  • kmalloc_double_free_test:重復釋放內存。
#define pr_fmt(fmt) "kasan test: %s " fmt, __func__

#include <linux/kernel.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/kasan.h>

static noinline void __init kmalloc_double_free_test(void)
{
	char *ptr;
	size_t size = 123;

	pr_info("double-free\n");
	ptr = kmalloc(size, GFP_KERNEL);
	if (!ptr) {
		pr_err("Allocation failed\n");
		return;
	}

	kfree(ptr);
	kfree(ptr);
}

static int __init kmalloc_tests_init(void)
{
	/*
	 * Temporarily enable multi-shot mode. Otherwise, we'd only get a
	 * report for the first case.
	 */
	bool multishot = kasan_save_enable_multi_shot();

	kmalloc_double_free_test();

	kasan_restore_multi_shot(multishot);

	return -EAGAIN;
}

module_init(kmalloc_tests_init);
MODULE_LICENSE("GPL");

輸出log

[159003.489404] kasan test: kmalloc_double_free_test double-free
[159003.496364] ==================================================================
[159003.504599] BUG: KASAN: double-free or invalid-free in           (null)
[159003.512152]
[159003.513943] CPU: 0 PID: 17631 Comm: insmod Tainted: G    B           4.9.191 #4
[159003.522265] Hardware name: sun50iw10 (DT)
[159003.526886] Call trace:
[159003.529769] [<ffffff900808ba74>] dump_backtrace+0x0/0x318
[159003.535965] [<ffffff900808bda0>] show_stack+0x14/0x1c
[159003.541771] [<ffffff90083ae758>] dump_stack+0xb0/0xe8
[159003.547579] [<ffffff90081f7ad4>] print_address_description+0x60/0x228
[159003.554950] [<ffffff90081f7ec8>] kasan_report_double_free+0x64/0x8c
[159003.562124] [<ffffff90081f7694>] kasan_slab_free+0x44/0x15c
[159003.568511] [<ffffff90081f4b50>] kfree+0xc8/0x258
[159003.573964] [<ffffff90008289a4>] kmalloc_double_free_test+0x84/0xb0 [test_kasan]
[159003.582443] [<ffffff9000829640>] kmalloc_tests_init+0x78/0x90 [test_kasan]
[159003.590302] [<ffffff9008083a8c>] do_one_initcall+0xe4/0x1b0
[159003.596695] [<ffffff9008190ce4>] do_init_module+0xf0/0x2ac
[159003.602987] [<ffffff900815bd40>] load_module+0x2690/0x2dcc
[159003.609277] [<ffffff900815c614>] SyS_init_module+0x198/0x224
[159003.615761] [<ffffff9008083200>] el0_svc_naked+0x34/0x38
[159003.621846]
[159003.623630] Allocated by task 17631:
[159003.627772]  save_stack_trace_tsk+0x0/0x1f4
[159003.632596]  save_stack_trace+0x18/0x20
[159003.637035]  kasan_kmalloc.part.1+0x44/0xec
[159003.641856]  kasan_kmalloc+0x88/0x9c
[159003.646030]  kmalloc_double_free_test+0x60/0xb0 [test_kasan]
[159003.652552]  kmalloc_tests_init+0x78/0x90 [test_kasan]
[159003.658446]  do_one_initcall+0xe4/0x1b0
[159003.662882]  do_init_module+0xf0/0x2ac
[159003.667210]  load_module+0x2690/0x2dcc
[159003.671544]  SyS_init_module+0x198/0x224
[159003.676073]  el0_svc_naked+0x34/0x38
[159003.680197]
[159003.681980] Freed by task 17631:
[159003.685733]  save_stack_trace_tsk+0x0/0x1f4
[159003.690558]  save_stack_trace+0x18/0x20
[159003.694987]  kasan_slab_free+0x90/0x15c
[159003.699417]  kfree+0xc8/0x258
[159003.702911]  kmalloc_double_free_test+0x7c/0xb0 [test_kasan]
[159003.709435]  kmalloc_tests_init+0x78/0x90 [test_kasan]
[159003.715328]  do_one_initcall+0xe4/0x1b0
[159003.719759]  do_init_module+0xf0/0x2ac
[159003.724089]  load_module+0x2690/0x2dcc
[159003.728418]  SyS_init_module+0x198/0x224
[159003.732945]  el0_svc_naked+0x34/0x38
[159003.737071]
[159003.738858] The buggy address belongs to the object at ffffffc031810d00
[159003.738858]  which belongs to the cache kmalloc-128 of size 128
[159003.753164] The buggy address is located 0 bytes inside of
[159003.753164]  128-byte region [ffffffc031810d00, ffffffc031810d80)
[159003.766389] The buggy address belongs to the page:
[159003.771893] page:ffffffbf00c60400 count:1 mapcount:0 mapping:          (null) index:0xffffffc031813a00 compound_mapcount: 0
[159003.784561] flags: 0x10200(slab|head)
[159003.788786] page dumped because: kasan: bad access detected
[159003.795161]
[159003.796939] Memory state around the buggy address:
[159003.802443]  ffffffc031810c00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[159003.810680]  ffffffc031810c80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[159003.818920] >ffffffc031810d00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[159003.827150]                    ^
[159003.830892]  ffffffc031810d80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[159003.839142]  ffffffc031810e00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[159003.847379] ==================================================================

分析

從上述log,kasan提示這是一個重復釋放內存的錯誤類型(BUG: KASAN: double-free or invalid-free xxx),并顯示出錯的函數名稱,出錯信息提示,出錯附近內存狀況和出錯位置。可以利用gdb+符號表查看源碼,以kmalloc_double_free_test為例:

$ ./out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gdb ~/link/kernel/linux-4.9/lib/test_kasan.ko
GNU gdb (Linaro_GDB-2016.05) 7.11.1.20160702-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=aarch64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /home1/weidonghui/link/kernel/linux-4.9/lib/test_kasan.ko...done.
(gdb) list *kmalloc_double_free_test+0x84
0x9a4 is in kmalloc_double_free_test (lib/test_kasan.c:477).
472                     return;
473             }
474
475             kfree(ptr);
476             kfree(ptr);
477     }
478
479     static int __init kmalloc_tests_init(void)
480     {
481             /*
(gdb)


責任編輯:武曉燕 來源: Linux深度
相關推薦

2016-09-12 16:01:28

Android內存泄露內存管理

2021-10-06 20:00:08

LinuxLinux內核Kasan

2025-11-04 01:25:00

2013-08-29 11:32:19

企業移動App定位

2016-05-12 09:33:11

IBM大型機實時分析

2025-08-07 01:00:00

2022-04-07 13:22:06

5G物聯網蜂窩

2016-06-02 14:11:34

銳捷網絡機車無線定位

2014-10-20 16:31:48

科來軟件網絡回溯分析

2021-06-10 14:20:46

無人機AI人工智能

2012-12-27 12:38:47

移動廣告地理信息服務

2011-05-10 15:26:30

藍影鼠標微軟

2021-03-26 05:59:10

內存檢測工具

2014-04-15 17:03:00

2009-06-03 14:15:34

2020-02-27 13:01:57

JVM內存劃分

2021-04-14 08:20:46

Lighthouse工具性能檢測

2015-03-13 09:10:29

2010-06-04 10:09:29

Linux 性能檢測
點贊
收藏

51CTO技術棧公眾號

在线观看 中文字幕| 麻豆精品视频| 久久爱一区二区| 亚洲精选av| 亚洲va在线va天堂| 亚洲蜜桃在线| 午夜视频免费看| 免费成人性网站| 欧美激情小视频| 亚洲一级片在线播放| www.丝袜精品| 欧美群妇大交群的观看方式 | 国产亚洲电影| 91麻豆精品国产| 欧美成人精品欧美一级乱| gogo在线高清视频| 久久青草欧美一区二区三区| 国产精品香蕉在线观看| 日韩黄色在线视频| 911久久香蕉国产线看观看| 亚洲精品中文字幕女同| 中文字幕 欧美 日韩| av高清一区| 亚洲成av人片| 久久久久久av无码免费网站下载| 成人在线观看黄色| 91丝袜国产在线播放| 亚洲xxx视频| 亚洲一区二区影视| 久久人人97超碰国产公开结果| 欧美美最猛性xxxxxx| 高清国产在线观看| 免费观看久久av| 亚洲精品国精品久久99热| 国产伦精品一区二区三区妓女下载| free性护士videos欧美| 一区二区三区在线观看视频| 亚欧洲精品在线视频免费观看| 三级无遮挡在线观看| 福利电影一区二区三区| 亚洲一区二区三区四区视频| 一本一道人人妻人人妻αv| 丝袜美腿亚洲一区二区图片| 欧美在线视频免费观看| 精品午夜福利在线观看| 欧美激情日韩| 欧美精品性视频| 美女福利视频在线观看| 一区二区三区在线| 久久精品国产96久久久香蕉| 蜜桃视频最新网址| 小小影院久久| 美女精品久久久| 日本妇女毛茸茸| 欧美在线播放| 色在人av网站天堂精品| 久久久久无码国产精品| 激情久久综合| 97在线看免费观看视频在线观看| 久久久久久久国产视频| 在线不卡欧美| 57pao成人国产永久免费| 国产精品7777777| 国产精品最新自拍| 欧美最猛性xxxx| 在线观看污污网站| 美女精品自拍一二三四| 成人黄色大片在线免费观看| 国产v在线观看| 国产91丝袜在线播放0| 国产在线精品一区二区三区| 日韩午夜影院| 国产女人aaa级久久久级| 五月婷婷综合色| 精品孕妇一区二区三区| 一区二区日韩电影| 日本免费不卡一区二区| 日韩高清不卡| 欧美一区日韩一区| 久久午夜夜伦鲁鲁片| 国产亚洲一卡2卡3卡4卡新区| 中文字幕av一区二区| 97成人资源站| 国产精品乱看| 成人在线一区二区| 欧美性猛交 xxxx| 久久精品欧美一区二区三区麻豆| 亚洲欧洲免费无码| 大黄网站在线观看| 在线免费观看一区| 免费人成视频在线播放| 天天做夜夜做人人爱精品 | 超黄网站在线观看| 一本色道久久综合亚洲91| 国产日韩欧美久久| 久久久久久毛片免费看 | 国产一二三精品| 久久九九视频| 黄色成人在线观看| 欧美性猛交xxxx乱大交蜜桃| 超碰人人草人人| 任你弄精品视频免费观看| 中文字幕亚洲欧美日韩2019| 动漫精品一区一码二码三码四码| 日韩高清在线不卡| 福利精品视频| 免费av毛片在线看| 日韩欧中文字幕| 日本一级大毛片a一| 波多野结衣在线播放一区| 欧美极品欧美精品欧美视频| 中文字幕在线视频第一页| 波多野结衣精品在线| 日韩视频在线观看视频| 性欧美18一19sex性欧美| 欧美r级在线观看| 一区二区三区在线播放视频| 亚洲影院免费| 国产精品一区二区三区在线观| a√在线中文网新版址在线| 午夜电影久久久| 中文字幕人妻无码系列第三区| 欧美精品久久久久久| 久久久女女女女999久久| 国产伦理吴梦梦伦理| 国产性做久久久久久| 日韩免费视频播放| 盗摄牛牛av影视一区二区| 啊v视频在线一区二区三区| av毛片在线免费观看| 99久久国产免费看| av在线com| 日韩中文字幕在线一区| 久久精品视频一| 亚洲一线在线观看| 亚洲国产电影在线观看| 国产成人精品视频ⅴa片软件竹菊| 国产精品自在| 久久久综合av| 欧美 中文字幕| 亚洲国产婷婷综合在线精品| 少妇性l交大片7724com| 欧美精品网站| www.久久艹| 牛牛精品在线视频| 精品日本一线二线三线不卡| 久久精品波多野结衣| 国产精品99久久久久久有的能看| 国产精品av免费| 国产精品1区| 欧美成人精品在线| 性少妇videosexfreexxx片| 伊人色综合久久天天人手人婷| 一级做a爱视频| 亚洲欧美综合国产精品一区| 高清视频一区| 欧美大胆a人体大胆做受| 日韩精品一区二区在线观看| 国产一级二级三级视频| 成人高清视频在线观看| 男人天堂1024| 欧洲grand老妇人| 国产精品综合不卡av| 成人三级网址| 精品国产凹凸成av人导航| 日本少妇性生活| 久久久久久久久99精品| 爱情岛论坛亚洲首页入口章节| 色喇叭免费久久综合| 亚洲一区二区三区777| 1区2区3区在线| 亚洲欧洲国产一区| 97精品久久人人爽人人爽| 樱花草国产18久久久久| 最新在线黄色网址| 美女免费视频一区| 妺妺窝人体色www看人体| 美女呻吟一区| 国产精品自产拍在线观| 日本天码aⅴ片在线电影网站| 亚洲精品福利在线观看| 中文字幕免费高清在线观看| 一区二区三区四区亚洲| 国产 中文 字幕 日韩 在线| 久久99蜜桃精品| 青青青在线视频播放| 国产精品一在线观看| 亚洲qvod图片区电影| 性欧美18~19sex高清播放| 久久精品99无色码中文字幕 | 日韩欧美久久| 青青草国产精品一区二区| 好了av在线| 亚洲跨种族黑人xxx| 国产精品美女一区| 欧美性猛交99久久久久99按摩| 成年人免费视频播放| av亚洲精华国产精华| 天堂av在线8| 久久成人精品| 久久精品无码中文字幕| 成人综合一区| 久久国产精品 国产精品| 福利一区三区| 日本最新高清不卡中文字幕| 欧美理论电影| 日韩中文字幕免费视频| 日韩福利一区二区| 欧美变态tickle挠乳网站| 中文无码av一区二区三区| 午夜婷婷国产麻豆精品| 日韩av毛片在线观看| 国产午夜三级一区二区三| 国产极品一区二区| 国产电影精品久久禁18| 91小视频网站| 日韩在线卡一卡二| 18岁网站在线观看| 一区在线播放| 2022中文字幕| 亚洲欧美综合久久久| 亚洲乱码一区二区三区| 精品久久电影| 日韩.欧美.亚洲| 午夜先锋成人动漫在线| 国产欧美日韩伦理| 一区二区三区四区精品视频| 国产日韩欧美中文在线播放| 搜成人激情视频| 97视频在线看| 日本无删减在线| 久久99亚洲热视| 三级网站视频在在线播放| 播播国产欧美激情| 欧美三级电影一区二区三区| 一本色道久久综合狠狠躁篇怎么玩 | 蜜臀精品久久久久久蜜臀 | 亚洲欧洲在线看| 欧美黄色小说| 亚洲精品视频免费| 日本成人一区二区三区| 日韩国产精品一区| 亚洲 精品 综合 精品 自拍| 精品处破学生在线二十三| 亚洲精选一区二区三区| 精品乱人伦小说| 人妻少妇一区二区三区| 亚洲大胆人体在线| 亚洲av成人精品日韩在线播放| 精品处破学生在线二十三| 神马午夜在线观看| 日韩黄色av网站| 好男人免费精品视频| 这里只有精品在线播放| 1769在线观看| 操人视频在线观看欧美| 欧美黑人猛交| 3344国产精品免费看| 欧美电影免费观看高清完整| 国产精品久久91| 亚洲一区二区av| 国产精品免费一区二区三区在线观看 | 国产伦精品一区二区三| 亚洲视频分类| 一区二区成人国产精品| 女人香蕉久久**毛片精品| 日本一本中文字幕| 欧美专区一区二区三区| 亚洲 激情 在线| 国产精品77777竹菊影视小说| 秘密基地免费观看完整版中文 | 免费成年人视频在线观看| 一区二区三区不卡视频在线观看| 日韩三级一区二区三区| 91福利社在线观看| 97免费观看视频| 亚洲国产天堂久久综合网| 国产一二三在线观看| 久久午夜a级毛片| 欧美办公室脚交xxxx| 国产在线98福利播放视频| 中文在线综合| 日本黄网免费一区二区精品| 在线观看国产精品入口| 国产精品宾馆在线精品酒店| 精品亚洲成a人在线观看| 无码国产69精品久久久久网站| 久久这里只有精品视频网| 一区二区三区影视| 欧美视频国产精品| 国产精品探花视频| 亚洲精品小视频在线观看| 乱人伦中文视频在线| 欧美一区在线直播| 电影91久久久| 欧美高清一区二区| 亚洲午夜精品一区 二区 三区| www一区二区www免费| 韩国av一区二区三区在线观看| 国产精品300页| 亚洲欧洲综合另类| 免费av中文字幕| 亚洲成人久久久| 国产精品实拍| 国产精品成人v| 日韩母乳在线| 欧美黄色免费网址| 麻豆国产一区二区| 无码人妻精品一区二区三| 免费av毛片在线看| 亚洲香蕉av| 欧美日韩大陆在线| 宅男噜噜99国产精品观看免费| 波多野结衣视频观看| 国产精品论坛| 久久网这里都是精品| 国产成人精品av| 国产精品丝袜久久久久久消防器材| 黑人与亚洲人色ⅹvideos| 欧美国产91| 欧美本精品男人aⅴ天堂| 中文字幕一区2区3区| 日韩av在线网| 黄网在线免费看| 亚洲最大福利网站| 2023国产精品久久久精品双| 欧美性猛交xxx乱久交| 91在线观看污| 日韩欧美大片在线观看| 欧美成人一级视频| 污网站在线免费看| 亚洲在线www| 一区二区电影在线观看| 伊人国产精品视频| 亚洲色图视频免费播放| 国产精品欧美综合亚洲| 久久激情视频免费观看| 欧美高清免费| 特级毛片在线免费观看| 久久99久久精品| 天海翼在线视频| 欧美一区二区三区在线看| 免费a级在线播放| 91免费看国产| 欧美久久九九| 亚洲av人人澡人人爽人人夜夜| 亚洲国产精品一区二区尤物区| 成人久久精品人妻一区二区三区| 色综合色综合网色综合 | 国产欧美日韩免费看aⅴ视频| 成人激情电影在线| 天堂视频免费看| 亚洲欧美偷拍三级| www.好吊色| 国精产品一区一区三区有限在线| 国产一级成人av| 国产xxxxx在线观看| 国产午夜亚洲精品羞羞网站| 亚洲无码精品国产| 操91在线视频| 秋霞综合在线视频| 天堂av在线网站| 综合自拍亚洲综合图不卡区| 午夜精品久久久久久久99老熟妇| 久久久久久久久久国产| 最新亚洲精品| 国产高潮免费视频| 伊人性伊人情综合网| 午夜黄色小视频| 国产精品专区一| 狠狠色狠狠色综合日日tαg| 日本xxxx裸体xxxx| 欧美日韩精品一区二区三区蜜桃| 国产在线1区| 国产自产精品| 美女精品一区二区| 国产亚洲欧美精品久久久www| 日韩成人在线播放| 欧美在线se| av女优在线播放| 国产午夜精品福利| 精品二区在线观看| 青青草99啪国产免费| 亚洲综合婷婷| 亚洲av无码国产精品久久| 欧美日本视频在线| 蜜桃视频在线网站| 一本色道久久综合亚洲精品婷婷| 国产sm精品调教视频网站| 国产午夜麻豆影院在线观看| 久久不射电影网| 国产成人三级| 国产a√精品区二区三区四区| 色婷婷综合中文久久一本| 91亚洲天堂| 视频在线99| 99国产精品视频免费观看| 夜夜躁狠狠躁日日躁av| 国产91精品久| 欧美日韩 国产精品|