如何识别用户空间和内核空间之间的特定套接字?

时间:2013-09-16 18:47:35

标签: c linux sockets tcp linux-kernel

我在User Space中有一个库拦截套接字层调用,例如socket()connect()accept()等。我只处理TCP套接字。

Down in Kernel Space我有一个网络内核模块,它处理所有的TCP连接。我需要能够在驱动程序中识别用户空间库拦截了哪些套接字。

到目前为止,我一直在使用priority(内核)中的struct sock字段,我可以在用户空间中使用setsockopt()设置该字段。但这是一个非常肮脏的黑客。

struct sock是否有任何类型的私有字段我可以安全地使用并通过setsockopt()从用户空间进行设置?

感谢。

2 个答案:

答案 0 :(得分:6)

实际上没有这样的“私有字段”选项可以仅由用户空间和内核代码使用。

使用SO_PRIORITY选项似乎有点过于干扰,因为它可以改变堆栈处理数据包的方式,并且可能导致难以理解的结果。更安全的选择是将SO_RCVBUFSO_SNDBUF值调整为通常默认值的一些小增量。 Linux将传入的值加倍,但您可以从默认值中查找增量,并知道delta的存在是一个信号,表明这是您的“截获”套接字。

答案 1 :(得分:1)

获取原始问题“我需要能够在驱动程序中识别出用户空间库拦截了哪些套接字。”事实上有一些功能。

首先,您需要知道所有现有连接都存储在全局哈希表中 - “tcp_hashinfo”,您可以在/ proc / kallsyms中找到该地址。

主要功能是__inet_lookup_skb(),它调用__inet_lookup(),并拆分为__inet_lookup_established()(寻找已建立的任何匹配套接字)和__inet_lookup_listener()(寻找已打开的侦听器,但尚未建立连接)

查找所需的主要输入是源/目标端口和IP地址信息,如果发现返回指针是套接字的“struct sock *”。

IPv6具有相同的名称和相同的逻辑。

函数(__inet_lookup_skb())被声明为“静态内联” - 它不能从/ proc / kallsyms找到,驱动程序也不能看到它,因为它是内联编译的。但是没有问题,因为这会调用另外两个函数 - inet_lookup_listener()和inet_lookup_established(),它们不是内联编译的。它的符号被导出,因此您可以安全地从内核模块中使用它。

重要的是读取这个hashinfo表是一个关键操作 - 多个CPU可能同时读取/写入它,这就是为什么在读取完成时在函数的开头/结尾完成锁定的原因,在阅读时防止它被修改。由于难以访问这些RCU锁,即使它本质上是全局的,也不要重新实现这些功能,只需重用它们即可。