2

I created the device file under /dev folder successfully, but writing to that device file makes kernel to throw following error messages.

Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10090.943733] Internal error: : 1b [#3] PREEMPT SMP ARM

Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10091.049020] Process echo (pid: 3728, stack limit = 0xdc40a218)

Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10091.054880] Stack: (0xdc40be60 to 0xdc40c000)

Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10091.059267] be60: c15491c6 00000022 dc5cb14c bf30430c dc40bedc dc40be88 c075312c c074fe5c

Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10091.067488] be80: c0753018 ffffff04 ffff0a00 c140414c c0d407c8 bf30430c c140414c 40cfbcf3

Message from syslogd@beaglebone at Feb 26 15:40:10 ... kernel:[10091.075709] bea0: 00852878 ffffff04 ffff0a00 00040952 c01a7404 c140414c 00852878 00852878

Segmentation fault

I know very basic of Linux Device Drivers

Can anyone help me with this issue??

I am attaching the code snippet I'm using for character file writing

#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/uaccess.h>
#include<linux/device.h>


MODULE_AUTHOR("RUCHA");
MODULE_DESCRIPTION("Character Driver First test");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.0.1");


static int MajorNum;
static struct class* RetValOfClassRegistration = NULL;
static struct device*  RetVal = NULL;
static char message[1024];
static int openDev(struct inode * , struct file *);
static int closeDev(struct inode * , struct file *);
static ssize_t readDev(struct file *, char *, size_t, loff_t *);
static ssize_t writeDev(struct file *, const char *, size_t, loff_t *);

static struct file_operations FileOps = {

    .owner = THIS_MODULE,
    .open = openDev,
    .read = readDev,
    .write = writeDev,
    .release = closeDev,

};

static int registerCharDev(void){

    return register_chrdev(0,"MyDev",&FileOps);
}

static int __init Loaded(void){

    // registering device

    MajorNum = registerCharDev();

    if(MajorNum < 0){
        printk("Can not register device\n");
        return -1;
    }

    printk("Driver Loaded with %d \n",MajorNum);


    // registering device class

    RetValOfClassRegistration = class_create(THIS_MODULE,"MyCharacterDriver");

    if(RetValOfClassRegistration < 0){

        printk("can not register class for driver number : %d\n",MajorNum);
        return 0;
    }


    // register the driver

    RetVal = device_create(RetValOfClassRegistration,NULL,MKDEV(MajorNum,0),NULL,"MyDev");


    return 0;

}


static void __exit Removed(void){
    device_destroy(RetValOfClassRegistration,MKDEV(MajorNum,0));
    class_unregister(RetValOfClassRegistration);
    class_destroy(RetValOfClassRegistration);
    unregister_chrdev(MajorNum,"MyDev");
    printk("Driver Removed\n");
}


module_init(Loaded);
module_exit(Removed);


static int openDev(struct inode *inodep , struct file *filep){

    printk("Device is now open to read write operations\n");
    return 0;
}


static int closeDev(struct inode *inodep , struct file *filep){

    printk("Device Closed\n");
    return 0;
}

static ssize_t readDev(struct file *filep, char *c, size_t v, loff_t *lp){

    printk("Read From the device\n");
    return 0;
}

static ssize_t writeDev(struct file *file, const char __user *buf, size_t len, loff_t *offset)
{
    sprintf(message, "%s(%zu letters)", buf, len);
    return 0;
}

and the user input I'm giving is by echo command

echo '1' > /dev/MyDev

please help me regarding this!

6
  • Looks like you got yourself a kernel oops. You can get a more detailed log via the dmesg command. Most probably your character device driver does something wrong in its write handler.
    – dragosht
    Feb 26, 2020 at 14:07
  • Yes It seems like that, this is the statement I used for device file writing sprintf(message, "%s(%zu letters)", buffer, len); Feb 27, 2020 at 4:51
  • where the message is the string I entered from the terminal and buffer is the char* of length len to hold that string. Feb 27, 2020 at 5:08
  • There's currently not enough information here to tell exactly what goes wrong. You should also edit in your message the code you use for your char device, the terminal commands you use to insert/write to the device and the kernel logs.
    – dragosht
    Feb 27, 2020 at 5:55
  • Yes !! I added the code for character file writing. Feb 28, 2020 at 4:55

1 Answer 1

1

As I was saying ... The problem is in your char driver's write function. More specifically, you're accessing the buffer from user space directly. You're not supposed to do that - the kernel has a specific API for that. See for instance this StackOverflow post on the topic.

For your specific case, you should drop the sprintf and use copy_from_user to copy data from the user space buffer into the driver's buffer. Something like this fixes the issue on my beaglebone black board:

static ssize_t writeDev(struct file *file, const char __user *buf, size_t len, loff_t *offset)
{
    printk("Write to device buf: 0x%p: len = %d, offset = %lld\n", buf, len, *offset);

    if (copy_from_user(message, buf, len)) {
        printk("Unable to read buffer from user\n");
        return -EFAULT;
    }   

    return len;
}
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .