我正在经历task-> mm指向的代码段的一些非常奇怪的行为,我希望有人能帮助我。 我正在做的是拉出代码段,并将其放入一个缓冲区,然后从中产生一个HMAC。 偶尔我会得到一个哎呀! 说不能用调用堆栈在memcpy()终止。 看来正在发生的事情是数据在复制过程中消失,并导致页面错误,然后是Ooops。 我已经search了很多关于在mm_struct中使用的这个看似短暂的内存的引用,但是什么都没find。 我不相信我在代码中做任何有争议的事情; 这里是简短的删除评论等。
struct mm_struct* __mm; ... __mm = get_task_mm(__task); if(likely(__mm)) { __buflen = (__mm->end_code - __mm->start_code); if(likely(__buflen > 0)) { __buf = (unsigned char*)__get_buffer(__buflen); if(likely(__buf)) { preempt_disable(); memcpy(__buf, (uint8_t*)__mm->start_code, __buflen); preempt_enable(); mmput(__mm); if(unlikely(!__do_ntru_hmac(__buf, __buflen, __hmac))) { __retcode = 0; } __release_buffer(__buf, __buflen); } else { printk(KERN_ERR "[%s] Buffer allocation failure [%d]\n", __task->comm, __buflen); __retcode = 0; } ...
内存分配例程很简单,目的是能够一次分配大块内存。 他们看起来像这样:
void* __get_buffer(unsigned long __buflen) { if(likely(__buflen <= KMALLOC_MAX_SIZE)) { return kmalloc(__buflen, GFP_KERNEL); } else { return (void*)__get_free_pages(GFP_KERNEL, get_order(__buflen)); } return NULL; } void __release_buffer(void* __buffer, unsigned long __buflen) { if(likely(__buflen <= KMALLOC_MAX_SIZE)) { kfree(__buffer); } else { free_pages((unsigned long)__buffer, get_order(__buflen)); } return; }
这个错误似乎是随机发生的,我不能将它绑定到任务,父节点或struct task_struct的任何其他组件。 我已经试过互斥和spinlock在memcpy期间保护内存,我已经尝试完全使用set_task_state()停止任务,并在复制后重新启动它,但似乎没有任何东西可以阻止这个问题。
更新:我仍然在锤击这个问题,虽然我会抛出更多的数据。 这是Oops转储。
Mar 16 09:39:27 ubuntu kernel: [ 324.229195] BUG: unable to handle kernel paging request at 0804b000 Mar 16 09:39:27 ubuntu kernel: [ 324.229199] IP: [<c1312dfd>] memcpy+0x1d/0x40 Mar 16 09:39:27 ubuntu kernel: [ 324.229221] *pdpt = 000000002cf4c001 *pde = 000000003b72c067 Mar 16 09:39:27 ubuntu kernel: [ 324.229223] Oops: 0000 [#1] SMP Mar 16 09:39:27 ubuntu kernel: [ 324.229225] Modules linked in: aerolock(OF) vmhgfs(OF) vmw_balloon psmouse snd_ens1371 serio_raw gameport snd_ac97_codec ac97_bus snd_pcm snd_seq_midi btusb snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device vmwgfx snd ttm drm bnep rfcomm soundcore mac_hid bluetooth snd_page_alloc vmw_vmci i2c_piix4 parport_pc ppdev shpchp lp parport hid_generic usbhid hid pcnet32 mptspi ahci libahci mptscsih mptbase floppy mii vmw_pvscsi vmxnet3 Mar 16 09:39:27 ubuntu kernel: [ 324.229256] CPU: 0 PID: 2880 Comm: aerolockd Tainted: GF O 3.11.0-17-generic #31~precise1-Ubuntu Mar 16 09:39:27 ubuntu kernel: [ 324.229258] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/31/2013 Mar 16 09:39:27 ubuntu kernel: [ 324.229259] task: f1816700 ti: ed774000 task.ti: ed774000 Mar 16 09:39:27 ubuntu kernel: [ 324.229262] EIP: 0060:[<c1312dfd>] EFLAGS: 00010202 CPU: 0 Mar 16 09:39:27 ubuntu kernel: [ 324.229264] EIP is at memcpy+0x1d/0x40 Mar 16 09:39:27 ubuntu kernel: [ 324.229266] EAX: ecc80000 EBX: 00011cd0 ECX: 00003b34 EDX: 08048000 Mar 16 09:39:27 ubuntu kernel: [ 324.229268] ESI: 0804b000 EDI: ecc83000 EBP: ed775e74 ESP: ed775e68 Mar 16 09:39:27 ubuntu kernel: [ 324.229269] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 Mar 16 09:39:27 ubuntu kernel: [ 324.229271] CR0: 80050033 CR2: 0804b000 CR3: 2d9d5000 CR4: 001407f0 Mar 16 09:39:27 ubuntu kernel: [ 324.229345] Stack: Mar 16 09:39:27 ubuntu kernel: [ 324.229347] 00011cd0 f1816700 f33703b4 ed775eb0 f9ba3a1b 0000063b 00000000 00000000 Mar 16 09:39:27 ubuntu kernel: [ 324.229353] 0000063c c1b80e4c f1816700 ed775ee0 08048000 ecc80000 00000000 f1816700 Mar 16 09:39:27 ubuntu kernel: [ 324.229358] f9baa952 f1816700 ed775f08 f9ba3b6e 00000000 00000000 00000000 c1b9d642 Mar 16 09:39:27 ubuntu kernel: [ 324.229364] Call Trace: Mar 16 09:39:27 ubuntu kernel: [ 324.229370] [<f9ba3a1b>] __generate_hmac+0x8b/0x190 [aerolock] Mar 16 09:39:27 ubuntu kernel: [ 324.229373] [<f9ba3b6e>] __validate_hmac+0x4e/0x220 [aerolock] Mar 16 09:39:27 ubuntu kernel: [ 324.229377] [<f9ba3da0>] ret_do_fork+0x60/0x70 [aerolock] Mar 16 09:39:27 ubuntu kernel: [ 324.229384] [<c167f12a>] trampoline_handler+0x11a/0x1c0 Mar 16 09:39:27 ubuntu kernel: [ 324.229390] [<c10839a4>] ? wake_up_new_task+0xe4/0x150 Mar 16 09:39:27 ubuntu kernel: [ 324.229394] [<c1054bf5>] ? SyS_clone+0x25/0x30 Mar 16 09:39:27 ubuntu kernel: [ 324.229397] [<c1054bf5>] ? SyS_clone+0x25/0x30 Mar 16 09:39:27 ubuntu kernel: [ 324.229400] [<c167efee>] kretprobe_trampoline+0x16/0x38 Mar 16 09:39:27 ubuntu kernel: [ 324.229404] [<c167efd8>] ? kretprobe_trampoline_holder+0x8/0x8 Mar 16 09:39:27 ubuntu kernel: [ 324.229406] [<c167c937>] syscall_call+0x7/0xb Mar 16 09:39:27 ubuntu kernel: [ 324.229408] Code: c3 90 8d 74 26 00 e8 33 fe ff ff eb e8 90 55 89 e5 83 ec 0c 89 5d f4 89 75 f8 89 7d fc 3e 8d 74 26 00 89 cb 89 c7 c1 e9 02 89 d6 <f3> a5 89 d9 83 e1 03 74 02 f3 a4 8b 5d f4 8b 75 f8 8b 7d fc 89 Mar 16 09:39:27 ubuntu kernel: [ 324.229439] EIP: [<c1312dfd>] memcpy+0x1d/0x40 SS:ESP 0068:ed775e68 Mar 16 09:39:27 ubuntu kernel: [ 324.229444] CR2: 000000000804b000 Mar 16 09:39:27 ubuntu kernel: [ 324.229447] ---[ end trace 3c014cb0223fa59a ]---
我尝试了很多不同的方式,但都遇到了失败。 copy_from_user()例如每次都失败; 有时不读整个请求,有时会返回一个部分。 每次它在一个部分失败,它在页面边界上这样做 – 再次使它看起来像记忆被中间复制带走。
鉴于我挂钩do_fork(),可以进程只是从内核空间过渡到用户空间,而我试图捕获它? 正如我之前提到的,我试过停止当前的任务并重新启动后期复制,但是没有任何效果。
另外有趣的是要注意; 我已经有相同的(memcpy())代码运行了六个星期直接在不同的负载下,没有在一个单一的处理器ARM BeagleBoard黑色运行Ubuntu 12.04(3.8.13-bone28)失败的故障。 这个问题似乎只发生在我运行Ubuntu 12.04的x86机器上,然后只有当我像启动Chromium一样重负载时。
对不起,这么长时间在这里啰嗦,我很难过。
有任何想法吗?
再次感谢,
皮特
正如您发现的那样,您无法直接从用户空间可靠地复制内存。
使用copy_from_user()
而不是memcpy()
。 而且不要禁用抢占,没有意义。