编写 Android 内核模块的尝试(二)

内核模块终于生成了,adb shell push 到了手机上,用 insmod 加载时,报:insmod: init_module ‘fklmModule.ko’ failed (Operation not permitted)。

看到有个地方(https://www.quora.com/How-can-I-execute-an-insmod-custom-module-on-Android)有人说他解决这个问题的措施了,有两条,第一条是编译时要加上 CFLAGS_MODULE=-fno-pic;另一条是要把模块的哈希值写入到 /module_hashes 文件里。他的原文是:

Hongmin Yang, studied at Hanyang University
Written 2 Jul 2014

I solved this problem 😀

1. make module with CFLAGS_MODULE=-fno-pic
– but I couldn’t understand its meaning
– any link or reply is welcome
2. add hash value to /module_hashes (it requires modifying ramdisk)
– in my case (moto g), init.mmi.rc copies it to /sys/kernel/module_whitelist.
so ramdisk must be modified.
– but how can I read hash value of a module directly? I get it by dmesg.
– modinfo didn’t show me hash value

经过查看,哈希值应该是 SHA1 的,因此在编译机上用 sha1sum 计算出模块的哈希值后,要把它插入到该文件中。首先要 mount -o remount -o rw / 把根文件系统加载成读写,还要把 module_hashes 文件的权限从仅 root 只读,搞成仅 root 读写;写入后用 cat 查看成功,但是 insmod 错误没变;又把第一条的更改也做了,还没有改观。

小兄弟友情提醒我说,是不是检查许可协议时出问题了,我突然觉得还真有可能,因为我写代码的时候手一欠把 GPL 改成了 LGPL。在网上有人说这个必须是 GPL,还把内核此处进行检查的代码列了出来(见 2.6 的内核,kernel/Module.c):

我一看,发现如果许可协议不对的话,应该会输出信息到 dmesg 里,但是用 dmesg | grep -i license 命令并没有找到东西,于是直接查看 dmesg 的完整输出,发现了令人震惊的结果,插入到 module_hashes 中的竟然没有生效,会有一条这样的信息:module-whitelist: Module hash not found in whitelist: 58d44…888b0。

期间,用 lsmod 列出过手机自带的动态模块,只有一个,叫 touchx,可以用 rmmod 卸载掉,也可以用 insmod /system/lib/modules/touchx.ko 再次成功加载。我甚至 remount 了 /system,把我的模块复制到了相同位置,也是不可以的。

截止到目前,怀疑 module_hashes 是在引导时读入的,之后就不会理会这个文件的变化了。尝试重启,重启后发现刚刚的修改并没有永久化,这也是为什么原文说到需要改 RAM disk。这个帖子(https://sourceforge.net/motorola/motox/discussion/general/thread/be703eaf/?limit=50)里说的很清楚:

Tal Aloni – 2014-05-07

The Moto G \ Moto X kernel implements a white-list mechanism to prevent the user from loading unknown modules into the kernel.
The white-list is part of the kernel (boot.img) and AFAIK you cannot modify it without unpacking, repacking and flashing the kernel.

(if you unpack boot.img, you will notice the ‘module_hashes’ file in the root directory, which contains the allowed SHA1 hashes)

This file is copied to ‘/sys/kernel/module_whitelist’ every boot (scripted in init.mmi.rc which is also part of the kernel),
There’s a kernel module that will make sure ‘/sys/kernel/module_whitelist’ is only written once and additional write attempts are ignored.

实现上述功能的代码位于 module-whitelist.c 中,看起来其自身似乎也是一个内核模块。于是考虑遍历内核中所有的模块,看能不能找到 check_module_hash 这个函数,然后对它做点手脚。很显然,突破这个函数的封锁只能为后人乘凉提供便利,自己还是需要走修改 ROM 里自带的白名单这条路的。

发表评论

电子邮件地址不会被公开。 必填项已用*标注