I'm attempting to write an Open RG kernel module that, at given intervals, sends a message up to the user space. To this end, I need the kernel to hold a pointer to a static buffer in the user space where this message will be stored. I'm having trouble sending the pointer to the kernel.
The user space function call is something like this (simplified, obviously):
typedef struct {
char msg[MAX_BOOT_MSG];
} msg_t;
static msg_t common_mem;
void user_space_func() {
openrg_module_ctrl(KOS_CDT_TEST, TEST_IOCTL_SET_COMMON_MEM, &common_mem.msg);
}
The kernel space usage is like this:
static void* msg_write;
static int do_ioctl(kos_chardev_t *context, unsigned int cmd,
unsigned long data) {
switch (cmd)
{
case TEST_IOCTL_SET_COMMON_MEM:
received_ioctl = 1;
int ret = copy_from_user(&msg_write, (void *)data, sizeof(char*));
printk("setting common mem to %p, received %d\n", msg_write, ret);
return 0;
}
default:
return -1;
}
The output is setting common mem to 0000000000000000, received 0. I see that common_mem.msg isn't NULL. Any idea what I'm doing wrong?
data is the address of the buffer, so by reading from that address, you are copying the contents of the buffer.
Please note that memory in user space can be moved or swapped out, so this address is valid only for the duration of the system call; you must not store the address for later usage.
Better allocate some memory in your driver, and allow the application to access it with mmap.
Related
I’m writing a device driver. If someone calls the write operation I want it to be deferred (using tasklet or workqueue). The code should be something like that:
static ssize_t dev_write(struct file *filp, const char *buff, size_t len, loff_t *off) {
packed_work *the_task;
the_task = kzalloc(sizeof(packed_work), GFP_ATOMIC);
if (the_task == NULL) {
printk(KERN_ERR "%s: tasklet buffer allocation failure\n", MODNAME);
return -1;
}
the_task->buffer = the_task;
the_task->buff = buff;
the_task->len = len;
INIT_WORK(&(the_task->the_work), (void*)deferred_write);
schedule_work(&the_task->the_work);
return len;
}
void deferred_write(struct work_struct *data) {
printk(“the text: %s\n”, container_of(data, packed_work, the_work)->buff);
//copy_from_user(&(the_object->stream_content), container_of(data, packed_work, the_work)->buff, len);
kfree((void*)container_of(data,packed_work,the_work));
}
And the struct looks like this:
typedef struct _packed_work{
void *buffer;
const char *buff;
size_t len;
struct work_struct the_work;
} packed_work;
The problem is that the kernel crashes. It crashes even before the copy_from_user (that’s why I commented it). In the deferred_write() I can print the length of the string but not the string itself. Is it a problem because the buffer is in the user space memory?
I know that, as a workaround, I can copy the user buffer in the task struct (using the copy_from_user() in the function write()) and then use the strcpy() in the deferred_write() function. But I really would like to use the copy_from_user() in deferred_write(). Is it possible? What can I do?
Even if it is possible (and there is surely a way), the user process has probably changed the contents of the buffer in the time before deferred_write runs. Notice that user programs often allocate these buffers on the stack, so they get overwritten when the function that called write returns and calls other functions.
Even worse: the user process could have unmapped the buffer, or it could have exited.
So you should not delay reading the buffer. You should read the buffer inside the write call and not anywhere else.
I am writing a char device that takes as input with ioctl a function pointer and a buffer pointer.
I want to modify the user machine context so that back in user mode, that function is executed with a new stack pointed by that buffer pointer.
What I have done is the following :
long ioctl_funcs(struct file *filp,unsigned int cmd, unsigned long arg)
{
int ret = 0;
switch(cmd) {
case IOCTL_SET_FUN:
printk(KERN_INFO "start\n");
struct myarg* a;
a = (struct myarg*) arg;
struct pt_regs* regs = task_pt_regs(current);
regs->ip = a->func;// func is a function implemented in user space
regs->sp = a->stack;// stack is the buffer allocated in user space with malloc
break;
}
return ret;
}
The good news is that the function is activated, the bad one is that the stack is the same (I have used gdb to test it).
In particular even if : regs->sp = 0; the new function is executed when it should crash since it should have no stack.
It seems the assignment of the stack pointer in this way is ineffective.
Why? How should I correctly assign the stack pointer?
The linux kernel version is : 3.18.106 and it is executed on Virtual Box.
I have a struct as so:
typedef struct
{
char* BUFFER;
int Size;
}DataTransfer;
In my IOCTL function I attempt to populate the struct and pass to userspace:
case CHAR_DRIVER_IOCQREAD:
printk(KERN_INFO "In CHAR_DRIVER_IOCQREAD");
dataTransfer.BUFFER = kmalloc(strlen_user("Hello") +1, GFP_KERNEL);
dataTransfer.Size = strlen_user("Hello") +1;
error_count = copy_to_user((DataTransfer*) arg, &dataTransfer, sizeof(dataTransfer) );
In userspace I attempt to receive the struct as so:
DataTransfer dataTransfer;
if(ioctl(fd, CHAR_DRIVER_IOCQREAD, &dataTransfer) < 0)
{
perror("ERROR in ioctl CHAR_DRIVER_IOCQREAD");
}
else
{
printf("Kernel returned size %d \n", dataTransfer.Size);
printf("Kernel returned string %s \n", dataTransfer.BUFFER);
}
What is the correct way of doing this?
A couple of problems here. First, you are copying the structure to user space but not the string it points to. The structure will point to the kernel memory you allocated which user space can not access. Second you are allocating the kernel memory but not actually putting anything there.
One way of doing this would be for user space to allocate memory for the IOCtl to write the string into and then pass a structure like your DataTransfer to the IOCtl describing the memory it allocated. The kernel would read the structure from user memory using copy_from_user and then, if the buffer allocated was large enough to hold the string, write it there using copy_to_user on the address passed to it inside the structure.
E.g. (kernel side, sketch only):
case CHAR_DRIVER_IOCQREAD:
DataTransfer dataTransfer;
if (copy_from_user(&dataTransfer, arg, sizeof(dataTransfer)))
return -EFAULT;
if (dataTransfer.Size < strlen(myString) + 1)
return -ENOMEM;
if (copy_to_user(dataTransfer.BUFFER, myString, strlen(myString) + 1))
return -EFAULT;
This question already has answers here:
copy_to_user vs memcpy
(2 answers)
Closed 7 years ago.
Let consider following code. For someone who read Linux Device Driver the context will be clear.
In short,
sbull is a driver which acts a disk device and the sbull_transfer function aims to transfer block of data from/to disk/user_space.
And everything is clear expect one thing.
I don't understand why we can just simply use memcpy function. After all, we copy from user space so why it is possible? Usually, I noticed, that we should use copy_from_user()/copy_to_user().
I don't understand why we needn't to use them. Please explain.
static void sbull_transfer(struct sbull_dev *dev, unsigned long sector,
unsigned long nsect, char *buffer, int write)
{
unsigned long offset = sector*KERNEL_SECTOR_SIZE;
unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;
if ((offset + nbytes) > dev->size) {
printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
return;
}
if (write)
memcpy(dev->data + offset, buffer, nbytes);
else
memcpy(buffer, dev->data + offset, nbytes);
}
The sbull driver can implement the actual data transfer with a simple memcpy call because data is already in memory, after all.
Function
static void sbull_request(request_queue_t *q)
{
struct request *req;
while ((req = elv_next_request(q)) != NULL) {
struct sbull_dev *dev = req->rq_disk->private_data;
if (! blk_fs_request(req)) {
printk (KERN_NOTICE "Skip non-fs request\n");
end_request(req, 0);
continue;
}
sbull_transfer(dev, req->sector, req->current_nr_sectors,
req->buffer, rq_data_dir(req));
end_request(req, 1);
}
}
calls elv_next_request before data is passed to sbull_transfer. Request function takes care about copying data to/from user space. The buffer contained in returned request struct is described in book as:
char *buffer;
A pointer to the buffer to or from which the data should
be transferred. This pointer is a kernel virtual address and can be
dereferenced directly by the driver if need be.
I am creating a thread for each request from the client to get the files on the server. Thread function normally gets a void pointer; but I need to give it a char pointer as a parameter and want it to be populated with the file names by the thread function.
Code creates a thread:
pt_ret = pthread_create(&thread_id, NULL, getfiles, (void*) thread_buff);
pthread_join(thread_id, pt_ret);
Def. of thread function:
void *getfiles(void *ptr) {
/* ... */
char buff[256]; // populating that local buffer with the file names
// ptr should be as a return of buff
}
I have tried different things but each time after that thread completes, thread_buff becomes just 'Q'.
Just cast it to a char*, since you know it actually is a char*:
void *getfiles(void *ptr) {
/* ... */
const char *ptr_char = (const char*)ptr;
char buff[256];
memcpy(buff, ptr_char, 256); //just as an example, check the sizes.
//you could also strcpy, that's up to you
}
Or you could also just work on the buffer pointed by ptr, without copying it, so it's accessible after the thread has ended:
void *getfiles(void *ptr) {
/* ... */
char *buff = (char*)ptr;
/* do stuff with buff. */
}
I think the problem is you want to use data stored in your thread's "buff" var AFTER the thread ends. Which is not possible, the data only exists on the stack temporarily.
You have to pass a char**ptr, and populate it with a copy of buff, like:
*ptr = strdup(buff)
And pass (void*)&thread_buff instead of (void*)thread_buff to the thread function.