64位Linux内核如何从ELF中启动32位进程

时间:2018-02-19 21:54:33

标签: linux linux-kernel x86-64 32bit-64bit

通过查看内核源代码中的binfmt_elf.c,我无法弄清楚在生成32位进程与64位进程时内核(64位)的作用有何不同。

有人可以向我解释我错过了什么吗?

(这个问题与我关于在64位指令(link)的同一过程中有32位指令的其他问题有关,但这可以作为一个单独的问题。)

1 个答案:

答案 0 :(得分:5)

如果 execveat 系统调用用于启动新进程,我们首先在内核源代码中输入 fs / exec.c 到SYSCALL_DEFINEx(execveat ..)功能。 然后这个调用这些函数:

  • do_execveat(..)
    • do_execveat_common(..)
      • exec_binprm(..)
        • search_binary_handler(..)

search_binary_handler 遍历各种二进制处理程序。在64位Linux内核中,将有一个64位ELF处理程序和一个32位ELF处理程序。两个处理程序最终都是使用相同的源 fs / binfmt_elf.c 构建的。但是,32位处理程序是通过 fs / compat_binfmt_elf.c 构建的,它在包含源文件 binfmt_elf.c 之前重新定义了许多宏。

binfmt_elf.c 内,调用 elf_check_arch 。这是在 arch / x86 / include / asm / elf.h 中定义的宏,在64位处理程序与32位处理程序中的定义不同。对于64位,它与 EM_X86_64 (62 - 在include / uapi / ilnux / elf-em.h中定义)进行比较。对于32位,它与 EM_386 (3)或 EM_486 (6)(在同一文件中定义)进行比较。如果比较失败,二进制处理程序放弃,所以我们最终只有一个处理程序负责ELF解析和执行 - 取决于ELF是64位还是32位。

因此,应在文件 fs / compat_binfmt_elf.c 中找到解析32位ELF与64位Linux中64位ELF的所有差异。

主要线索似乎是 compat_start_thread start_thread 重新定义为 compat_start_thread 。此函数定义位于 arch / x86 / kernel / process_64.c 中。 compat_start_thread 然后使用以下参数调用 start_thread_common

start_thread_common(regs, new_ip, new_sp,
             test_thread_flag(TIF_X32)
             ? __USER_CS : __USER32_CS,
             __USER_DS, __USER_DS);

正常的 start_thread 函数使用以下参数调用 start_thread_common

start_thread_common(regs, new_ip, new_sp,
             __USER_CS, __USER_DS, 0);

在这里,我们已经看到了体系结构相关的代码,对于64位ELF和32位ELF, CS 的处理方式不同。

然后我们在 arch / x86 / include / asm / segment.h 中有__USER_CS和__USER32_CS的定义:

#define __USER_CS           (GDT_ENTRY_DEFAULT_USER_CS*8 + 3)
#define __USER32_CS         (GDT_ENTRY_DEFAULT_USER32_CS*8 + 3)

#define GDT_ENTRY_DEFAULT_USER_CS   6
#define GDT_ENTRY_DEFAULT_USER32_CS 4

所以__USER_CS是6 * 8 + 3 = 51 = 0x33

__USER32_CS是4 * 8 + 3 = 35 = 0x23

这些数字与这些示例中用于CS的数字相匹配:

由于CPU未在实模式下运行,因此段寄存器不会填充段本身,而是填充16位选择器:

来自维基百科(Protected mode):

  

在保护模式下,segment_part由16位选择器替换,其中13个高位(位3到位15)包含描述符表中的条目索引。下一位(位2)指定操作是与GDT还是LDT一起使用。选择器的最低两位(位1和位0)被组合以定义请求的特权,其中0和3的值分别代表最高和最低特权。

CS值为0x23时,位1和0 3 ,表示“最低权限”。位2 0 ,意味着 GDT ,位3到位15是4,这意味着我们从全局描述符表(GDT)获得索引4 )。

到目前为止,我已经能够挖掘多远。