Linux 内核无法执行任何二进制文件(错误-12)

Linux 内核无法执行任何二进制文件(错误-12)

问题:内存分配问题

我的平台:

SOC = STM32H743 (ARMv7E-M | Cortex-M7)
Board = Waveshare CoreH7XXI 
Linux Kernel = 5.8.10 (stable 2020-09-17)
initial defconfig file = stm32_defconfig
rootfs = built using busybox | busybox compiled using arm-linux-gnueabihf-gcc as FDPIC ELF

我已经通过以下方式创建了一次 rootfs本指南并由我自己将其配置为将其编译为 FDPIC ELF(对于无 mmu 平台(如 arm_cortex-m 系列)而言位置独立的 elf),另一次我使用 buildroot(工具链、rootfs 和内核)构建它。

但这没有用。我的内核无法执行任何文件,甚至是我的 rootfs 中的 /linuxrc 或 /sbin/init 的 init 文件(我知道它们是 busybox 二进制文件的符号链接)。正如我在第一段中提到的,我尝试了不同的可执行格式(我的意思是 FDPIC ELF 和 BFLT(平面二进制)),但它们都不起作用,并且内核抛出了错误,errno -12这意味着内存不足

这是我的内核日志,log_level 为 7:

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 5.7.19 (root@Mahyar1284) (gcc version 9.3.0 (Buildroot 2020.08), GNU ld (GNU Binutils) 2.32) #3 PREEMPT Sun Oct 11 08:20:09 +0330 2020
[    0.000000] CPU: ARMv7-M [411fc271] revision 1 (ARMv7M), cr=00000000
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
[    0.000000] OF: fdt: Machine model: Waveshare STM32H743i-Coreh7 board
[    0.000000] Built 1 zonelists, mobility grouping off.  Total pages: 1937
[    0.000000] Kernel command line: console=ttySTM0,115200n8 root=/dev/mmcblk0p2 rw rootwait loglevel=7 init=/linuxrc
[    0.000000] Dentry cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.000000] Inode-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] Memory: 5136K/7812K available (1517K kernel code, 142K rwdata, 556K rodata, 72K init, 114K bss, 2676K reserved, 0K cma-reserved)
       .
       .
       .
       .
[    0.866164] VFS: Mounted root (ext4 filesystem) on device 179:2.
[    0.875365] devtmpfs: mounted
[    0.879076] Freeing unused kernel memory: 72K
[    0.883567] This architecture does not have kernel memory protection.
[    0.889882] Run /linuxrc as init process
[    0.902632] random: fast init done
[    0.911679] linuxrc: page allocation failure: order:8, mode:0xcc0(GFP_KERNEL), nodemask=(null)
[    0.922278] nommu: Allocation of length 675840 from process 1 (linuxrc) failed
[    0.929778] binfmt_flat: Unable to allocate RAM for process text/data, errno -12
[    0.937629] Kernel panic - not syncing: Requested init /linuxrc failed (error -12).
[    0.945187] ---[ end Kernel panic - not syncing: Requested init /linuxrc failed (error -12). ]---

使用调试级别 17 进行日志记录:

