Within char device, where do i put ioread? - c

I've got a pci device and all I want is to read its memory by "cat"ing from /dev/pcidevice. My first attempt for the char device's read function looked like this:
ssize_t cdev_read(struct file *filp, char __user *buffer, size_t count, loff_t *f_pos) {
ssize_t retval = 0;
struct mypci_dev *device = filp->private_data;
/* reading data from pci device */
device->values.fst = ioread16(device->bar[0]+OFFSET_FST);
device->values.snd = ioread16(device->bar[0]+OFFSET_SND);
...
device->values.lst = ioread16(device->bar[0]+OFFSET_LST);
retval = copy_to_user(buffer, &device->values.fst, count);
return retval;
}
And it didn't work :/ I changed the copy_to_user line into
retval = copy_to_user(buffer, "dummy", strlen("dummy")+1);
but cat /dev/pcidevice still returned nothing.
Next I shifted all ioread16 calls into cdev_open() and I got what I wanted. But now I'm curious why it's only working this way. And how can I make it work the other way?
ATM I think about timers that start copying etc. but some kind of wait until ioreads have finished would be enough.
Any ideas?

copy_to_user() function returns number of bytes that could not be copied. On success, it returns 0. Now imagine how surprised the user space would be when it reads 0 bytes.
The real question is how that actually works inside cdev_open()? I hope that you read I/O bar in that function and not sending anything to the user space. In that case, try adding rmb(); after your reads before calling copy_to_user() to make sure every read is finished (rmb() is a read memory barrier).
Also, check out LDD chapter 3 and chapter 5 if you haven't done so already.
Hope it helps. Happy hacking!

Related

linux proc size limit problems

