我遇到了一个非常奇怪的场景,我正在为我的QNAP 639 Pro编写一个自定义内核模块。
该模块在Ubuntu 12.04的相同内核版本下成功运行:
Linux ubuntu 3.4.6-030406-generic #201207191609 SMP i686 i686 i386GNU/Linux
然而,在我的qnap上编译了许多小时之后,我得到了一个带有指针解引用的内核错误,这是一个dmesg转储:
[ 1491.062409] Got pinode dentry
[ 1491.062434] BUG: unable to handle kernel NULL pointer dereference at (null)
[ 1491.063351] IP: [<c0605e48>] memcpy+0x18/0x2c
[ 1491.063351] *pde = 00000000
[ 1491.063351] Oops: 0000 [#1] SMP
[ 1491.063351] Modules linked in: nocansee(O+) iscsi_tcp(O) libiscsi_tcp(O) libiscsi(O) scsi_transport_iscsi(O) fbdisk(O) bridge stp ipv6 8021q uvcvideo videobuf2_vmalloc videobuf2_memops videobuf2_core v4l2_common videodev v4l2_int_device snd_usb_caiaq snd_usb_audio hid_logitech snd_usbmidi_lib snd_hwdep snd_seq_midi snd_rawmidi fnotify(PO) xhci_hcd udf isofs ufsd(PO) jnl(O) e1000e(O) usblp iTCO_wdt iTCO_vendor_support rtcmod(O) usbhid cryptodev(O) hal_netlink(O) usb_storage uhci_hcd ehci_hcd usbcore usb_common mv_sata(O) [last unloaded: nocansee]
[ 1491.063351]
[ 1491.063351] Pid: 17279, comm: insmod Tainted: P O 3.4.6 #1 ICP / iEi ATOM NAS /ATOM NAS (QE05)
[ 1491.063351] EIP: 0060:[<c0605e48>] EFLAGS: 00210286 CPU: 0
[ 1491.063351] EIP is at memcpy+0x18/0x2c
[ 1491.063351] EAX: 0000001a EBX: f8e60978 ECX: 0000001a EDX: 00000068
[ 1491.063351] ESI: 00000000 EDI: f8e60978 EBP: d38a7e64 ESP: d38a7e50
[ 1491.063351] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 1491.063351] CR0: 8005003b CR2: 00000000 CR3: 35ecd000 CR4: 000007c0
[ 1491.063351] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 1491.063351] DR6: ffff0ff0 DR7: 00000400
[ 1491.063351] Process insmod (pid: 17279, ti=d38a6000 task=f651c000 task.ti=d38a6000)
[ 1491.063351] Stack:
[ 1491.063351] d38a7e64 c042588f 00000000 00000013 f8e604b4 d38a7e7c f8e60324 f8e603fd
[ 1491.063351] d7e39850 d5809400 f8e5daf8 d38a7e8c f8e62060 f8e608a8 00000000 d38a7ea8
[ 1491.063351] c0401151 f8e62000 00000000 f8e5daf8 00000013 f8e604b4 d38a7fac c04598a6
[ 1491.063351] Call Trace:
[ 1491.063351] [<c042588f>] ? printk+0x15/0x17
[ 1491.063351] [<f8e60324>] hook_proc+0x4f/0x65 [nocansee]
[ 1491.063351] [<f8e62060>] module_init_proc+0x60/0x7a [nocansee]
[ 1491.063351] [<c0401151>] do_one_initcall+0x71/0x113
[ 1491.063351] [<f8e62000>] ? 0xf8e61fff
[ 1491.063351] [<c04598a6>] sys_init_module+0x1060/0x128e
[ 1491.063351] [<c0422251>] ? kmap_atomic_prot+0x23/0x9c
[ 1491.063351] [<c0863b64>] syscall_call+0x7/0xb
[ 1491.063351] Code: 08 89 73 50 89 73 54 c6 43 4c 04 88 43 4d 5b 5e 5f 5d c3 55 89 e5 57 56 89 d6 53 89 c3 89 c8 89 ca c1 e8 02 83 ec 08 89 c1 89 df <f3> a5 89 d1 83 e1 03 74 02 f3 a4 5a 89 d8 59 5b 5e 5f 5d c3 55
[ 1491.063351] EIP: [<c0605e48>] memcpy+0x18/0x2c SS:ESP 0068:d38a7e50
[ 1491.063351] CR2: 0000000000000000
[ 1491.314433] ---[ end trace 97a00886892de9ee ]---
QNAP正在运行
Linux 3.4.6 #1 SMP i686 unknown.
这是mod信息:
$ modinfo nocansee.ko
filename: nocansee.ko
license: GPL
depends:
vermagic: 3.4.6 SMP mod_unload ATOM
parm: rc_name:charp
parm: rc_dir:charp
parm: mod_name:charp
parm: mod_dir:charp
这是源代码的相关部分,它会导致Oops:
struct path p;
if(kern_path("/myfolder", 0, &p))
return;
pinode = p.dentry->d_inode;
if(!pinode)
return;
printk(KERN_DEBUG "Got pinode dentry");
// hook folder
proc_fops = *pinode->i_fop; //Line which causes kernel Oops
proc_original = pinode->i_fop;
proc_fops.readdir = do_readdir_proc;
pinode->i_fop = &proc_fops;
欢迎任何帮助!非常感谢!
您得到了一个file_operations为NULL的索引节点。只需在对file_operations指针解引用的那行之前添加check:
if (!pinode->i_fop)
return;
proc_fops = *pinode->i_fop;