在_do_fork()中执行copy_process()时__stack_chk_fail?

时间:2017-03-11 14:01:52

标签: linux linux-kernel fork intel qemu

我试图在x86_64上做一个关于linux内核(4.4.52)的实验项目,其中一个要求是每当控制流离开特定功能时,CR0寄存器中的写保护位总是启用。一般来说,它就像(这个想法来自nested kernel,但这与我的问题不太相关):

DISABLE_CR0.WP_BIT
original_func()
ENABLE_CR0.WP_BIT

通过这样做,整个内核将在启用CR0.WP的情况下执行。我已经用上面的格式替换了原来的native_set_pte函数和native_write_cr3函数,现在内核在启动时崩溃了。

这是日志(它的原始日志,虽然序列看起来很奇怪):

[    1.403888] IP: [<ffff8800351ebbb0>] 0xffff8800351ebbb0
[    1.403891] PGD 2876067 PUD 2877067 PMD 3500e063 PTE 80000000351eb163
[    1.403892] Oops: 0011 [#2] SMP
[    1.403898] Modules linked in: crct10dif_pclmul crc32_pclmul aesni_intel aes_x86_64 lrw gf128mul glue_helper ablk_helper cryptd psmouse pata_acpi floppy
[    1.403901] CPU: 0 PID: 143 Comm: systemd-udevd Tainted: G      D         4.4.52v1+ #2
[    1.403902] Hardware name: Fedora Project OpenStack Nova, BIOS 0.5.1 01/01/2011
[    1.403903] task: ffff8800351c0e00 ti: ffff8800351e8000 task.ti: ffff8800351e8000
[    1.403905] RIP: 0010:[<ffff8800351ebbb0>]  [<ffff8800351ebbb0>] 0xffff8800351ebbb0
[    1.403906] RSP: 0018:ffff8800351ebba8  EFLAGS: 00211086
[    1.403906] RAX: 000000000000000e RBX: ffff8800351ebcf8 RCX: 000000000000000e
[    1.403907] RDX: 0000000000000000 RSI: 0000000000201092 RDI: 0000000000201092
[    1.403908] RBP: 0000000000000003 R08: ffffffff82778d60 R09: ffff8800351ebb40
[    1.403909] R10: 0000000000000030 R11: ffffc00000000fff R12: ffff8800351c0e00
[    1.403909] R13: 0000000000000010 R14: 0000000000201046 R15: ffffffffffffffff
[    1.403911] FS:  00007f1f021e38c0(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000
[    1.403912] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    1.403912] CR2: ffff8800351ebbb0 CR3: 00000000351cd000 CR4: 00000000001406f0
[    1.403916] Stack:
[    1.403918]  ffffffff810b62ae ffff8800351ebbc0 000000000000006c 0000000000000000
[    1.403920]  ffff8800351ebbd8 ffffffff810b62ae ffffffff8111ce51 00000000000364a4
[    1.403921]  ffffffff82783168 000000000000005c 000000000000000c ffffffff820583b0
[    1.403922] Call Trace:
[    1.403928]  [<ffffffff810b62ae>] ? kvm_sched_clock_read+0x1e/0x30
[    1.403930]  [<ffffffff810b62ae>] ? kvm_sched_clock_read+0x1e/0x30
[    1.403933]  [<ffffffff8111ce51>] ? __raw_callee_save___pv_queued_spin_unlock+0x11/0x20
[    1.403935]  [<ffffffff8111c49e>] ? down_trylock+0x2e/0x40
[    1.403937]  [<ffffffff81129959>] ? console_trylock+0x19/0x60
[    1.403938]  [<ffffffff8112af2e>] ? vprintk_emit+0x29e/0x530
[    1.403945]  [<ffffffff8115fe8e>] ? crash_kexec+0x7e/0x140
[    1.403953]  [<ffffffff81440ae5>] ? find_next_bit+0x15/0x20
[    1.403955]  [<ffffffff814390bb>] ? __const_udelay+0x2b/0x30
[    1.403958]  [<ffffffff810a2a0c>] ? native_stop_other_cpus+0x8c/0x170
[    1.403965]  [<ffffffff811dde8f>] ? panic+0xeb/0x215
[    1.403968]  [<ffffffff810d12a7>] ? copy_process+0x727/0x1b20
[    1.403970]  [<ffffffff810d32f9>] ? __stack_chk_fail+0x19/0x20
[    1.403972]  [<ffffffff810d12a7>] ? copy_process+0x727/0x1b20
[    1.403974]  [<ffffffff810d2808>] ? _do_fork+0x78/0x360
[    1.403975]  [<ffffffff810d2b99>] ? SyS_clone+0x19/0x20
[    1.403986]  [<ffffffff818694f2>] ? entry_SYSCALL_64_fastpath+0x16/0x71
[    1.404004] Code: 00 00 00 86 10 21 00 00 00 00 00 a8 bb 1e 35 00 88 ff ff 18 00 00 00 00 00 00 00 b0 bb 1e 35 00 88 ff ff ae 62 0b 81 ff ff ff ff <c0> bb 1e 35 00 88 ff ff 6c 00 00 00 00 00 00 00 00 00 00 00 00
[    1.404005] RIP  [<ffff8800351ebbb0>] 0xffff8800351ebbb0
[    1.404006]  RSP <ffff8800351ebba8>
[    1.404006] CR2: ffff8800351ebbb0
[    1.404008] ---[ end trace b62acacf75e0c54f ]---
[    1.406415] Kernel Offset: disabled
[    1.456105] ---[ end Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff810d12a7
[    1.456105]

我想问题是copy_process处的某些内容会导致溢出,也许它会写入一些只读内存?但是根据英特尔的文档, CR0.WP位应该只影响管理员模式,这是否意味着内核在执行copy_process时以管理员模式运行?

我试图反汇编内核,并对所有那些无数的汇编指令感到沮丧......所以我决定用qemu找到它。但是,内核在qemu中发生了 NOT 崩溃!!我使用的命令是

qemu-system-x86_64 -m 1G -kernel arch/x86/boot/bzImage -initrd arch/x86/boot/linux4.4.52-rootfs.img -hda vdisk.img --append "root=/dev/sda rw console=ttyS0" -nographic

我曾经认为_do_fork独立于特定设备和文件系统(如果我错了,请纠正我),那么导致内核在我的VPS崩溃的原因应该会导致它在qemu崩溃,它没有。

有没有人遇到同样的问题?我现在真的需要一些帮助。

P.S。我在我的VPS,ubuntu 16.04.2上这样做,但我认为这不是原因。

1 个答案:

答案 0 :(得分:1)

请注意,QEMU不是完全架构准确的模型,QEMU不提供所有架构引用功能的完全支持,因为QEMU的目标是仿真速度,而不是准确性,然后它只提供一些可行的架构配置文件来运行OS。

有些功能QEMU做的精确和正确,如分页和分段,但很多都没有:CPUID,syscall存在一些问题,许多指令不生成#GP,#SS,#PO,浮点错误,有些指令是没有实现(AVX,AVX2,FMA)等。

你应该使用x86黄金模型中的一个来捕捉这些棘手的情况:尝试使用Bochs或英特尔本身提供的一种。