为什么需要lkm机制?
作为单内核,linux不像微内核那般具有天生的动态可扩展性。为了弥补这一设计上的不足,linux采用了一种lkm机制。算是对微内核的一种的扩展,使系统功能具有一定的重构性。为什么这里用一定的可扩展行性呢?写过驱动程序的都知道,每次系统重新启动后,通过sudo insmod 命令添加的lkm便消失了。如果需要,必须重新添加。为了避免每次都手动添加,可以在系统启动脚本里面添加这一条命令来折中一下。否则,如果需要lkm常驻内存的话,只能重新编译内核,等待几个小时了-_- !!!
第一部分:linux 中的 lkm
大部分的linux发行版本均支持lkm,这一点不需要担心。在linux 2.x.x编译lkm均需要通过Makefile来完成,单一的gcc命令似乎不再能胜任编译的任务了。开门见山:来一个干货: hello ustc 。
源码如下:hello.c
#include#include #include MODULE_LICENSE("GPL"); static int __init begin(void) { printk("linux kernel : Hello ustc!! \n"); return 0; } static void __exit end(void) { printk("linux kernel: Bye bye!\n"); } module_init(begin); module_exit(end);
对应的Makefile如下:
obj-m := hello.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) all: $(MAKE) -C $(KDIR) M=$(PWD) modules clean: $(MAKE) -C $(KDIR) M=$(PWD) clean
已经验证过,编译没有任何问题。如果出现任何问题,检查Makefile的空格和Tab问题(属于Makefile细节问题,如遇到问题,网上查吧)。
正常情况下,会生成hello.ko文件,sudo insmod hello.ko即可以完成模块加载工作。查看打印信息,命令为:dmesg。
一旦恶意lkm进入内核后,理论上讲:此时整个os便不再可信。因为lkm可以获得任何想要的硬件参数,修该任何想要修改的地方。例如系统调用表的修改、硬件写保护的关闭、打开...有一点编程经验的程序员均可以轻松拿到想要的数据、修改想要隐藏的数据、增加想实现的功能。
第二部分:Android 中的 lkm
在Android中,lkm开发变得异常复杂。经验证,lkm的开发完全可以实现,但是遇到的麻烦远比预期多得多。首先编译方法的资料,网络上少之又少。其次,编译后遇到的首要问题就是,大多发行版的Android默认并不支持lkm。最终,当你信心满满的重新编译内核想验证lkm的威力的时候,麻烦又来了:Android版本的碎片化很严重,lkm的加载需要版本适配。
本以为linux下的嵌入式汇编已经很恶心了,但是Andoird下的Arm指令Thumb指令才是真正的可怕。Thumb指令有区分Thumb-1 和Thumb-2指令。在写汇编的时候,需要的相对跳转的时候,可能会遇到很多麻烦,因为Arm下存在指令流水线的概念。