使用适当的包装函数从 sk_buff 获取 pid

Posted

技术标签:

【中文标题】使用适当的包装函数从 sk_buff 获取 pid【英文标题】:get pid from sk_buff using proper wrapper function 【发布时间】:2021-08-26 06:24:39 【问题描述】:

这是Getting PID from sk_buff and inode in Linux Kernel的后续问题, 而且由于我无法在答案下发表评论,所以我在这里..

答案是skb->sk->socket->file->f_owner->pid

我之所以这么问,是因为我有一种预感,在内核空间中使用指针直接处理数据很容易出错。

我用谷歌搜索了这个,但没有发现任何有用的东西。

任何帮助或建议将不胜感激。

顺便说一下,内核版本是4.4或3.10。基于最新内核头的解决方案也可以。

【问题讨论】:

【参考方案1】:

由于我本周正在使用 5.10.28 和 Debian 11,这就是您得到的解决方案。 :-@) 来自 /usr/include/linux/pid.h(或 debian/linux-headers/usr/src/linux-headers-5.10.28/include/linux/pid.h,如果你愿意)的这条评论告诉它比我一个人做的更好:

/*
 * What is struct pid?
 *
 * A struct pid is the kernel's internal notion of a process identifier.
 * It refers to individual tasks, process groups, and sessions.  While
 * there are processes attached to it the struct pid lives in a hash
 * table, so it and then the processes that it refers to can be found
 * quickly from the numeric pid value.  The attached processes may be
 * quickly accessed by following pointers from struct pid.
 *
 * Storing pid_t values in the kernel and referring to them later has a
 * problem.  The process originally with that pid may have exited and the
 * pid allocator wrapped, and another process could have come along
 * and been assigned that pid.
 *
 * Referring to user space processes by holding a reference to struct
 * task_struct has a problem.  When the user space process exits
 * the now useless task_struct is still kept.  A task_struct plus a
 * stack consumes around 10K of low kernel memory.  More precisely
 * this is THREAD_SIZE + sizeof(struct task_struct).  By comparison
 * a struct pid is about 64 bytes.
 *
 * Holding a reference to struct pid solves both of these problems.
 * It is small so holding a reference does not consume a lot of
 * resources, and since a new struct pid is allocated when the numeric pid
 * value is reused (when pids wrap around) we don't mistakenly refer to new
 * processes.
 */

检查 pid.h 会显示一些对您有帮助的实用程序,如果您准备在内核空间中处理此问题(鉴于上面的黑暗警告,需要稍微了解命名空间等)。您的 sk_buff 包含一个指向 struct pid 的指针,而不仅仅是一个整数 pid,并且可能是一个用户空间进程,由于您在内核空间中,该进程现已消失。您最好的选择是:

#include <pid.h>

struct pid *myspid;
pid_t mypid;

myspid = get_pid(skb->sk->socket->file->f_owner->pid);
if (myspid == NULL)
    /* forget it */
mypid = pid_nr(myspid);
return mypid;

但肯定不止于此。只是让你进入球场。

【讨论】:

感谢您的意见。我实际上是在寻找一种从struct sk_buff 获取struct pid 的方法。直接使用指针操作数据会导致内核恐慌,因此是个问题。但是我发现来自struct pid 的pid 信息代表了来自套接字的指定接收者 数据,而不是实际的套接字文件所有者。还是谢谢你。

以上是关于使用适当的包装函数从 sk_buff 获取 pid的主要内容,如果未能解决你的问题,请参考以下文章

释放 sk_buff 是谁的责任

python 使用此包装器而不是崩溃从函数中获取默认输出。

sk_buff结构

使用适当的包装将元素左右对齐

使用 org-indent-mode 时如何用适当的缩进包装列表?

sk_buff的数据预留和对齐