使用适当的包装函数从 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的主要内容,如果未能解决你的问题,请参考以下文章