使用 KASLR 内核功能时,内核无法分配 crashkernel 内存

问题描述

我在运行在 centos6.2 上的 x86_64 平台上使用 4.19.149 内核。 我的编译内核配置包含以下选项:

CONfig_PHYSICAL_START=0x1000000
CONfig_RELOCATABLE=y
CONfig_RANDOMIZE_BASE=y

我的内核命令行是:

?> cat /proc/cmdline
ro root=LABEL=/ rd_NO_LUKS  KEYBOARDTYPE=pc KEYTABLE=us LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=512M@0M nompath append="nmi_watchdog=2" printk.time=1 rd_NO_LVM rd_NO_DM dm_mod.use_blk_mq=y rcutree.kthread_prio=99 intel_pstate=enable intel_idle.max_cstate=0 processor.max_cstate=1 idle=halt console=tty0 console=ttyS0,38400n8d

总结一下:

  1. 我请求内核在低内存区域为 crashkernel 分配 512M。 查看内核 arch/x86/kernel/setup.c 时: 我可以看到,对于我的配置,内核尝试在 16M 之间分配那些 512M 的内存- 896M:
    #define CRASH_ALIGN     (16 << 20)
    ...
    # define CRASH_ADDR_LOW_MAX (896UL << 20)
    ...
    static void __init reserve_crashkernel(void)
    ....
        if (crash_base <= 0) {
        /*
         * Set CRASH_ADDR_LOW_MAX upper bound for crash memory,* as old kexec-tools loads bzImage below that,unless
         * "crashkernel=size[KMG],high" is specified.
         */
        crash_base = memblock_find_in_range(CRASH_ALIGN,high ? CRASH_ADDR_HIGH_MAX
                             : CRASH_ADDR_LOW_MAX,crash_size,CRASH_ALIGN);
        if (!crash_base) {
            pr_info("crashkernel reservation Failed - No suitable area found.\n");
            return;
        }```
    
  2. 因为我在启动时使用了 CONfig_RANDOMIZE_BASE 选项,然后才为 crashkernel,引导加载程序将我的内核提取随机物理地址中。 代码在 arch/x86/boot/compressed/kaslr.c

问题是,有一段时间,随机化内核地址会导致为崩溃内核分配内存失败。 例如:在我的一次重启中:

?> cat /proc/iomem
00000000-00000fff : Reserved
00001000-0009fbff : System RAM
0009fc00-0009ffff : Reserved
000a0000-000bffff : PCI Bus 0000:00
000f0000-000fffff : Reserved
  000f0000-000fffff : System ROM
00100000-bfff9fff : System RAM
  17000000-17c02fff : Kernel code
  17c03000-183523ff : Kernel data
  18883000-189fffff : Kernel bss
bfffa000-bfffffff : Reserved
c0000000-febfefff : PCI Bus 0000:00
  febf7000-febf707f : 0000:00:03.0
  febf8000-febf81ff : 0000:00:04.0
  febf9000-febf91ff : 0000:00:05.0
  febfa000-febfa1ff : 0000:00:06.0
  febfb000-febfb1ff : 0000:00:07.0
  febfc000-febfc1ff : 0000:00:08.0
  febfd000-febfd1ff : 0000:00:09.0
  febfe000-febfe03f : 0000:00:0a.0
fec00000-fec003ff : IOAPIC 0
fee00000-fee00fff : Local APIC
fffbc000-ffffffff : Reserved

在这个例子中,内核获得了 368M-380M,这给我的 512M 崩溃内核内存留下了空间(不是从上到下 - 896M-380M 不够,从下到上 16M-368M 不够)。 我的问题是:

  1. 这似乎是 KASLR 功能中的一个错误 - 这是一个已知问题吗?
  2. 有没有办法告诉 KASLR 避免将内核地址随机化到低内存区域?我可以看到使用 memmap 命令行参数我可以添加内存区域来实现这一点,问题是这些 memmap 也会导致 crashkernel 的分配失败。 谢谢。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)