前言
这几天在踩内核编译的坑,笔者虽然参考了许多帖子,但由于谷歌今年更新了内核编译的方法,也就是说一年前的文章参考意义不大,而今年的文章总是会有些许描述模糊或遗漏的地方,众所周知内核编译这个东西稍有差池等于失败,所以本文会尽可能详细的记录每一步的操作,希望后续的人少走一些弯路
环境配置
环境 |
配置 |
VMware |
16.1.1 build-17801498 |
Ubuntu |
Ubuntu 20.04.2 LTS |
物理机内存 |
32G |
虚拟机内存 |
16G |
物理机储存 |
2T |
虚拟机内存 |
1T |
目标机型 |
Pixel 4 |
目标版本 |
Android 10 |
分支版本 |
android-10.0.0_r9 |
下载内核源码
正常来讲在 https://source.android.com/setup/building-kernels 中应该可以查询到 pixel4 的内核
1 | Pixel 4 (flame) device / google / coral - kernel android - msm - coral - 4.14 - android13
|
但在这里对于萌新有个坑,官网只给出了 android13 的内核,我们要编译的 android10 在哪里?(这里踩了个大坑,我最开始一直以为这个 git 包含了4-13的所有分支,最离谱的是还能正常 check out android 10 的分支)访问 https://android.googlesource.com/kernel/manifest/+refs 搜索 android-msm-coral-4.14-android 我们可以得到如下信息,与 android10 匹配的共有四条,之间区别不太清楚,有知晓的大佬可以告知下,先行谢过,笔者这里亲测 android10-qpr3 是可用的
1 2 3 4 5 6 7 8 9 10 11 12 | android - msm - coral - 4.14 - android10
android - msm - coral - 4.14 - android10 - c2f2
android - msm - coral - 4.14 - android10 - qpr1
android - msm - coral - 4.14 - android10 - qpr3
android - msm - coral - 4.14 - android11
android - msm - coral - 4.14 - android11 - qpr2
android - msm - coral - 4.14 - android11 - qpr3
android - msm - coral - 4.14 - android12
android - msm - coral - 4.14 - android12 - qpr1
android - msm - coral - 4.14 - android12 - v2 - beta - 2
android - msm - coral - 4.14 - android12L
android - msm - coral - 4.14 - android13
|
在可以科学上网的情况,我们可以使用下方的命令获取内核源码
1 | repo init - u https: / / android.googlesource.com / kernel / manifest - b android - msm - coral - 4.14 - android10 - qpr3
|
为了加速下载,当然是使用国内的镜像
1 2 | echo "REPO_URL='https://gerrit-googlesource.proxy.ustclug.org/git-repo'" >> ~ / .bashrc
source ~ / .bashrc
|
但有时候使用了上方的配置还是会失败,笔者这里选择一劳永逸直接修改 repo 文件,在约 130 行处替换 https://gerrit.googlesource.com/git-repo 为 https://gerrit-googlesource.proxy.ustclug.org/git-repo
禁用 ssl 验证,否则会失败
1 2 | git config - - global http.sslverify false
git config - - global https.sslverify false
|
设置拉取的目标文件,这里同样使用国内的镜像源
1 2 3 4 5 6 7 8 9 10 11 12 13 | mkdir ~ / bin / android - kernel && cd ~ / bin / android - kernel
repo init - u git: / / mirrors.ustc.edu.cn / aosp / kernel / manifest - b android - msm - coral - 4.14 - android10 - qpr3
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
注意:下面的提示表示更新成功,并不是报错
Downloading Repo source from https: / / gerrit - googlesource.proxy.ustclug.org / git - repo
repo: Updating release signing keys to keyset ver 2.3
Your identity is : lxz < 211527456 @qq.com>
If you want to change this, please re - run 'repo init' with - - config - name
repo has been initialized in / home / lxz / bin
|
拉取内核源码
查询手机内核版本
为了在众多内核中准确找到我们真机对应的内核版本,可以在真机系统中输入以下命令查询 short commit id,其中 4.14.111-g 后边的为 short commit id
1 2 3 | flame: /
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Linux version 4.14 . 111 - gb3ac0fc2b0f7 - ab5912761 (android - build@abfarm - us - east1 - c - 0082 ) (Android ( 5484270 based on r353983c) clang version 9.0 . 3 (https: / / android.googlesource.com / toolchain / clang 745b335211bb9eadfa6aa6301f84715cee4b37c5 ) (https: / / android.googlesource.com / toolchain / llvm 60cf23e54e46c807513f7a36d0a7b777920b5881 ) (based on LLVM 9.0 . 3svn ))
|
编译内核源码
如果当前的环境并未编译过 android 源码,那么需要配置如下的环境依赖,已经编译过 android 的源码那么可以跳过此步骤
1 | sudo apt - get install git - core gnupg flex bison build - essential zip curl zlib1g - dev gcc - multilib g + + - multilib libc6 - dev - i386 libncurses5 lib32ncurses5 - dev x11proto - core - dev libx11 - dev lib32z1 - dev libgl1 - mesa - dev libxml2 - utils xsltproc unzip fontconfig libncurses5
|
在安装完上述依赖后,不论你是否编译过 android 源码都还需再安装 libssl-dev
1 | sudo apt - get install libssl - dev
|
切换到我们手机当前版本的内核源码分支
1 2 | cd ~ / bin / android - kernel / private / msm - google
git checkout b3ac0fc2b0f7
|
执行编译脚本,编译完成后的镜像 Image.lz4 存放在 ~/bin/android-kernel/out/android-msm-floral-4.14/dist 目录中
1 | ~ / bin / android - kernel / build / build.sh
|
编译时遇到报错
1 2 3 | . / security / selinux / include / classmap.h: 245 : 2 : error:
- git a / scripts / selinux / mdp / mdp.c b / scripts / selinux / mdp / mdp.c:
|
解决方案参考 编译错误 error New address family defined, please update secclass_map.解决
修复触屏
如果你此时将 Image.lz4 文件直接替换为 aosp 中的 Image.lz4 就直接编译刷机,那么你将得到一部触屏失效的 Pixel 4,所以还需要一些处理,方法主要参考 eBPF on Android之编译内核与打补丁(解决触摸和WIFI失效问题),大佬的帖子里有修复原理的详细分析,感谢 seeeseee 大佬的分享,但大佬的帖子中包含了 eBPF 的开启,我们这里暂时不需要,步骤会做一些精简。我的理念是一步一步操作,如果遇到问题,可以即时的发现问题,如果一次性操作太多,一旦出现问题就很难定位,所以我建议你先将触屏失效的手机做出来再解决触屏失效的问题。
解包 boot.img
使用 Android-Image-Kitchen 解包手机当前使用的 boot.img(boot.img 拖到 unpackimg.bat 即可),此时我们可以得到如下信息(信息拷贝一份留着有用),以及 split_img\boot.img-ramdisk.cpio.gz,我们手动将 split_img\boot.img-ramdisk.cpio.gz 解压,将得到的 boot.img-ramdisk.cpio 文件拷贝到 ~/bin/android-kernel 目录下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ANDROID! magic found at: 0
BOARD_KERNEL_CMDLINE console = ttyMSM0, 115200n8 androidboot.console = ttyMSM0 printk.devkmsg = on msm_rtb. filter = 0x237 ehci - hcd.park = 3 service_locator.enable = 1 androidboot.memcg = 1 cgroup.memory = nokmem usbcore.autosuspend = 7 androidboot.usbcontroller = a600000.dwc3 swiotlb = 2048 androidboot.boot_devices = soc / 1d84000 .ufshc buildvariant = userdebug
BOARD_KERNEL_BASE 0x00000000
BOARD_NAME
BOARD_PAGE_SIZE 4096
BOARD_HASH_TYPE sha1
BOARD_KERNEL_OFFSET 0x00008000
BOARD_RAMDISK_OFFSET 0x01000000
BOARD_SECOND_OFFSET 0x00f00000
BOARD_TAGS_OFFSET 0x00000100
BOARD_OS_VERSION 10.0 . 0
BOARD_OS_PATCH_LEVEL 2019 - 10
BOARD_HEADER_VERSION 2
BOARD_HEADER_SIZE 1660
BOARD_DTB_SIZE 1002744
BOARD_DTB_OFFSET 0x01f00000
|
配置 mkbootimg 脚本
将 mkbootimg.py 拷贝到 /home/lxz/bin/android-kernel 目录下
修改脚本文件
打开脚本文件 build.sh
1 | gedit ~ / bin / android - kernel / build / build.sh
|
在约 396 行处添加代码,作用是将boot.img-ramdisk.cpio
复制到产物目录下,参与后续打包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | if [ - n "${ABI_DEFINITION}" ]; then
echo "========================================================"
echo " Copying abi definition to ${DIST_DIR}/abi.xml"
pushd $ROOT_DIR / $KERNEL_DIR
cp "${ABI_DEFINITION}" ${DIST_DIR} / abi.xml
popd
fi
if [ - f "${VENDOR_RAMDISK_BINARY}" ]; then
cp ${VENDOR_RAMDISK_BINARY} ${DIST_DIR}
fi
echo "========================================================"
echo " Files copied to ${DIST_DIR}"
|
编译内核
KERNEL_CMDLINE、BASE_ADDRESS、PAGE_SIZE 的值来自于上边的解包信息,过程中会在LTO vmlinux.o
这里卡一段时间并报警告,多多多多多多等一会儿即可,编译完成后的镜像 Image.lz4 存放在 ~/bin/android-kernel/out/android-msm-floral-4.14/dist 目录中
1 2 3 | cd ~ / bin / android - kernel
BUILD_CONFIG = private / msm - google / build.config BUILD_BOOT_IMG = 1 MKBOOTIMG_PATH = mkbootimg.py VENDOR_RAMDISK_BINARY = boot.img - ramdisk.cpio KERNEL_BINARY = Image.lz4 BOOT_IMAGE_HEADER_VERSION = 2 KERNEL_CMDLINE = "console=ttyMSM0,115200n8 androidboot.console=ttyMSM0 printk.devkmsg=on msm_rtb.filter=0x237 ehci-hcd.park=3 service_locator.enable=1 androidboot.memcg=1 cgroup.memory=nokmem usbcore.autosuspend=7 androidboot.usbcontroller=a600000.dwc3 swiotlb=2048 androidboot.boot_devices=soc/1d84000.ufshc buildvariant=userdebug" BASE_ADDRESS = 0x00000000 PAGE_SIZE = 4096 build / build.sh
|
重打包 boot.img
将 Image.lz4 重命名为 boot.img-kernel,拷贝到 Android Image Kitchen\split_img 目录下替换原本的 boot.img-kernel,此时执行 repackimg.bat 会得到 image-new.img,执行下方的命令将其刷入手机,此时等待手机重启即可
1 2 3 | adb reboot bootloader
fastboot flash image - new.img
fastboot reboot
|
添加 Log
既然我们已经成功的编译内核了,那我们有理由选择留下一些自己的内核 Log,比如说通过修改函数 do_sys_open
1 | gedit ~ / bin / android - kernel / private / msm - google / fs / open .c
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | long do_sys_open( int dfd, const char __user * filename, int flags, umode_t mode)
{
struct open_flags op;
int fd = build_open_flags(flags, mode, &op);
struct filename * tmp;
/ / add
const struct cred * cred = current_cred();
kuid_t uid = cred - >uid;
int pid = current - >pid;
int myuid = uid.val;
if (myuid > 10000 ) {
char bufname[ 256 ] = { 0 };
strncpy_from_user(bufname, filename, 255 );
printk( "lxzLog do_sys_open pathname:%s uid:%d pid:%d\n" , bufname, myuid, pid);
}
/ / add
if (fd)
return fd;
tmp = getname(filename);
if (IS_ERR(tmp))
return PTR_ERR(tmp);
fd = get_unused_fd_flags(flags);
if (fd > = 0 ) {
struct file * f = do_filp_open(dfd, tmp, &op);
if (IS_ERR(f)) {
put_unused_fd(fd);
fd = PTR_ERR(f);
} else {
fsnotify_open(f);
fd_install(fd, f);
}
}
putname(tmp);
return fd;
}
|
重新编译内核刷进手机,在 cmd (power shell 不支持 &)中直接使用如下的命令就可以查看属于自己的内核 Log 了
1 2 3 4 5 6 7 8 9 | adb root & adb shell dmesg | findstr lxzLog
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[ 5.973256 ] lxzLog do_sys_open pathname: / proc / 1662 / timerslack_ns uid: 10094 pid: 1662
[ 5.973305 ] lxzLog do_sys_open pathname: / proc / thread - self / attr / current uid: 10094 pid: 1662
[ 5.973454 ] lxzLog do_sys_open pathname: / sys / fs / selinux / context uid: 10094 pid: 1662
[ 5.974109 ] lxzLog do_sys_open pathname: / proc / thread - self / attr / current uid: 10094 pid: 1662
[ 5.975541 ] lxzLog do_sys_open pathname: / sys / devices / system / cpu / online uid: 10094 pid: 1662
[ 5.978139 ] lxzLog do_sys_open pathname: / proc / self / cmdline uid: 10094 pid: 1662
[ 5.979101 ] lxzLog do_sys_open pathname: / dev / binder uid: 10094 pid: 1662
|
eBPF安全开发与攻防对抗
最后于 1天前
被简单的简单编辑
,原因: