type
status
date
slug
summary
tags
category
icon
password
 
💡
如果是虚拟机编译内存要求18G及以上(或交换分区32G),防止内存不够杀掉编译进程,为什么是18呢,因为试过16G会死(link-vmlinux.sh:行 101: 609008 已杀死 ${LD} ${KBUILD_LDFLAGS} -r -o ${1} $(l) … 。如果使用WSL配合docker

1. 拉取官方内核

  • 安装必要依赖
    • 通过cat /proc/version 查看内核信息
      • Linux version 4.19.202-g5fbe36ea56f7-ab8008033 (build-user@build-host) (Android (7284624, based on r416183b) clang version 12.0.5 (https://android.googlesource.com/toolchain/llvm-project c935d99d7cf2016289302412d708641d52d2f7ee), LLD 12.0.5 (/buildbot/src/android/llvm-toolchain/out/llvm-project/lld c935d99d7cf2016289302412d708641d52d2f7ee)) #1 SMP PREEMPT Thu Dec 16 06:08:11 UTC 2021
     
     
    • 进入具体的分支,查看其中的default.xml ,重点关注<project path="build" name="kernel/build" ,如果revision的值为main,请千万不要下载,否则你就会发现下载下来之后根本无法build!!,这是由于build仓库和内核源码仓库不同步导致的
      • notion image
        notion image
    • 进行内核编译,在这之前需要配置好repo,并且最好配置全局的源为清华源,这部分参照源码编译部分
      • 等待完成(大概需要60G以上的磁盘空间,耗时两小时左右)后需要进行checkout 。这里的分支是依据Linux version 4.19.224-gf75e15ae64d0-ab8115056 (build-user@build-host)g后的字符串决定的。
        • 拉取后的源码git仓库分为三部分:android-kernel 是拉取源码的根目录,然后是msm-google以及build,其中msm-google 是内核源码仓库,任何对内核的更改提交位于该仓库,build的负责编译的仓库,任何对编译配置等提交位于该仓库。android-kernel 无需add内容或者提交commitmsm-google 以及build 在修改后需要进行提交commit,否则编译的内核会是dirty的。
          notion image
          notion image

      2. 提取boot.img-ramdisk.cpio.lz4

      • 修改build.sh
        • 在内核源码根目录,进入build/build.sh,找到下方代码的位置
        • 并在这两行代码之前加上下列命令
       
      然后需要修改编译参数GKI_RAMDISK_PREBUILT_BINARY,使得ramdisk被打包进入boot.img
      具体见第六节
       
       

      3. 嵌入rwProcMem33

      • 修改rwProcMem33 中的 ver_control.h MY_LINUX_VERSION_CODE切换到对应的安卓内核版本,这里本来就是4.19.224,与4.19.113接近所以不需要更改了。
        • notion image
      • Linux 4.11前,Linux内核把页表分为4级
        • 页全局目录(Page Global Directory,PGD)
        • 页上层目录(Page Upper Directory,PUD)
        • 页中间目录(Page Middle Directory,PMD)
        • 直接页表(Page Table,PT)
        • 所以对于Linux version 4.11以下的内核版本,并不支持五级页表,选择启用读取pagemap文件来计算物理内存的地址,同时注释掉启用页表计算物理内存的地址
          notion image
          Linux version 4.11版本把页表扩展到五级,在页全局目录和页上层目录之间增加了页四级目录(Page 4th Directory,P4D)。所以对于Linux version 4.11及以上的内核版本,选择启用页表计算物理内存的地址,同时注释掉启用读取pagemap文件来计算物理内存的地址 。这里是默认情况,所以不进行更改。
          notion image
      • rwProcMem33/linux_kernel_api文件夹中新建一个头文件linux_kernel_api.h 写入
        • 为了包含linux_kernel_api.h头文件,在api_proxy.h的前几行中加入#include "linux_kernel_api/linux_kernel_api.h"
          • notion image
        • private/msm-google/drivers/Makefile的开头加入下列命令
          • notion image
        • 在编译rwProcMem33内核模块时,由于内核编译时会将警告视为错误导致编译内核停止,所以我们要修改Makefile来忽视warning。在private/msm-google/Makefile找到如下位置,在-Wno-format-security后加上一个-w参数
          • notion image
         

        4. 编译内核

        在安卓内核源码的根目录打开终端使用如下命令开始编译
        命令的参数为使用android-image-kitchen解包boot.img之后,控制台所打印的参数请务必替换为相对应的参数!!!
        参数对应关系为
        生成的imgandroid-kernel/out
        notion image
         
        💡
        注意,任何对于kernel源码的改动均需commit,如果不进行commit将会导致内核版本带有dirty+等字样,可能影响环境检测。这里添加了新的rwProcMem33 并且在其内部进行了修改,那么就进入private 目录先add新内容,再进入rwProcMem33文件夹手动提交内部模块的commit,然后在外部进行commit,直到git status不出现其他信息

        5. Magisk修补

        boot.img复制到设备中,然后使用设备中的Magisk APP选择安装修补
         

        6. 刷入内核

        正常的操作一定是下面这样的,但是实际发现存在问题
        刷了整整两天Pixel5的内核,包括尝试刷入编译生成的vendor_boot.img 等各种方案,但是很不幸,不是卡google就是一直循环bootloader重启。
        后来看到了参考2中Droid SMU的回复。他提示先执行根目录下的build_redbull.sh进行编译,然后将编译后的kernel/out/android-msm-pixel-4.19/dist/中的
        Image.lz4, Image.lz4-dtb, kernel-uapi-headers.tar.gz and all the *.ko kernel moduleskernel/out/android-msm-pixel-4.19/dist/ 复制到 aosp/device/google/redbull-kernel 中(建议先创建该文件夹备份),然后make -j8编译aosp 。编译完成后将kernel/out/android-msm-pixel-4.19/dist/中的vendor_boot.img 复制到AOSP目录下out/target/product/redfin 中。然后通过fastboot flashall -w 刷写即可。
         
        但是这样是需要编译AOSP的,如何不使用AOSP直接编译内核并替换是个问题,实际经过解img可以发现,vendor_boot.img在单独编译和放入aosp编译得到的文件结构是基本一致的,但是boot.img确有很大差别
        如下图所示,左侧为内核独立编译后boot.img解包后的文件结构,右侧为使用AOSP编译的内核。
        notion image
        通过查看MKBOOTIMG 的参数可以发现--ramdisk /android-kernel/prebuilts/boot-artifacts/ramdisks/ramdisk-aosp_arm64.img 指定了一个奇怪的img。
        再查看private/msm-google/source/build.config.redbull.common 发现就是GKI_RAMDISK_PREBUILT_BINARY=${ROOT_DIR}/prebuilts/boot-artifacts/ramdisks/ramdisk-aosp_arm64.img 指向的内容,从而使其认为ramdisk实际是这个img提供的,再看LZ4_RAMDISK=1 那么将GKI_RAMDISK_PREBUILT_BINARY 指向提取的boot.img-ramdisk.cpio.lz4 即可。
        🔥
        正确的做法:手动指定private/msm-google/source/build.config.redbull.common 中的
        GKI_RAMDISK_PREBUILT_BINARY=${ROOT_DIR}/boot.img-ramdisk.cpio.lz4 这样才会把bootramdisk 打包进入boot.img

        在不使用 init_boot 的情况下为设备构建启动映像

        对于没有 init_boot 分区的设备来说,您需要一个 ramdisk 二进制文件,该二进制文件可以通过下载 GKI 启动映像后解压缩来获取。关联的 Android 版本中的任何 GKI 启动映像都可以使用。
        目标文件夹是内核树的顶级目录(当前的工作目录)。
        如果您使用 AOSP master 进行开发,则可以从 ci.android.com 上的 aosp_arm64 build 中下载 ramdisk-recovery.img 构建工件,并将其用作 ramdisk 二进制文件。
        当您拥有 ramdisk 二进制文件并将其复制到内核 build 的根目录中的 gki-ramdisk.lz4 时,可以通过执行以下命令来生成启动映像:
        如果您使用的是基于 x86 的架构,请将 Image 替换为 bzImage,将 aarch64 替换为 x86_64
        该文件位于工件目录 $KERNEL_ROOT/out/$KERNEL_VERSION/dist 中。
        启动映像位于 out/<kernel branch>/dist/boot.img
        还有人提到另外的解决方案,但是很显然,在实际测试过程中发现编出的ko文件已经被打包进入vendor_boot.img 所以不是这个问题。但是鉴于可能以后会有这样的问题,先把答案留在这。
         
        李大锐
        This is the script I use to launch a custom kernel which is working on pixel 4a. The key is
        flashing boot.img twice after sending *.ko.
        I think the the root cause is that the ko file built by the kernel does not enter the boot.img built by aosp. To fundamentally solve this problem a correct boot.img might be needed.
         

        7. 编译HwBpClient客户端

        首先在VS installer中安装MFC支持
        notion image
        拉取项目进入rwProcMem33\hwBreakpointProcModule\testHwBpClient文件夹,使用vs打开进行项目编译 在testHwBpClientDlg.cpp的这个位置进行修改,将这个位置的llX改为I64X%zu改成I64d,否则将无法正确输入内容。即修改677 - 701行内容,替换成下面的代码。
        notion image
        使用ctrl-B 生成exe
        notion image
         
         

        8. 编译HwBpServer服务端

        编译HwBpServer服务端需要NDK,并将NDK引入环境变量中
        NDK可以在android studio中进行安装,依次点击File->Project Structure->SDK Location,找到Android NDK location,点击Download即可开始安装,我这里使用的ndk的版本为ndk25.2.9519653如果没有安装Android studio,NDK的安装方法可以在谷歌上找到
        NDK安装完成后,进入到rwProcMem33\hwBreakpointProcModule\testHwBpServer\jni,打开cmd运行命令ndk-build 。如果没有添加到环境变量可以直接找到ndk文件夹中ndk-build.cmd 拖到cmd或者powershell中,在jni 目录下执行。
        编译后的文件在rwProcMem33\hwBreakpointProcModule\testHwBpServer\libs中,选择对应手机架构的ELF,push到手机中运行即可
        notion image
        notion image
         
         

        #参考

        1. 将rwProcMem33编译进安卓内核 | 看雪
        1. 如何编译并运行 Pixel 6 的自定义内核 | XDA
        1. Google Groups Problem about pixel kernel build
        1. 无法使用自定义构建内核刷新/启动 Pixel5
         
        Android-DirtyStream 漏洞详细说明Android grantUriPermission与StartAnyWhere
        • Twikoo