- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我已经编写了一个将可信路径执行 (TPE) 实现到您的内核中的 LKM:
https://github.com/cormander/tpe-lkm
当我将 WRAP_SYSCALLS 定义为 1 时,我偶尔会遇到内核 OOPS(在这个问题的末尾描述),并且在我的智慧结束时试图追踪它。
一点背景:
由于 LSM 框架不导出其符号,因此我必须创造性地研究如何将 TPE 检查插入正在运行的内核中。我写了一个 find_symbol_address() 函数,它为我提供了我需要的任何函数的地址,而且它工作得很好。我可以这样调用函数:
int (*my_printk)(const char *fmt, ...);
my_printk = find_symbol_address("printk");
(*my_printk)("Hello, world!\n");
而且效果很好。我使用此方法定位 security_file_mmap、security_file_mprotect 和 security_bprm_check 函数。
然后我用 asm 覆盖这些函数,跳转到我的函数以执行 TPE 检查。问题是,当前加载的 LSM 将不再执行它 Hook 该函数的代码,因为它已被完全劫持。
这是我做的一个例子:
int tpe_security_bprm_check(struct linux_binprm *bprm) {
int ret = 0;
if (bprm->file) {
ret = tpe_allow_file(bprm->file);
if (IS_ERR(ret))
goto out;
}
#if WRAP_SYSCALLS
stop_my_code(&cs_security_bprm_check);
ret = cs_security_bprm_check.ptr(bprm);
start_my_code(&cs_security_bprm_check);
#endif
out:
return ret;
}
注意 #if WRAP_SYSCALLS 部分之间的部分(默认情况下定义为 0)。如果设置为 1,则会调用 LSM 的 Hook ,因为我将原始代码写回 asm 跳转并调用该函数,但我偶尔会遇到带有“无效操作码”的内核 OOPS:
invalid opcode: 0000 [#1] SMP
RIP: 0010:[<ffffffff8117b006>] [<ffffffff8117b006>] security_bprm_check+0x6/0x310
我不知道是什么问题。我尝试了几种不同类型的锁定方法(详见start/stop_my_code 内部)都无济于事。要触发内核 OOPS,请编写一个简单的 bash while 循环,无限地启动后台“ls”命令。大约一分钟后,它就会发生。
我正在 RHEL6 内核上对此进行测试,也适用于 Ubuntu 10.04 LTS (2.6.32 x86_64)。
虽然这种方法到目前为止是最成功的,但我尝试了另一种方法,即简单地将内核函数复制到我用 kmalloc 创建的指针,但是当我尝试执行它时,我得到: 内核试图执行受 NX 保护的页面 - 利用尝试? (uid: 0)。如果有人能告诉我如何 kmalloc 空间并将其标记为可执行文件,那也将帮助我解决上述问题。
感谢任何帮助!
最佳答案
1.看来,security_bprm_check()
的开头在调用函数之前没有完全恢复。哎呀发生在 security_bprm_check+0x6
,即在您放置在那里的跳跃之后,看起来,跳跃的某些部分在那一刻仍然存在。我现在不能说为什么会发生这种情况。
看看 Kernel Probes (KProbes) 的实现在 x86 上,它可能会给你一些提示。另见 description of KProbes了解详情。 KProbes 需要以安全的方式修补和恢复几乎任意的内核代码片段来完成他们的工作。
2.现在介绍您提到的另一种方法,即函数的复制。以下是一些 hack 并且会被内核开发人员皱眉,但如果没有其他方法,这可能会有所帮助。
您可以分配内存以将函数复制到与分配内核模块代码的内存相同的区域。默认情况下,该区域应该是可执行的。同样,KProbes 使用这个技巧来分配它们的迂回缓冲区。
内存由 module_alloc()
分配函数并由 module_free()
释放.这些函数当然不会导出,但您可以像查找 security_file_mmap()
一样找到它们的地址。等等。出于好奇,您正在使用 kallsyms_on_each_symbol()
,对吧?
如果您以这种方式分配内存,这也有助于避免另一个不太明显的问题。在 x86-64 上,可用于 kmalloc 和模块代码的内存地址区域彼此相距甚远(请参阅 Documentation/x86/x86_64/mm.txt ),超出任何相对跳转的范围。如果内存被映射到模块的地址区,你可以使用near relative jumps和calls来调用复制的函数。这种方式也避免了 RIP 相对寻址的类似问题。
编辑:请注意,在 x86 上,如果您将某些代码复制到不同的内存区域并希望它在那里运行,则可能需要对该代码进行一些更改。至少您需要修复将控制转移到复制代码之外的相关调用和跳转(例如,对另一个函数的调用等)以及具有 RIP 相对寻址的指令。
除此之外,代码中可能还有其他结构需要修复。例如,编译器可能优化了部分甚至全部 switch
。语句通过表跳转。也就是说,每个 case
的代码块地址保存在内存中的表中,开关变量是该表的索引。这样,您的模块将执行类似 jmp <table_start>(%reg, N)
的操作,而不是进行多次比较。 (N 是指针的大小,以字节为单位)。也就是说,只是跳转到表中适当元素中的地址。因为此类表是在您复制代码之前为代码创建的,所以可能需要进行修复,否则此类跳转会将执行带回到原始代码段而不是复制的代码段。
关于linux - 在 linux 内核中包装函数时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6434701/
总的来说,我对 Linux 内核和操作系统非常感兴趣。我想知道的是,内核的文件类型或扩展名是什么?它显然没有 .exe 或 .out 扩展名,因为它们用于安装在操作系统上的应用程序。 内核只是一个二进
我需要为 Raspbian Linux 内核添加一个自己的系统调用。现在我在搜索了大约 2 天以找到解决方案后陷入困境。 要加一个系统调用,我基本上是按照大纲来的( http://elinux.org
对于一个学术项目,我希望将源文件 (myfile.c) 添加到 kernel/目录,与exit.c相同的目录和 fork.c .构建系统似乎不会自动获取新文件,因为我在 myfile.c 中定义的函数
浏览器排行榜 浏览器市占率排行榜全球榜 。 浏览器市占率排行榜中国榜 -快科技 。 如果按照浏览器内核来看, Chromium 内核的市场占有率无疑是最大的,一家独大
给定一个进程或线程的任务结构,迭代属于同一进程的所有其他线程的习惯用法是什么? 最佳答案 Linux 不区分进程(任务)和线程。库调用 fork() 和 pthread_create() 使用相同的系
我正在用c(不是linux。完全从头开始)从头开始制作一个内核,但我遇到了一些问题。我有这个代码: #include "timer.h" int ms = 0; void timer_handler(
我正在从头开始制作一个 C 内核,我实际上只是从网站上复制了这段代码,因为我的代码无法工作,所以我很困惑。 void kmain(void) { const char *str = "my f
我不确定,如果我完全理解上述差异,所以我想自己解释一下,你可以打断我,只要我有错:“内核是创建内核线程的初始代码段。内核线程是由内核管理的进程。用户线程是进程的一部分。如果你有一个单线程进程,那么整个
看一下struct file 定义from this code Linux 内核版本 2.6.18。 我正在尝试比较代码中的两个 struct file 变量,并确定它们是否指的是同一个文件。该结构中
我试图在 Linux 启动时使嵌入式设备中的 LED 闪烁。基本上,LED 闪烁表明 Linux 正在启动。为了使 LED 闪烁,我正在做以下事情 在 init/main.c 中创建了一个全局定时器(
我有一些在 FreeBSD 和 Linux 上运行的特定硬件。 我必须做一个用户空间应用程序,它将使用内核/用户空间应用程序之间的共享内存与驱动程序一起工作。我的应用程序对来自用户空间的共享内存进行忙
我在哪里可以找到 linux 内核中相应函数的解释,特别是对于 ICMPv4? 例如:icmp_reply、icmp_send等 感谢您的帮助。 最好的,阿里木 最佳答案 探索 Linux 内核中的
我在 Linux Kernel 3.4 上工作,我有以下代码: /* Proximity sensor calibration values */ unsigned int als_kadc;
我正在阅读“罗伯特·洛夫 (Robert Love) 撰写的 Linux 内核开发第 3 版”,以大致了解 Linux 内核的工作原理..(2.6.2.3) 我对等待队列的工作方式感到困惑,例如这段代
我之前也问过同样的问题,但是我的帖子不知为何被删除了。 无论如何,我正在尝试使用 C++ 并编写一个允许我直接访问内存并向其中写入内容的程序。我听说我需要对内核做一些事情,因为它是连接操作系统和应用程
在尝试了解 Ruby 执行方法时,我找到了这篇关于在 Ruby 中运行命令的五种方法的博文 http://mentalized.net/journal/2010/03/08/5_ways_to_run
是否有 Linux 发行版(Minix 除外)包含良好的源代码文档?或者,是否有一些好的文档来描述一般的 Linux 源代码? 我已经下载了内核源代码,但是(不出所料)我有点不知所措,我想知道是否有一
有谁知道 linux 中的哪个函数或文件包含查找用于 bind() 系统调用的随机端口的算法?我到处寻找,在 Linux 源代码中找不到包含此算法的方法。 谢谢! 最佳答案 这是一段又长又复杂的代码,
前言 首先,对于有科班背景的读者,可以跳过本系列文章。这些文章的主要目的是通过简单易懂的汇总,帮助非科班出身的读者理解底层知识,进一步了解为什么在面试中会涉及这些底层问题。否则,某些概念将始终
CentOS7.2与CentOS6区别及特点 Linux 操作系统的启动首先从 BIOS 开始,接下来进入 boot loader,由 bootloader 载入内核,进行内核初始化。内核初始化的
我是一名优秀的程序员,十分优秀!