How to change void* parameter inside of a thread function - c

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.

Related

How to pass a char *array (belonging to the user address space) to a tasklet or workqueue in a kernel module?

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.

Modify the user stack pointer in kernel mode

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.

Failed to get void ponter as function arguments while calling function from application to Dynamic Loaded Library in Linux

I have created one dynamic library in Linux OS. There is one function called test which has one argument as void *buffer.
I have used mmap call inside that function which maps memory successfully without any issue.
I have mapped that memory into one global char *buffer inside dynamic loaded library.
void *buffer;
int test(void *buffer_app)
{
buffer = (char *)mmap(0, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, 0);
buffer_app = (char *)buffer;
return 0;
}
Than, I have created one command line test application which will open that dynamic library using dlopen function.
All, above things works fine as per requirement.
After that, I have kept one void *buffer as global inside command line test application and passed it as argument of test function to map memory from dll.
void *buffer;
int main()
{
void *handle;
int status = 0;
handle = dlopen("libtest.so", RTLD_NOW | RTLD_GLOBAL);
dlerror(); /* Clear any existing error */
giPtr = dlsym(handle, "GI_Funcs");
status = giPtr->test(buffer);
}
So, I am getting address of buffer as 0x0 instead of address which points memory called by mmap in dynamic library.
Does anyone has idea about this issue?
Change your dll function as:
int test(void *buffer_app)
{
buffer = (char *)mmap(0, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, 0);
*(char **)buffer_app = buffer; /* Optional: No need to cast */
/* ^ */
return 0;
}
And later call it as:
status = giPtr->test(&buffer);
/* ^ */
You are passing pointer by value and the local value of pointer (argument) is being changed. Send the address of pointer to reflect the change in caller function also.

copy_from_user gives null pointer

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.

How can I get rid of this c warning?

Here sock_client is an socket:
LaunchThread(proxy_handlereq, sock_client);
static void LaunchThread(int (*func)(), void *parg)
{
#ifdef WINDOWS
LPDWORD tid;
CreateThread(NULL, 0L, (void *)func, parg, 0L, &tid);
#else
pthread_t pth;
pthread_create(&pth, NULL, func, parg);
#endif
}
I'm getting the following warning: warning: cast to pointer from integer of different size
How can I pass it as the 2nd parameter of LaunchThread?
Try this:
LaunchThread(proxy_handlereq, (void*)sock_client);
Edit:
Ok, now I see: sock_client is just the integer number of the port.
And you want to pass this number to the other thread, right?
(Depending on the pointer size on your system) you can get rid of the
warning by this dirty cast:
LaunchThread(proxy_handlereq, (void*)(0xFFFFFFFFFFFFFFFF & sock_client);
But actually I would recommend, that you create a data structure with
all the information, that you want to pass to the other thread, e.g.:
struct MyData {
int socket_no;
const char* host_name;
...
};
Then create an instance of this and pass a pointer to the instance to
your LaunchThread function.
Edit2:
You can see some sample code in this question:
Multiple arguments to function called by pthread_create()?
If sock_client is a socket, you need to invoke LaunchThread as:
LaunchThread(proxy_handlereq, &sock_client);
because both CreateThread and pthread_create expect a pointer to the argument to pass on to func().

Resources