循环遍历内核空间中的链表
Posted
技术标签:
【中文标题】循环遍历内核空间中的链表【英文标题】:Loop through linked list in kernel space 【发布时间】:2021-04-17 00:54:37 【问题描述】:我正在尝试遍历task_struct 内的 vma(由指针 mm 引用)。我正在做的是尝试打印 struct vm_area_struct 的一些属性(具体来说,我正在尝试打印 vm_start)。我的问题是我不断收到 NULL 指针取消引用错误。
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/sched/signal.h>
#include <linux/sched/task_stack.h>
void print_mmap(struct vm_area_struct *mmap)
while (mmap != NULL)
printk(KERN_INFO "vm_start: %lu\n", mmap->vm_start);
mmap = mmap->vm_next;
void procs_info_print(void)
struct task_struct *task_list;
size_t process_counter = 0;
for_each_process(task_list)
printk(KERN_INFO "new process\n");
volatile long state = task_list->state; /* state of the process */
struct mm_struct *mm = task_list->mm; /* address space of this process */
struct vm_area_struct *mmap = mm->mmap; /* list of VMAs */
print_mmap(mmap);
struct files_struct *files = task_list->files; /* list of open files */
/* registers */
unsigned long tasks_ax = task_pt_regs(task_list)->ax;
unsigned long tasks_bx = task_pt_regs(task_list)->bx;
unsigned long tasks_cx = task_pt_regs(task_list)->cx;
unsigned long tasks_dx = task_pt_regs(task_list)->dx;
unsigned long tasks_ip = task_pt_regs(task_list)->ip; /* program counter */
unsigned long tasks_sp = task_pt_regs(task_list)->sp;
unsigned long tasks_bp = task_pt_regs(task_list)->bp;
unsigned long tasks_si = task_pt_regs(task_list)->si;
unsigned long tasks_di = task_pt_regs(task_list)->di;
printk(KERN_INFO "== Number of process: %zu\n", process_counter);
static int __init entry(void)
procs_info_print();
return 0;
static void __exit end(void)
printk(KERN_INFO, "Exiting\n");
module_init(entry);
module_exit(end);
我得到的错误是
[ 139.457092] new process
[ 139.457094] vm_start: 94895486087168
[ 139.457095] vm_start: 94895489552384
[ 139.457096] vm_start: 94895489794048
[ 139.457098] vm_start: 94895495430144
[ 139.457099] vm_start: 139802326335488
[ 139.457100] vm_start: 139802326470656
[ 139.457101] vm_start: 139802460553216
[ 139.457102] vm_start: 139802460688384
[ 139.457103] vm_start: 139802574995456
[ 139.457104] vm_start: 139802574999552
[ 139.457105] vm_start: 139802583388160
[ 139.457106] vm_start: 139802583392256
[ 139.457108] vm_start: 139802591780864
[ 139.457109] vm_start: 139802593472512
[ 139.457110] vm_start: 139802595565568
[ 139.457111] vm_start: 139802595569664
[ 139.457112] vm_start: 139802595573760
[ 139.457113] vm_start: 139802595692544
[ 139.457114] vm_start: 139802597785600
[ 139.457115] vm_start: 139802597789696
[ 139.457116] vm_start: 139802597793792
[ 139.457117] vm_start: 139802597875712
[ 139.457118] vm_start: 139802599968768
[ 139.457119] vm_start: 139802599972864
[ 139.457120] vm_start: 139802599976960
[ 139.457121] vm_start: 139802600017920
[ 139.457123] vm_start: 139802602110976
[ 139.457124] vm_start: 139802602115072
[ 139.457125] vm_start: 139802602119168
[ 139.457126] vm_start: 139802602151936
[ 139.457127] vm_start: 139802604244992
[ 139.457128] vm_start: 139802604249088
[ 139.457129] vm_start: 139802604253184
[ 139.457130] vm_start: 139802604670976
[ 139.457131] vm_start: 139802606764032
[ 139.457132] vm_start: 139802606768128
[ 139.457133] vm_start: 139802606784512
[ 139.457134] vm_start: 139802606788608
[ 139.457135] vm_start: 139802606804992
[ 139.457136] vm_start: 139802608898048
[ 139.457138] vm_start: 139802608902144
[ 139.457139] vm_start: 139802608906240
[ 139.457140] vm_start: 139802608922624
[ 139.457141] vm_start: 139802611015680
[ 139.457142] vm_start: 139802611019776
[ 139.457143] vm_start: 139802611023872
[ 139.457144] vm_start: 139802611048448
[ 139.457145] vm_start: 139802613141504
[ 139.457146] vm_start: 139802613145600
[ 139.457147] vm_start: 139802613149696
[ 139.457148] vm_start: 139802613161984
[ 139.457149] vm_start: 139802615255040
[ 139.457151] vm_start: 139802615259136
[ 139.457152] vm_start: 139802615263232
[ 139.457153] vm_start: 139802615721984
[ 139.457154] vm_start: 139802617819136
[ 139.457155] vm_start: 139802617823232
[ 139.457156] vm_start: 139802617827328
[ 139.457157] vm_start: 139802617933824
[ 139.457158] vm_start: 139802620026880
[ 139.457159] vm_start: 139802620030976
[ 139.457160] vm_start: 139802620035072
[ 139.457161] vm_start: 139802620051456
[ 139.457162] vm_start: 139802620162048
[ 139.457163] vm_start: 139802622255104
[ 139.457164] vm_start: 139802622259200
[ 139.457165] vm_start: 139802622263296
[ 139.457166] vm_start: 139802622410752
[ 139.457168] vm_start: 139802624507904
[ 139.457169] vm_start: 139802624512000
[ 139.457170] vm_start: 139802624516096
[ 139.457171] vm_start: 139802624720896
[ 139.457172] vm_start: 139802626813952
[ 139.457173] vm_start: 139802626818048
[ 139.457174] vm_start: 139802626822144
[ 139.457175] vm_start: 139802626846720
[ 139.457176] vm_start: 139802628939776
[ 139.457177] vm_start: 139802628943872
[ 139.457178] vm_start: 139802628947968
[ 139.457179] vm_start: 139802630078464
[ 139.457180] vm_start: 139802632175616
[ 139.457181] vm_start: 139802632183808
[ 139.457182] vm_start: 139802632204288
[ 139.457183] vm_start: 139802632208384
[ 139.457184] vm_start: 139802632224768
[ 139.457185] vm_start: 139802634321920
[ 139.457187] vm_start: 139802634326016
[ 139.457188] vm_start: 139802634330112
[ 139.457189] vm_start: 139802634629120
[ 139.457190] vm_start: 139802636726272
[ 139.457191] vm_start: 139802636730368
[ 139.457192] vm_start: 139802636738560
[ 139.457193] vm_start: 139802636767232
[ 139.457194] vm_start: 139802638860288
[ 139.457195] vm_start: 139802638864384
[ 139.457196] vm_start: 139802638868480
[ 139.457197] vm_start: 139802638929920
[ 139.457198] vm_start: 139802641022976
[ 139.457199] vm_start: 139802641027072
[ 139.457200] vm_start: 139802641031168
[ 139.457201] vm_start: 139802641121280
[ 139.457203] vm_start: 139802643214336
[ 139.457204] vm_start: 139802643218432
[ 139.457205] vm_start: 139802643222528
[ 139.457600] vm_start: 139802643341312
[ 139.457601] vm_start: 139802645438464
[ 139.457602] vm_start: 139802645442560
[ 139.457604] vm_start: 139802645446656
[ 139.457605] vm_start: 139802645487616
[ 139.457606] vm_start: 139802645540864
[ 139.457607] vm_start: 139802647633920
[ 139.457608] vm_start: 139802647638016
[ 139.457609] vm_start: 139802647642112
[ 139.457610] vm_start: 139802647932928
[ 139.457611] vm_start: 139802650030080
[ 139.457612] vm_start: 139802650046464
[ 139.457613] vm_start: 139802650050560
[ 139.457614] vm_start: 139802650054656
[ 139.457616] vm_start: 139802650386432
[ 139.457617] vm_start: 139802652479488
[ 139.457618] vm_start: 139802652487680
[ 139.457619] vm_start: 139802652491776
[ 139.457620] vm_start: 139802652495872
[ 139.457621] vm_start: 139802652647424
[ 139.457622] vm_start: 139802654740480
[ 139.457623] vm_start: 139802654744576
[ 139.457624] vm_start: 139802654748672
[ 139.457625] vm_start: 139802654756864
[ 139.457626] vm_start: 139802654965760
[ 139.457627] vm_start: 139802657058816
[ 139.457628] vm_start: 139802657161216
[ 139.457629] vm_start: 139802657165312
[ 139.457631] vm_start: 139802657193984
[ 139.457632] vm_start: 139802659287040
[ 139.457633] vm_start: 139802659291136
[ 139.457634] vm_start: 139802659295232
[ 139.457635] vm_start: 139802661093376
[ 139.457636] vm_start: 139802663186432
[ 139.457637] vm_start: 139802663751680
[ 139.457638] vm_start: 139802663755776
[ 139.457639] vm_start: 139802663763968
[ 139.457640] vm_start: 139802665758720
[ 139.457641] vm_start: 139802667855872
[ 139.457642] vm_start: 139802667872256
[ 139.457644] vm_start: 139802667880448
[ 139.457645] vm_start: 139802667896832
[ 139.457646] vm_start: 139802669998080
[ 139.457647] vm_start: 139802670153728
[ 139.457648] vm_start: 139802670157824
[ 139.457649] vm_start: 139802670161920
[ 139.457650] vm_start: 140733449646080
[ 139.457651] vm_start: 140733451108352
[ 139.457652] vm_start: 140733451120640
[ 139.457653] new process
[ 139.463574] BUG: kernel NULL pointer dereference, address: 0000000000000000
[ 139.463592] #PF: supervisor read access in kernel mode
[ 139.463595] #PF: error_code(0x0000) - not-present page
谁能帮我循环直到我到达这个链表的末尾而不抛出错误?
我在内核中读到 vma 也是根据红黑树组织的。但是,在检查内核中的代码后,我找不到存储在节点中的任何信息。这可能是遍历 vma 的更可靠的方法。但是现在我不知道如何访问存储在其中的数据(据说)。
【问题讨论】:
在循环条件中,您需要将 iterator 本身与 NULL 进行比较,而不是其vm_next
字段:while(mmap != NULL)
。参见例如该代码:elixir.bootlin.com/linux/v5.10.6/source/arch/parisc/kernel/…
@Tsyvarev 我做了你建议的改变,但我仍然得到错误。你能在你的最后运行代码,看看你是否没有收到错误?
奇怪的是,它似乎很好地完成了一个进程,然后它突然在下一个进程上得到一个空指针引用。
检查迭代器是否为 NULL 是迭代链表的正确方法。可能,您的代码的其他部分是错误的。例如。 “新进程”表示要创建的新进程,它使您正在迭代的对象。
我将发布到目前为止的其余代码以展示我所做的工作。请稍等。
【参考方案1】:
while(mmap->vm_next != NULL)
看起来不对。循环控制关闭 1,mmap
可能为空。试试这个
while(mmap != NULL)
某些进程(即僵尸进程)没有可用的 VM 指针。
【讨论】:
感谢您的回复。我之前将我的代码更改为这个建议(有人已经建议过这个)但它没有任何区别。我将更新示例中的代码以反映这一点,因为它更干净。 @rogerroger69:如果我是你,我会开始检查所有内容是否为空,比如mm
本身。以上是关于循环遍历内核空间中的链表的主要内容,如果未能解决你的问题,请参考以下文章