我在内核模块中有以下代码,它遍历进程树并打印进程名称和 uid,直到 init 进程:
// recursivly walk the task's parent until we reach init
void parent_task_walk(struct task_struct *task) {
struct task_struct *parent;
char filename[MAX_FILE_LEN];
if (task && task->mm) {
parent = get_task_parent(task);
printk("%s (uid:%d)", exe_from_mm(task->mm, filename, MAX_FILE_LEN),
get_task_uid(task));
if (parent && task->pid != 1) {
printk(", ");
parent_task_walk(parent);
}
}
}
注意:我使用了一些引用真实内核函数的宏,因为这是针对内核模块的跨越多个版本。源代码位于此文件中: https://github.com/cormander/tpe-lkm/blob/319e1e29ea23055cca1c0a3bce3c865def14d3d2/core.c#L61
输出最终看起来像这样:
/bin/bash ( uid:500), /usr/sbin/sshd (uid:500), /usr/sbin/sshd (uid:0)、/usr/sbin/sshd (uid:0)、/sbin/init (uid:0)
这是一个递归函数。正如您可以想象的那样,当您启动 200 个 bash shell 然后触发事件时,事情会变得很糟糕。我不确定到底发生了什么,但机器死机了。我假设内核耗尽了堆栈空间,出现 OOM,然后自行射击?
我想知道处理这种情况的最佳方法是什么。我看到几个选项:
1)在 N 个进程后停止遍历进程树
2)在某个字符数组(最终将被打印)已满后停止遍历
3)使用 goto
而不是递归函数,但仍然遵守选项 #1 和 #2 中的新规则
4) 使用您将为我阐明的其他一些非递归方法
这发生在内核空间中,因此不是最友好的环境。任何人都可以指出为此采取的最佳方法吗?
I have the following code in a kernel module that walks up the process tree and prints the process names and uids up until the init process:
// recursivly walk the task's parent until we reach init
void parent_task_walk(struct task_struct *task) {
struct task_struct *parent;
char filename[MAX_FILE_LEN];
if (task && task->mm) {
parent = get_task_parent(task);
printk("%s (uid:%d)", exe_from_mm(task->mm, filename, MAX_FILE_LEN),
get_task_uid(task));
if (parent && task->pid != 1) {
printk(", ");
parent_task_walk(parent);
}
}
}
NOTE: I make use of some macros that reference the real kernel functions, as this is for a kernel module the spans multiple versions. The source code is in this file: https://github.com/cormander/tpe-lkm/blob/319e1e29ea23055cca1c0a3bce3c865def14d3d2/core.c#L61
The output ends up looking something like this:
/bin/bash (uid:500), /usr/sbin/sshd (uid:500), /usr/sbin/sshd (uid:0), /usr/sbin/sshd (uid:0), /sbin/init (uid:0)
It's a recursive function. As you can imagine, things go bad when you launch 200 bash shells and then trigger the event. I'm not sure exactly what happens, but the machine freezes. Kernel ran out of stack space I'm assuming, went OOM, and shot itself?
I'm wondering what's the best way to handle that case. I see a few options:
1) stop walking the process tree after N processes
2) stop walking after some character array (that will eventually be printed) is full
3) make use of a goto
instead of a recursive function, and yet still obey a new rule from options #1 and #2
4) use some other non-recursion method that you'll articulate for me
This is happening in kernel space, so not the most hospitable environment. Can anyone give any pointers as to the best approach to take for this?
发布评论
评论(1)
事实上,您的内核崩溃可能是因为您正在使用递归函数而发生。
您可以使用一个非常简单的循环来代替递归函数...您来自仅函数式编程的世界吗? while 循环是 C 中的标准循环,但如果您确实想使用 goto,您可以...;) 这是使用循环的代码。
Indeed you kernel crash probably happens because you are using a recursive function.
You could just use a very simple loop instead of your recursive function... Do you come from a functional programming only world? A while loop is standard in C, but if you really want to use a goto you could... ;) Here is the code using a loop.