I'm trying to write a linux kernel module that can dump the contents of other modules to a /proc file (for analysis). In principle it works but it seems I run into some buffer limit or the like. I'm still rather new to Linux kernel development so I would also appreciate any suggestions not concerning the particular problem.
The memory that is used to store the module is allocated in this function:
char *get_module_dump(int module_num)
{
struct module *mod = unhiddenModules[module_num];
char *buffer;
buffer = kmalloc(mod->core_size * sizeof(char), GFP_KERNEL);
memcpy((void *)buffer, (void *)startOf(mod), mod->core_size);
return buffer;
}
'unhiddenModules' is an array of module structs
Then it is handed over to the proc creation here:
void create_module_dump_proc(int module_number)
{
struct proc_dir_entry *dump_module_proc;
dump_size = unhiddenModules[module_number]->core_size;
module_buffer = get_module_dump(module_number);
sprintf(current_dump_file_name, "%s_dump", unhiddenModules[module_number]->name);
dump_module_proc = proc_create_data(current_dump_file_name, 0, dump_proc_folder, &dump_fops, module_buffer);
}
The proc read function is as follows:
ssize_t dump_proc_read(struct file *filp, char *buf, size_t count, loff_t *offp)
{
char *data;
ssize_t ret;
data = PDE_DATA(file_inode(filp));
ret = copy_to_user(buf, data, dump_size);
*offp += dump_size - ret;
if (*offp > dump_size)
return 0;
else
return dump_size;
}
Smaller Modules are dumped correctly but if the module is larger than 126,796 bytes only the first 126,796 bytes are written and this error is displayed when reading from the proc file:
*** Error in `cat': free(): invalid next size (fast): 0x0000000001f4a040 ***
I've seem to run into some limit but I couldn't find anything on it. The error seems to be related so memory leaks but the buffer should be large enough so I don't see where this actually happens.
The procfs has a limit of PAGE_SIZE (one page) for read and write operations. Usually seq_file is used to iterate over the entries (modules in your case ?) to read and/or write smaller chunks. Since you are running into problems with only larger data, I suspect this is the case here.
Please have a look here and here if you are not familiar with seq_files.
A suspicious thing is that in dump_proc_read you are not using "count" parameter. I would have expected copy_to_user to take "count" as third argument instead of "dump_size" (and in subsequent calculations too). The way you do, always dump_size bytes are copied to user space, regardless the data size the application was expecting. The bigger dump_size is, the larger the user area that gets corrupted.

how to use 'cat' in following simple device read program

static ssize_t device_read (struct file* filp, char *bufStoreData, size_t bufCount, loff_t* curOffset)
{
printk(KERN_INFO"reading from the device");
ret = copy_to_user(bufStoreData,virtual_device.data,bufCount);
return ret;
}
does copy_to_user returns number of bytes remaining to read or number of bytes read?
whats the use of bufcount if i am using cat
if all the data is not read in single call how it can read the remaining data?Is this responsibility of application to issue system call again or the driver works automatically?
I need to understand this basic concept.
copy_to_user() returns the number of bytes that couldn't be copied to user space. If the complete buffer could be copied, it returns 0.
Normally, if !=0, means that there was some sort of memory problem (writting past a legal memory address), so these situations should be detected and reported to the user.
static ssize_t device_read (struct file* filp, char *bufStoreData,
size_t bufCount, loff_t* curOffset)
{
size_t bytes_to_copy;
printk(KERN_INFO"reading from the device");
/* do stuff to get device data into virtual_device.data . Also
update virtual_device.datasize */
bytes_to_copy = (virtual_device.datasize <= bufCount)?
virtual_device.datasize : bufCount;
/* note that I'm not using bufCount, but an hypothetical field in
virtual_device that gives me how much data the device has ready
for the user. I choose the lower of both */
/* Also recall that if the number of bytes requested by the user is
less than the number of bytes the device has generated, then the
next read should return the remainder of the device data, so the
driver should carry the count of how many bytes have been copied
to the user and how many are left. This is not covered in this
example. */
ret = copy_to_user(bufStoreData,virtual_device.data, bytes_to_copy);
if (ret != 0)
return -EPERM; /* if copy was not successful, report it */
return bytes_to_copy;
}
When the user issues ret = read (fd, buffer, sizebuff); it expects one of these things and should react accordingly:
ret is equal to sizebuff. That means that read could return all the data the user requested. Nothing else to do here.
ret is positive, but less than sizebuff. That means that the read gave the user some data, but not as much as he requested. The user process must re-issue the read syscall to retrieve the remaining data, if needed. Something like: ret = read (fd, buffer+ret, sizebuff-ret);
ret is 0. This means that the device has no more data to send. It's the EOF condition. User process should close the device.
ret is < 0. This is an error condition. User process must check errno and take appropiate measures.
Your device driver will have to return an appropiate value in device_read according to what happened to the device when it was read.
On the other hand, a process like cat expects to read as much as 4096 bytes per read call. If the device sends less than that, it will print the received data and will ask for more. cat will only stop if it receives a signal (Ctrl-C for example), or if a read call returns an unrecoverable error (such as ENODEVICE, which should be generated by your driver if such condition arises), or if reads 0 bytes (EOF condition).
A rather silly device that returns "Hello, world" to the user process. It employs some global data that must be reset in device_open function. Note that if several processes are going to use your device at the same time, these global data must be turned into instance data (using file->private_data). This device_read example shows how to deal with device buffers and user buffers, and how to keep track of bytes sent to the user, so the device never sends more data than it has, never sends more data than the user requests, and when the device runs out of data, it returns 0 to the user.
int curindx = 0; /* should be reset upon calling device_open */
static ssize_t device_read (struct file* filp, char *bufStoreData,
size_t bufCount, loff_t* curOffset)
{
size_t bytes_to_copy;
char device_data[]="Hello, world!\n";
size_t remaindersize;
remaindersize = strlen(device_data) - curindx;
bytes_to_copy = (remaindersize <= bufCount)?
remaindersize : bufCount;
ret = copy_to_user(bufStoreData,device_data+curindx, bytes_to_copy);
if (ret != 0)
return -EPERM; /* if copy was not successful, report it */
curindx += bytes_to_copy;
return bytes_to_copy;
}
1) does copy_to_user returns number of bytes remaining to read or number of bytes read?
copy_to_user returns a number of bytes that could not be copied.
2) whats the use of bufcount if i am using cat
bufCount is a number of bytes user can read. In other words, it's a buffer size of user space application. I guess cat uses multiple of PAGE_SIZE for buffer size, actually you can check it yourself by adding printk to your device_read() function:
print(KERN_INFO "bufCount=%ld\n", bufCount);
3) if all the data is not read in single call how it can read the remaining data? Is this responsibility of application to issue system call again or the driver works automatically?
User space programs use read() system call to read data from files (including block and character devices) which returns 0 only if the end of file is reached. That's how they know when to stop. So, yes, it's responsibility of user-space program to read remaining data (if it needs to).
ssize_t ret;
...
while ((ret = read(fd, buf, bufsize)) > 0) {...};
if (ret < 0)
error();
On the other hand, the responsibility of device driver is to correctly maintain offsets inside its internal structures and return values that make sense.
P/S:
I'd recommend you to read a book "Linux device drivers" which is freely available in internet (http://lwn.net/Kernel/LDD3/) and touches these topics in details.

copy_to_user vs memcpy

I have always been told(In books and tutorials) that while copying data from kernel space to user space, we should use copy_to_user() and using memcpy() would cause problems to the system. Recently by mistake i have used memcpy() and it worked perfectly fine with out any problems. Why is that we should use copy_to_user instead of memcpy()
My test code(Kernel module) is something like this:
static ssize_t test_read(struct file *file, char __user * buf,
size_t len, loff_t * offset)
{
char ani[100];
if (!*offset) {
memset(ani, 'A', 100);
if (memcpy(buf, ani, 100))
return -EFAULT;
*offset = 100;
return *offset;
}
return 0;
}
struct file_operations test_fops = {
.owner = THIS_MODULE,
.read = test_read,
};
static int __init my_module_init(void)
{
struct proc_dir_entry *entry;
printk("We are testing now!!\n");
entry = create_proc_entry("test", S_IFREG | S_IRUGO, NULL);
if (!entry)
printk("Failed to creats proc entry test\n");
entry->proc_fops = &test_fops;
return 0;
}
module_init(my_module_init);
From user-space app, i am reading my /proc entry and everything works fine.
A look at source code of copy_to_user() says that it is also simple memcpy() where we are just trying to check if the pointer is valid or not with access_ok and doing memcpy.
So my understanding currently is that, if we are sure about the pointer we are passing, memcpy() can always be used in place of copy_to_user.
Please correct me if my understanding is incorrect and also, any example where copy_to_user works and memcpy() fails would be very useful. Thanks.
There are a couple of reasons for this.
First, security. Because the kernel can write to any address it wants, if you just use a user-space address you got and use memcpy, an attacker could write to another process's pages, which is a huge security problem. copy_to_user checks that the target page is writable by the current process.
There are also some architecture considerations. On x86, for example, the target pages must be pinned in memory. On some architectures, you might need special instructions. And so on. The Linux kernels goal of being very portable requires this kind of abstraction.
This answer may be late but anyway copy_to_user() and it's sister copy_from_user() both do some size limits checks about user passed size parameter and buffer sizes so a read method of:
char name[] = "This message is from kernel space";
ssize_t read(struct file *f, char __user *to, size_t size, loff_t *loff){
int ret = copy_to_user(to, name, size);
if(ret){
pr_info("[+] Error while copying data to user space");
return ret;
}
pr_info("[+] Finished copying data to user space");
return 0;
}
and a user space app read as read(ret, buffer, 10); is OK but replace 10 with 35 or more and kernel will emit this error:
Buffer overflow detected (34 < 35)!
and cause the copy to fail to prevent memory leaks. Same goes for copy_from_user() which will also make some kernel buffer size checks.
That's why you have to use char name[] and not char *name since using pointer(not array) makes determining size not possible which will make kernel emit this error:
BUG: unable to handle page fault for address: ffffffffc106f280
#PF: supervisor write access in kernel mode
#PF: error_code(0x0003) - permissions violation
Hope this answer is helpful somehow.

talking to device in linux. WRITE function

I'm trying to write a simple device driver, and use the Dev_Read() and Dev_Write() functions, which I have already defined.
My driver registers a character device tied to a
given major number this way
# mknod /dev/mydev c 250 0
And then, from my user program I open the device this way
int fd;
if ((fd = open("/dev/mydev", O_RDWR)) < 0)
{
perror("open /dev/mydev");
exit(EXIT_FAILURE);
}
after I invoke the Read() function
int read_bytes = read (fd, buffer, 1);
and successfully get kernel space information, that my Dev_Read function works.
My problem is that I don't understand how to implement my Dev_Write function.
How can I write someting to my file, to see that Dev_Write function works ?
THANK YOU for help.
It would help to know what you've tried which didn't work.
One thing to be aware of, and not necessarily intuitive, is that your driver's write function must copy the write buffer from the caller's space into kernel space. An example of that can be seen in the tutorial at http://www.freesoftwaremagazine.com/articles/drivers_linux -
ssize_t memory_write( struct file *filp, char *buf,
size_t count, loff_t *f_pos) {
char *tmp;
tmp=buf+count-1;
copy_from_user(memory_buffer,tmp,1);
return 1;
}
where memory_buffer is space you've allocated within your driver.

locking of copy_[to/from]_user() in linux kernel

as stated in: http://www.kernel.org/doc/htmldocs/kernel-hacking.html#routines-copy this functions "can" sleep.
So, do I always have to do a lock (e.g. with mutexes) when using this functions or are there exceptions?
I'm currently working on a module and saw some Kernel Oops at my system, but cannot reproduce them. I have a feeling they are fired because I'm currently do no locking around copy_[to/from]_user(). Maybe I'm wrong, but it smells like it has something to do with it.
I have something like:
static unsigned char user_buffer[BUFFER_SIZE];
static ssize_t mcom_write (struct file *file, const char *buf, size_t length, loff_t *offset) {
ssize_t retval;
size_t writeCount = (length < BUFFER_SIZE) ? length : BUFFER_SIZE;
memset((void*)&user_buffer, 0x00, sizeof user_buffer);
if (copy_from_user((void*)&user_buffer, buf, writeCount)) {
retval = -EFAULT;
return retval;
}
*offset += writeCount;
retval = writeCount;
cleanupNewline(user_buffer);
dispatch(user_buffer);
return retval;
}
Is this save to do so or do I need locking it from other accesses, while copy_from_user is running?
It's a char device I read and write from, and if a special packet in the network is received, there can be concurrent access to this buffer.
You need to do locking iff the kernel side data structure that you are copying to or from might go away otherwise - but it is that data structure you should be taking a lock on.
I am guessing your function mcom_write is a procfs write function (or similar) right? In that case, you most likely are writing to the procfs file, your program being blocked until mcom_write returns, so even if copy_[to/from]_user sleeps, your program wouldn't change the buffer.
You haven't stated how your program works so it is hard to say anything. If your program is multithreaded and one thread writes while another can change its data, then yes, you need locking, but between the threads of the user-space program not your kernel module.
If you have one thread writing, then your write to the procfs file would be blocked until mcom_write finishes so no locking is needed and your problem is somewhere else (unless there is something else that is wrong with this function, but it's not with copy_from_user)

Resources