copy_to_user set array at index - c

I am writing a character device driver, but at the moment it freezes, and i have to reboot to stop it or crashes and the terminal exits
I have a global array
char* array;
On which i use kmalloc(9, GFP_KERNEL) so it should be the size of 9. If i wanted to use file operations .write to set a specific index how would i do that?
This is my current code (which crashes and terminal exits)
ssize_t mydriver_write(struct file *filp, const char* buf, size_t count, loff_t *f_pos)
{
raw_copy_to_user(array[*buf], 'x', 1);
}
EDIT:
I have already tried this version aswell
raw_copy_to_user(&array[3], x, 1);
where x is kmalloc'd to size 1 and x[0]='x'
But in this case my program freezes and i cannot remove the driver and the machine requires a reboot to remove it.

Related

Sscanf to device for reading lines with offset

I've created a user space program that reads from a text file into a buffer, and writes it to device using fprintf and the store function from said device.
The user space program is supposed to write the entire buffer and send it into the store function's buf parameter.
//store function for chardev
ssize_t modify(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) //sysfs store/write implementation - add new rule
Then the device is supposed the read the strings from the buffer 9 by 9 (hard coded size of line in the buffer).
for(j=0;j<=num_of_rules;j++){
if((read=sscanf(buf,"%s%s%s%s%s%s%s%s%s%n",
rule_name, direction_string, src_ip,
dst_ip, src_port_string, dst_port_string,
protocol_string, ack_string, action_string, &offset))==9)
{
printk("offset = %u",offset);
EDIT: Adding pictures of the run attempt
Picture 1: Running the user space program and printing the contents of buf:
Picture 2: Running dmesg and showing that the data has been written to the kernel module. Also, the offset is 59, the length of the first line:
The reading of the first line goes fine, and the offset is correct, but when I try to advance buf with the offset using buf+=offest, the next run kills the process and prints "Killed".
Why is that and how can I fix it?
Thank you.

Writing to a file from a kernel module

I need to implement the following function as part of a kernel module:
ssize_t write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
which writes buf into the file filp using f_pos, and then updates f_pos.
my question is how can I write to f_pos and then change it's value?
I understand that it points to the start of the free file space but how can I update it after i'm done writing?
Thank you

Linux kernel module : my variable lost its value when it's used in thread function

I am developing a Linux kernel module which read my embedded board button code and use it in order to turn on/off the board led.
When I push button, the module is sending correctly the button code, which is 260, to user-space.
Now, from user-space, I am using the write function in order to re-send this code kernel module :
write(fd, buf_wr, strlen(buf_wr));
Where fd is the file descriptor of my module, and buf_wr is the buffer which will be written to the file.
In kernel space, I am using the write_pid function in this way :
static ssize_t write_pid(struct file *pfile, const char __user *buffer,
size_t length, loff_t *offset)
{
char cod_buf[12];
printk("WE ARE IN WRITE_PID FUNCTION\n");
copy_from_user(cod_buf, buffer, length);
sscanf(cod_buf, "%i", &lcode);
printk("lcode = %i\n", lcode);
return 0;
}
I defined lcode in my kernel module as a global variable :
int lcode = 0;
and I can see that it is receiving the correct button code which is 260.
Now, I created a thread in the module, I want this thread to run some instructions basing on the button code :
int write_in_thread(void *data) {
printk("Under write_in_thread, lcode = %i\n", lcode);
switch (lcode) {
case 260:
//instructions....
//instructions....
//instructions....
break;
default :
//instructions....
break;
}
return 0;
}
The problem here, I can see that, Under write_in_thread, lcode = 0. It's not 260. So the case statement is running the default one which I don't need here.
How can I fix the lcode variable in order to keep it's value in the thread function?
Thank you!

Writing to Linux device driver causes infinite loop

I have been writing a kernel space device driver that can be read from and written to from user space. The open, read, release operations all work perfectly. The problem I am having is with the user-space code that should access the device driver and and write something to it.
The user-space program writes to two files: 1) to a .txt file (and prints a to the console to let the user know it was completed), and 2) to the device driver (and also prints a text to let the user know it was also completed).
Below is the user-space code in full:
int main() {
FILE *fp;
fp = fopen("./test.txt","w");
fputs("Test\n", fp);
fclose(fp);
printf("Printed to txt\n"); //Prints normally.
fp = fopen("/dev/testchar", "w");
fputs("Test\n", fp);
fclose(fp);
printf("Printed to dev\n"); //Never gets to this point
return 0;
}
When I compile and run the code the program spits out
Printed to txt
and just hangs until ctrl+c is called. It never gets beyond the second fputs().
While monitoring kern.log I see endless calls to write to the device driver.
Here I have extracted relevant code from the device driver:
static char msg[256] = {0};
static struct file_operations fops =
{
.write = dev_write
};
static ssize_t dev_write(struct file *file, const char *buf, size_t len, loff_t *ppos)
{
sprintf(msg, "Input:%s, Chars:%lu\n", buf, len);
printk(KERN_NOTICE "%s\n", msg);
return 0;
}
uname -r: 4.10.0-38-generic
gcc -v: gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
My question is: why is the program getting stuck in an infinite loop when writing to the device, and how do I fix it?
Thanks in advance. Any help will be greatly appreciated.
I think the kernel write operation is supposed to return the number of bytes written. You return 0. So the write system call returns to userspace with 0. However, since your userspace code is using stdio, then your userspace code tries the write again, assuming the system call simply didn't write out all the data. If you return the length of the input, then stdio will know all the data was written. Alternatively you can use the write system call directly rather than fputs. Your kernel code will still be incorrect, but your program will terminate.
You can test this using strace and see all the system calls.

C - infinite read from cat in Device file

I've been having some headache with infinite reads from cat (cat doesn’t close because it doesn’t receive end of function from my read function. How can I implement an end of read so that reading the file with cat will only produce 1 output per command in the terminal?
function. This is the kernel read() function I've written:
static ssize_t dev_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
char tmp_buf[MAX_BUF_SIZE]; //defined as 100
int bLen=0;
sprintf(tmp_buf, "Some message");
bLen = strlen(tmp_buf);
if(copy_to_user(buf,tmp_buf, bLen)){
return -EFAULT;
}
return bLen;
}
I'm answering because I found this early on in my search.
Cat continually reads until it gets an empty response. Once it finished getting some data it goes back and asks "have anything else?" To which your module says yes and sends it the data again. You need to break the chain and have it send an empty response. The best way to do this would be to place
if(*ppos > 0){
return 0;
}
at the beginning of the function and add the length of the data you are sending back to *ppos before exiting.

Resources