c - 通过 LD_PRELOAD 插入 JVM 时卡在关闭套接字上

标签 c sockets

我通过 LD_PRELOAD 变量插入 JVM。

基本上,我想构建一个虚拟路由表(VRT)。在调用 bind() 时,我将 IP 地址和端口参数修改为我的选择(我将其保存在 VRT 中)。另外,我将套接字描述符(bind() 的第一个参数)添加到链接列表中。 (到目前为止,套接字的 sin_family 类型为 AF_INET6)。

现在,当套接字关闭(close())时,我想删除虚拟路由表条目。因此,我检查我们尝试关闭的套接字描述符是否存储在链接列表中。如果是,则意味着它的记录存在于VRT中,因此我应该在关闭套接字之前删除VRT条目。我面临的问题是,在这个阶段,同一个套接字描述符的 sin_family 值为 1(我不知道它代表什么)而不是 10(AF_INET6,bind() 期间的值)。此外,我尝试在这个阶段打印套接字描述符的IP地址和端口,但它是垃圾。

我不知道我错过了什么。

更新: 我的代码没有问题。出现异常的原因是 JVM 的以下行为(我通过 strace 跟踪)

9722  socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 12
...(receive messages)...
9722  dup2(11, 12)                      = 12 (?!?)
9722  close(12)                         = 0

JVM 在我们的套接字上复制了另一个文件描述符,因此它的 sin_family 在 close() 上无法正确显示。奇怪!

最佳答案

sin_family == 1AF_UNIX,即管道或域名套接字。

<小时/>

您确定它确实是“相同”的套接字描述符吗?但你如何识别它呢?它的整数值仅对进程是唯一的。

如果您正在 LD_PRELOAD fork 子进程,他们也会使用您的钩子(Hook),使用与父进程相同的描述符集,并且它们的所有 sibling 和子进程都会这样做。

因此,为了解决这个歧义,请在 Hook bind() 代码中使用 getpid() 获取 PID,并将 PID 添加到您为此套接字存储的 key 中。

<小时/>

dup2(int fdOld, int fdNew) 在将 fdNew 复制为 fdOld 之前关闭它。但我想你不能将调用挂接到 close() 上:-(。

关于c - 通过 LD_PRELOAD 插入 JVM 时卡在关闭套接字上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10437146/

相关文章:

java - 我可以在 Android 上调用从 Java 内部生成图像的 C 程序吗?

Java 套接字编程

php - MySQL localhost/127.0.0.1 问题

ios - Socket.io 不会按需关闭套接字(并且不允许我的 swift 应用程序再次重新连接到 node.js 服务器)

c - 从套接字读取字符串时,不打印第一个字符

c++ - 非 native 类型上具有多个条件的 GDB 断点

python - 如何使用 pyhunspell 向 .dic/.aff 文件添加新词?

c - UDP 缓冲区溢出而没有填充接收缓冲区?

c - 如何在 C 中扩展二维动态数组?

c - 为什么我的值还是5