[    1.019849] Run /linuxrc as init process
[    1.023842]   with arguments:
[    1.026661]     /linuxrc
[    1.029174]   with environment:
[    1.032436]     HOME=/
[    1.034646]     TERM=linux
[    1.052238] linuxrc: page allocation failure: order:8, mode:0xcc0(GFP_KERNEL), nodemask=(null)
[    1.060781] CPU: 0 PID: 1 Comm: linuxrc Not tainted 5.8.10 #41
[    1.066932] Hardware name: STM32 (Device Tree Support)
[    1.072346] [<d000b3fd>] (unwind_backtrace) from [<d000a527>] (show_stack+0xb/0xc)
[    1.079832] [<d000a527>] (show_stack) from [<d0056421>] (warn_alloc+0x63/0xe2)
[    1.087242] [<d0056421>] (warn_alloc) from [<d00567e9>] (__alloc_pages_nodemask+0x33b/0x55a)
[    1.095743] [<d00567e9>] (__alloc_pages_nodemask) from [<d0056a17>] (__get_free_pages+0xf/0x24)
[    2.108641] [<d0056a17>] (__get_free_pages) from [<d0056c9f>] (alloc_pages_exact+0x33/0x44)
[    2.117162] [<d0056c9f>] (alloc_pages_exact) from [<d0054025>] (do_mmap+0x46f/0x5aa)
[    2.124999] [<d0054025>] (do_mmap) from [<d004f47b>] (vm_mmap_pgoff+0x5d/0x86)
[    2.132321] [<d004f47b>] (vm_mmap_pgoff) from [<d008bbdb>] (load_flat_file+0x39b/0x5dc)
[    2.140215] [<d008bbdb>] (load_flat_file) from [<d008bfe9>] (load_flat_binary+0x49/0x2dc)
[    2.148593] [<d008bfe9>] (load_flat_binary) from [<d00614c1>] (__do_execve_file+0x439/0x584)
[    2.157129] [<d00614c1>] (__do_execve_file) from [<d0061b03>] (do_execve+0x17/0x1a)
[    2.164892] [<d0061b03>] (do_execve) from [<d0184965>] (kernel_init+0x41/0xa0)
[    2.172212] [<d0184965>] (kernel_init) from [<d00082ad>] (ret_from_fork+0x11/0x24)
[    2.179638] Exception stack(0xd0435fb0 to 0xd0435ff8)
[    2.184861] 5fa0:                                     00000000 00000000 00000000 00000000
[    2.193055] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    2.201091] 5fe0: 00000000 00000000 00000000 00000000 00000000 00000000
[    2.207831] Mem-Info:
[    2.210012] active_anon:0 inactive_anon:0 isolated_anon:0
[    2.210012]  active_file:6 inactive_file:11 isolated_file:0
[    2.210012]  unevictable:0 dirty:1 writeback:0
[    2.210012]  slab_reclaimable:26 slab_unreclaimable:339
[    2.210012]  mapped:0 shmem:0 pagetables:0 bounce:0
[    2.210012]  free:580 free_pcp:0 free_cma:0
[    2.239767] Node 0 active_anon:0kB inactive_anon:0kB active_file:24kB inactive_file:44kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:0kB dirty:4kB writeback:0kB shmem:0kB writeback_tmp:0kB all_unreclaimable? no
[    2.259994] Normal free:2320kB min:284kB low:352kB high:420kB reserved_highatomic:0KB active_anon:0kB inactive_anon:0kB active_file:24kB inactive_file:44kB unevictable:0kB writepending:4kB present:7812kB managed:5188kB mlocked:0kB kernel_stack:200kB pagetables:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[    2.287792] lowmem_reserve[]: 0 0
[    2.290982] Normal: 10*4kB (UM) 5*8kB (UM) 4*16kB (UM) 6*32kB (UM) 1*64kB (M) 3*128kB (UM) 2*256kB (M) 2*512kB (UM) 0*1024kB 0*2048kB 0*4096kB = 2320kB
[    2.304689] 17 total pagecache pages
[    2.308111] 1953 pages RAM
[    2.310798] 0 pages HighMem/MovableOnly
[    2.314765] 656 pages reserved
[    2.317682] nommu: Allocation of length 675840 from process 1 (linuxrc) failed
[    2.325066] active_anon:0 inactive_anon:0 isolated_anon:0
[    2.325066]  active_file:6 inactive_file:11 isolated_file:0
[    2.325066]  unevictable:0 dirty:1 writeback:0
[    2.325066]  slab_reclaimable:26 slab_unreclaimable:339
[    2.325066]  mapped:0 shmem:0 pagetables:0 bounce:0
[    2.325066]  free:580 free_pcp:0 free_cma:0
[    2.354738] Node 0 active_anon:0kB inactive_anon:0kB active_file:24kB inactive_file:44kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:0kB dirty:4kB writeback:0kB shmem:0kB writeback_tmp:0kB all_unreclaimable? no
[    2.374960] Normal free:2320kB min:284kB low:352kB high:420kB reserved_highatomic:0KB active_anon:0kB inactive_anon:0kB active_file:24kB inactive_file:44kB unevictable:0kB writepending:4kB present:7812kB managed:5188kB mlocked:0kB kernel_stack:200kB pagetables:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[    2.402754] lowmem_reserve[]: 0 0
[    2.405941] Normal: 10*4kB (UM) 5*8kB (UM) 4*16kB (UM) 6*32kB (UM) 1*64kB (M) 3*128kB (UM) 2*256kB (M) 2*512kB (UM) 0*1024kB 0*2048kB 0*4096kB = 2320kB
[    2.419639] 17 total pagecache pages
[    2.423247] binfmt_flat: Unable to allocate RAM for process text/data, errno -12
[    2.430708] Kernel panic - not syncing: Requested init /linuxrc failed (error -12).
[    2.438253] ---[ end Kernel panic - not syncing: Requested init /linuxrc failed (error -12). ]---


更新: 我设法使用 GDB + OpenOCD 调试内核,发现错误在binfmt_flat.c文件行634::

pr_err("Unable to allocate RAM for process text/data, " "errno %d\n", ret);
        memp = realdatastart;
        memp_size = len;
    } else {

        len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(u32);
        len = PAGE_ALIGN(len);
        textpos = vm_mmap(NULL, 0, len,
            PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);

        if (!textpos || IS_ERR_VALUE(textpos)) {
            ret = textpos;
            if (!textpos)
                ret = -ENOMEM;
            pr_err("Unable to allocate RAM for process text/data, "
                   "errno %d\n", ret);
            goto err;
        }

我认为问题发生在 vm_mmap 函数 ( textpos = vm_mmap(NULL, 0, len, PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);)

Linux 源代码树中 vm_mmap 函数的链接

unsigned long vm_mmap(struct file *file, unsigned long addr,
    unsigned long len, unsigned long prot,
    unsigned long flag, unsigned long offset)
{
    if (unlikely(offset + PAGE_ALIGN(len) < offset))
        return -EINVAL;
    if (unlikely(offset_in_page(offset)))
        return -EINVAL;

    return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
}

相关内容