尝试访问const char * buffer时崩溃

时间:2017-08-31 10:01:33

标签: c linux-device-driver

我正在尝试编写Linux内核模块。在那里,我已经注册了开放,读,写,释放功能,如下所示:

static struct file_operations fops =
{
   .open = dev_open,
   .read = dev_read,
   .write = dev_write,
   .release = dev_release,
};

驱动程序将字符设备创建为/ dev / hvacchar。这部分似乎工作正常。

为了测试,我写信给驱动程序:

cat > /dev/hvacchar
asdf1234

呼叫过程立即被杀死。

我已从dev_write中删除了所有内容,只剩下一个printk()。这是代码:

static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
   printk(KERN_INFO "HVACCHAR: Entered dev_write()\n");
   printk(KERN_INFO "HVACChar: b4 sprintf(): buffer=%c\n", buffer[0]);
   return len;
}

tail -f /var/log/kern.log显示第一个printk语句,但不显示第二个。我猜它在尝试访问缓冲区变量时崩溃了。根据我的理解,它由系统提供,它应该有一个有效的内存分配。我做错了什么?

这是来自kern.log的整个转储

Aug 31 15:17:28 app-ThinkCentre-M900 kernel: [873016.888579] HVACChar: Device has been opened 1 time(s)
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.627170] HVACCHAR: Entered dev_write()
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.627203] BUG: unable to handle kernel paging request at 00000000015c9004
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.630465] IP: [<ffffffffc08f7070>] dev_write+0x20/0x40 [hvacchar]
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.633714] PGD 51364067 PUD 374d3067 PMD 374f6067 PTE 80000000ac7de867
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.637075] Oops: 0001 [#36] SMP
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.640346] Modules linked in: hvacchar(OE) binfmt_misc btrfs xor raid6_pq ufs qnx4 hfsplus hfs minix ntfs msdos jfs xfs libcrc32c uas usb_storage ebbchar(OE) rfcomm bnep intel_rapl x86_pkg_temp_thermal input_leds intel_powerclamp coretemp snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic snd_hda_intel snd_hda_codec i915_bpo snd_hda_core snd_hwdep snd_pcm kvm_intel snd_seq_midi kvm snd_seq_midi_event snd_rawmidi snd_seq hci_uart irqbypass btbcm btqca snd_seq_device btintel snd_timer crct10dif_pclmul intel_ips drm_kms_helper bluetooth drm crc32_pclmul ghash_clmulni_intel aesni_intel snd aes_x86_64 lrw gf128mul mei_me glue_helper ablk_helper serio_raw cryptd i2c_algo_bit fb_sys_fops syscopyarea sysfillrect sysimgblt soundcore mei video acpi_pad 8250_fintek wmi intel_lpss_acpi intel_lpss pinctrl_sunrisepoint pinctrl_intel acpi_als kfifo_buf i2c_hid industrialio mac_hid parport_pc ppdev lp parport hid_generic usbhid hid e1000e psmouse ptp ahci pps_core libahci fjes [last unloaded: hvacchar]
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.660535] CPU: 1 PID: 31522 Comm: cat Tainted: G      D    OE   4.4.0-92-generic #115~14.04.1-Ubuntu
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.662854] Hardware name: LENOVO 10FLS13501/30D0, BIOS FWKT5AA   09/23/2016
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.664735] task: ffff88010759e900 ti: ffff8800374e0000 task.ti: ffff8800374e0000
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.666473] RIP: 0010:[<ffffffffc08f7070>]  [<ffffffffc08f7070>] dev_write+0x20/0x40 [hvacchar]
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.668233] RSP: 0018:ffff8800374e3ea8  EFLAGS: 00010282
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.669703] RAX: 000000000000001d RBX: 00000000015c9000 RCX: 0000000000000000
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.671127] RDX: 0000000000000001 RSI: ffff88023dc8dd98 RDI: ffff88023dc8dd98
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.672547] RBP: ffff8800374e3eb8 R08: 000000000000000a R09: 0000000000000000
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.673890] R10: 0000000000000000 R11: 00000000000009bc R12: 0000000000000009
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.675080] R13: 0000000000000009 R14: ffff8800374e3f20 R15: 0000000000000009
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.676237] FS:  00007f92c016d740(0000) GS:ffff88023dc80000(0000) knlGS:0000000000000000
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.677373] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.678484] CR2: 00000000015c9004 CR3: 000000008fbd5000 CR4: 00000000003406e0
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.679420] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.680331] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.681209] Stack:
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.682065]  ffff880139bf6300 00000000015c9000 ffff8800374e3ec8 ffffffff812010c8
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.682936]  ffff8800374e3f08 ffffffff812016e2 ffffffff8120161c ffff880139bf6300
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.683789]  ffff880139bf6300 00000000015c9000 0000000000000009 0000000000000009
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.684640] Call Trace:
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.685436]  [<ffffffff812010c8>] __vfs_write+0x18/0x40
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.686232]  [<ffffffff812016e2>] vfs_write+0xa2/0x1a0
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.687028]  [<ffffffff8120161c>] ? vfs_read+0x10c/0x130
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.687818]  [<ffffffff81202406>] SyS_write+0x46/0xa0
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.688604]  [<ffffffff8180cd36>] entry_SYSCALL_64_fastpath+0x16/0x75
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.689391] Code: c0 31 c0 5d c3 66 0f 1f 44 00 00 0f 1f 44 00 00 55 48 c7 c7 80 80 8f c0 31 c0 48 89 e5 41 54 49 89 d4 53 48 89 f3 e8 ff cb 88 c0 <0f> be 53 04 0f be 33 48 c7 c7 a8 80 8f c0 31 c0 e8 ea cb 88 c0
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.691080] RIP  [<ffffffffc08f7070>] dev_write+0x20/0x40 [hvacchar]
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.691905]  RSP <ffff8800374e3ea8>
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.692728] CR2: 00000000015c9004
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.693552] ---[ end trace eee0478c7200f93f ]---
Aug 31 15:17:31 app-ThinkCentre-M900 kernel: [873020.693962] HVACChar: Device successfully closed

我是linux和设备驱动程序的新手。请温柔:)

1 个答案:

答案 0 :(得分:2)

嗯,原因很简单。您的代码在内核上下文中执行,而包含数据的缓冲区来自用户空间。任何内核的最大目标之一是提供内存保护,因此内核和用户空间使用不同的内存区域。如果需要从用户空间获取一些数据,请使用 copy_from_user() 功能将其复制到内核内存中。如果您不遵循该方案并且只是尝试直接访问数据,这将导致内存访问冲突,并且内核会抱怨它(就像在您的日志输出中):&#34;无法处理内核分页请求&#34;。

因此,正确的解决方案(基于您的代码)看起来有点像这样:

#include <linux/slab.h>

static ssize_t dev_write(struct file *filep, const char __user *buffer, size_t len, loff_t *offset) {
    char *buf_internal;

    buf_internal = kmalloc(len, GFP_KERNEL);
    if (buf_internal == NULL)
        return -ENOMEM;

    if (copy_from_user(buf_internal, buffer, len)) {
        kfree(buf_internal);
        return -EFAULT;
    }

    buf_internal[len - 1] = '\0';

    printk(KERN_INFO "HVACCHAR: Entered dev_write()\n");
    printk(KERN_INFO "HVACChar: b4 sprintf(): buffer=%c\n", buf_internal[0]);

    kfree(buf_internal);

    return len;
}

请找到添加到函数原型的__user限定符,以突出显示缓冲区的性质。我没有测试代码,但我希望这个想法非常明确:)