ti-j7200 平台KASLR问题

发布时间 2023-04-11 16:17:06作者: River008

经过调查确认821需要u-boot配合支持才能实现KASLR,目前uboot不支持KASLR

调查经过:

5.10内核ARM64 开启KASLR功能的话需要打开CONFIG_RANDOMIZE_BASE,

每次start_kernel的运行地址是要加上一个随机偏移,偏移由kaslr_early_init返回

以此达到地址随机化目的。

#ifdef CONFIG_RANDOMIZE_BASE
        tst     x23, ~(MIN_KIMG_ALIGN - 1)      // already running randomized?
        b.ne    0f
        mov     x0, x21                         // pass FDT address in x0
        bl      kaslr_early_init                // parse FDT for KASLR options
        cbz     x0, 0f                          // KASLR disabled? just proceed
        orr     x23, x23, x0                    // record KASLR offset
        ldp     x29, x30, [sp], #16             // we must enable KASLR, return
        ret                                     // to __primary_switch()
0:
#endif 
        add     sp, sp, #16
        mov     x29, #0
        mov     x30, #0
        b       start_kernel

 

kaslr_early_init提供偏移的方式是从DTS中获取一个随机种子seed(get_kaslr_seed)或者从CPU获取(arch_get_random_seed_long_early)

        /*
         * Retrieve (and wipe) the seed from the FDT
         */
        seed = get_kaslr_seed(fdt);

        /*
         * Check if 'nokaslr' appears on the command line, and
         * return 0 if that is the case.
         */
        cmdline = kaslr_get_cmdline(fdt);
        str = strstr(cmdline, "nokaslr");
        if (str == cmdline || (str > cmdline && *(str - 1) == ' ')) {
                kaslr_status = KASLR_DISABLED_CMDLINE;
                return 0;
        }

        /*
         * Mix in any entropy obtainable architecturally if enabled
         * and supported.
         */

        if (arch_get_random_seed_long_early(&raw))
                seed ^= raw;

        if (!seed) {
                kaslr_status = KASLR_DISABLED_NO_SEED;
                return 0;
        }
经过确认821 CPU没有提供RNDR随机数寄存器,参考下列AArch64 Instruction Set Attribute  Register 0,无法提供seed,所以我们的系统中只有DTS提供seed

https://developer.arm.com/documentation/ddi0595/2021-06/AArch64-Registers/ID-AA64ISAR0-EL1--AArch64-Instruction-Set-Attribute-Register-0?lang=en#fieldset_0-63_60

但是DTS中提供的seed是固定的,所以每次重启偏移是固定的

进一步调查uboot实现,如下所示uboot会提供随机数sec_firmware_get_random然后更新DTS中的随机种子seed,这样就确保偏移是随机的。

但是需要CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT目前Ti的预编译的uboot是不支持该特性的,打开该配置后编译不通过,需要配套实现

CONFIG_SYS_MEM_RESERVE_SECURE,但是目前的uboot没有提供该功能。

int fdt_fixup_kaslr(void *fdt)
{
    int nodeoffset;
    int err, ret = 0;
    u8 rand[8];

#if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT)
    /* Check if random seed generation is  supported */
    if (sec_firmware_support_hwrng() == false) {
        printf("WARNING: SEC firmware not running, no kaslr-seed\n");
        return 0;
    }

    ret = sec_firmware_get_random(rand, 8);
    if (ret < 0) {
        printf("WARNING: No random number to set kaslr-seed\n");
        return 0;
    }

    err = fdt_check_header(fdt);
    if (err < 0) {
        printf("fdt_chosen: %s\n", fdt_strerror(err));
        return 0;
    }

    /* find or create "/chosen" node. */
    nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
    if (nodeoffset < 0)
        return 0;

    err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", rand,
                  sizeof(rand));
    if (err < 0) {
        printf("WARNING: can't set kaslr-seed %s.\n",
               fdt_strerror(err));
        return 0;
    }
    ret = 1;
#endif

更新:

从下述看即使uboot可以编译通过,KASLR还是不能实现。

arm64平台实现KASLR的总体思路是通过trustzone运行一个sec firmware,sec firmware会负责生成kaslr-seed,也就是用来计算内核偏移的随机种子。其中,sec firmware的加载工作由u-boot负责执行,u-boot通过ppa(可以理解为trustzone中的一个应用,用来将sec frimware加载到trust总额中运行)将sec firmware(如teeOS.bin)加载到trustzone中运行,然后在fdt_fixup的过程中调用sec firmware生成kaslr-seed,并将这个值设置到对应的fdt。

整个实现思路的安全主旨就是通过trustzone来生成随机数,以保证随机数的安全性,进而保证内核地址的随机性。但在我们使用的平台上没有实现trustzone,ppa也不会生成和运行,因而导致虽然我们开启了必须的配置,但实际的业务逻辑并不支持KASLR的运行,所以必须在现有平台上重新构建安全地生成随机数的逻辑。“

参考:

https://blog.csdn.net/andlee/article/details/121014664