我遇到了一些非常奇怪的行为,任务指向的代码段> mm,我希望有人可以帮助我。我正在做的是拉出代码段并将其放入缓冲区,然后从中生成HMAC。偶尔我会得到一个Ooops!说不能与调用堆栈终止在memcpy()。似乎正在发生的事情是数据在复制过程中消失,导致页面错误,然后是Ooops。我已经广泛搜索了mm_struct中使用的这种看似短暂的内存本质,但没有发现任何东西。我不相信我在代码中做了任何有争议的事情;这里是为了简洁而删除评论等。
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的任何其他组件。我在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())代码在不同的负载下连续工作六周而没有在运行Ubuntu 12.04(3.8.13-bone28)的单个处理器ARM BeagleBoard Black上出现故障。这个问题似乎只发生在我运行Ubuntu 12.04的x86机箱上,然后才发生重负载就像启动Chromium一样。
很抱歉在这里啰嗦,我很难过。
有什么想法吗?
提前再次感谢,
皮特
答案 0 :(得分:1)
您无法直接从用户空间可靠地复制内存,如您所发现的那样。
使用copy_from_user()
代替memcpy()
。并且不要禁用抢占,没有意义。