更改Linux内核系统调用编号

6
我想要用不同的系统调用表构建自己的自定义内核(相同的系统调用但在不同的位置/编号)。我正在使用3.2.29版本的内核。
更改内核非常容易:
1)在‫‪arch/x86/kernel/syscall_table_32.S中更改系统调用的位置
2)在arch/x86/include/asm/unistd_32.h中更改系统调用宏的编号
3)编译和安装新内核
我调换了系统调用的顺序:sys_open 代替了 sys_read 的位置和编号,反之亦然。
我认为,如果我使用修改后的内核头文件编译glibc,我可以拥有一个运行中的系统,但不幸的是,这还不够,我的系统无法启动。
我漏掉了什么吗?我需要做什么才能使系统运行?
我采取的步骤如下:
1)按照问题所述构建并安装内核
2)使用make headers_install INSTALL_HDR_PATH=[path] 提取新的内核头文件
3)使用参数--with-headers=[path/include]编译glibc
4)我使用一张Live CD以外部方式访问文件系统,以便安装新的glibc,使用make install install_root=[原始文件系统] (因此系统在安装期间不会中断)
我希望新的glibc已经构建好了,但我不确定。
之后,在引导系统时,启动停留在(initrafms) shell屏幕上:我猜我需要重建initrd,但是如何根据新的系统调用表进行编译呢?

请不要关闭有投票和答案的主题相关问题。 - Chris Stratton
在某人“乐于助人”编辑问题之前,@JonasWielicki已经解释了这是在学校任务添加新系统调用后的实验。虽然效用值得怀疑,但此处考虑的更改确实引起了注意,说明了事物的工作方式以及存在许多依赖关系。对于没有人依赖的系统进行黑客攻击可能是学习知识的好方法。 - Chris Stratton
@ChrisStratton 啊,谢谢你的澄清。学习和尝试是做事情的好方法,我只是在想 :) - Jonas Schäfer
4个回答

1
你需要重建所有东西。即使所有的二进制都是动态链接的,也有可能旧的系统调用被内联到二进制中,因为许多 C 函数只是 return syscall(__NR_somecall,...)
你可以手动完成这个过程,但是如果不使用像 buildroot、aboriginal 或类似的交叉编译工具链,则很难保持工具链的正确性。选择最适合您的工具链(我更喜欢 Rob Landley 的 aboriginal - http://landley.net/aboriginal/)。
然后为了制作您的 initrd,只需使用{z,bz,xz}cat oldinit.rd |cpio -id; rm oldinit.rd来扩展旧的initrd即可。用新的内核模块、库和二进制文件替换旧文件,然后使用 cpio 进行压缩(cpio 需要-H newc 选项)...或者现在您可以重新构建内核并将 initramfs 指向该目录,但如果您的 initrd 可能需要经常更改(例如,如果您正在测试全新的系统调用结构并需要进行大量调试),则不建议这样做。

0

混淆系统调用号码真的会造成很大的影响。你至少需要重建系统上所有静态链接的二进制文件以及initrd(如果使用)。


动态生成的应用程序中的启动代码可能还会执行一两个系统调用(如exit(2))。 - Marco van de Voort
@tmyklebu,您认为glibc可以在不使用新系统进行编译的情况下编译以在新系统上运行吗?如果可以,那么需要采取哪些一般步骤才能实现呢? - assafmo
@tmyklebu 我想要一个最小化的工作系统,所以我只会重建必要的静态链接二进制文件,但是你能给我一些关于如何为新系统重建initrd的线索吗? - 4x6hw
@tmyklebu,内核方面我还需要做哪些更改吗? - 4x6hw

0

您没有说明引导失败的具体时间点,但即使内核启动,由initrd压缩ramdisk中包含的关键程序也很可能会失败,因为它们有原始syscall号硬编码。您需要重新构建和打包这些程序。

您可以考虑首先用静态的hello-world类型程序替换init,以验证您的内核是否支持用户空间;然后研究如何使现代Linux用户空间的所有复杂性匹配。


我编辑了问题以更好地描述过程,以及引导失败的情况。 - 4x6hw

0

你必须学会阅读崩溃转储信息,并告诉我们内核发生了什么错误。没有这些信息,人们几乎无法帮助您或提供有用的建议。


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