在Linux内核3中替换系统调用

4

1
你需要替换一个系统调用,而不是添加一个新的系统调用,有什么原因吗? - kba
@Kristian,这样做是为了使用内核模块来监视通过给定系统调用进行的调用。希望这样做是为了调试目的 :-) - jdehaan
他为什么不能修改源代码中现有的调用呢?它们都应该在arch/<architecture>/kernel/中可用。 - kba
@Kristian,因为你需要重新编译内核,所以更容易的方法是编译并插入一个内核模块来激活“功能”,然后使用rmmod命令来停用它。 - jdehaan
同时,是的,我不想要一个包含重新编译内核过程的解决方案 :) - Panos
显示剩余5条评论
2个回答

6
我建议使用kprobes来完成这种工作,您可以轻松地在任何内核地址(或符号...)上中断并更改执行路径,所有这些都可以在运行时通过内核模块进行。
Kprobes的工作原理是通过动态替换指令(例如您的系统调用入口的第一个指令)为断点(例如在x86上的int3)。在do_int3处理程序中,notifier通知kprobes,然后将执行传递到您注册的函数,从此处开始,您可以做几乎任何事情。 Documentation/kprobes.txt提供了非常好的文档,例如在samples/kprobes/kprobes_example.c中的一个小例子(在此示例中,它们在do_fork上中断以记录系统上的每个fork)。它具有非常简单的API,并且现在非常便携。

警告: 如果您需要更改执行路径,请确保您的 kprobes 没有被优化(即 jmp 指令到您的处理程序替换了您打断的指令,而不是 int3),否则您将无法轻松地更改执行(在函数返回之后,系统调用函数仍将像往常一样执行)。如果您只对跟踪感兴趣,则可以忽略此问题。


没错!我会调查你建议的kprobe,并在我的情况下回复是否有效 :) 谢谢!!! - Panos
我调查了jprobes,它真的很棒!我的唯一担忧是我不知道当accept系统调用接受一个套接字连接时调用哪个内核例程 :( - Panos
对于TCP连接,使用tcp_connect!现在我只需要找到新UDP连接的调用! - Panos
很高兴它能满足你的需求 :) 通常要在内核中找到系统调用函数,只需要添加前缀 sys_,所以对于所有的 accept (tcp 和 udp),你通常会在 sys_accept 上断点。是的,当你想要跟踪时,jprobes 真的很好用!还有更高级别的接口,它们在内部使用 kprobes,你可能会发现它们很有用,比如 ftrace:你甚至不需要编写一个内核模块,而是可以使用 debugfs 中的接口,阅读 Documentation/trace/ftrace 获取更多信息。还有审计子系统,但你需要编写一个守护进程。 - Quentin Casasnovas
你能否请看一下这里http://stackoverflow.com/questions/8314291/extract-information-from-struct-socket? :)我监控4个内核函数,用于传入、传出TCP和UDP连接,而不是监控sys_connect和sys_accept(没找到它们:( )。 - Panos
显示剩余7条评论

1

编写一个更好的LKM选项。您所说的替换是什么意思,您想要添加一个新的吗。


我不想添加一个新的。我希望在系统调用被调用时收到通知,并从其参数中提取一些信息。 - Panos
替换和添加是软件工程中两个基本且不含糊的操作。你真的需要问替换是否意味着添加吗?</被动挑衅> - Eric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接