Copy struct containing char* from kernel to user - c

I have a struct that looks like this:
struct ProcStruct {
pid_t procID;
char *name;
};
On the kernel side, I've defined a system call that has this header
SYSCALL_DEFINE3(dfsproc, pid_t, pid, int32_t *, pidc, struct ProcStruct *, ps)
I'm trying to copy kps which has the same type as ps (which is struct ProcStruct* as mentioned in the syscall header) to the user accessible memory using:
copy_to_user(ps, kps, sizeof(struct ProcStruct) * 256);
The problem is that this is actually a shallow copy, so char *name isn't copied.
What should I do in order to copy the char* into the user accessible memory?

Related

How to write after the end of the already initialized struct?

I have a struct initialized on a stack, and i want to write data in memory right after the struct and make a pointer inside a struct point to that data.
I know it is achievable on the stack/heap with uninitialized structure using malloc(sizeof(struct) + additional size) or alloca(). but can i perform initialization of a data after the struct is already initialized on the stack? and can i perform this initialization inside a initializator function?
Simple example:
struct TEST {
wchar_t* itest;
};
void init_struct(struct TEST* test) {
// point to the end of the struct
char* walk_ptr = (char*)test + sizeof(test);
test->itest = (wchar_t*)walk_ptr;
// initialize data after the struct
...
}
int main(void) {
struct TEST test;
init_struct(&test);
return 0;
}
You could do this by embedding the structure inside another structure to reserve memory for the extra data:
int main(void)
{
struct { struct TEST test; wchar_t data[NumberOfElements]; } S;
init_struct(&S.test);
…
}
However, the code in init_struct adds an incorrect size, sizeof(test), to the pointer. You likely wanted to add sizeof (struct Test), or, equivalently, sizeof *test, since you want to get past the struct TEST that test points to, not past a struct TEST * that test is.
However, even adding the correct size of the structure would not guarantee strictly conforming C code, since C implementations may insert padding between structure members. Properly we would add the offset of the data member. To do that, we nwould eed to give the structure a tag and then either make the structure definition visible to init_struct or pass the offset to init_struct. However, it is easier just to pass the address of the extra data:
void init_struct(struct TEST *test, wchar_t *data)
{
test->itest = data;
}
int main(void)
{
struct { struct TEST test; wchar_t data[NumberOfElements]; } S;
init_struct(&S.test, S.data);
…
}
Of course, a pointer can point anywhere, and there is no apparent reason the data should be immediate after the structure, so we can disconnect them:
int main(void)
{
struct TEST test;
wchar_t data[NumberOfElements];
init_struct(&test, data);
…
}

Allocating a struct dirent without malloc()

I need to use readdir_r() to read the contents of a directory in a multithreaded program. Since the size of struct dirent is filesystem dependent, man readdir_r recommends
name_max = pathconf(dirpath, _PC_NAME_MAX);
if (name_max == -1) /* Limit not defined, or error */
name_max = 255; /* Take a guess */
len = offsetof(struct dirent, d_name) + name_max + 1;
to find the size of the allocation needed. To allocate it
entryp = malloc(len);
is called, and finally readdir_r() uses it like this:
struct dirent *returned;
readdir_r(DIR*, entryp, &returned);
However, I'd like to avoid calling malloc() (or any other manual memory management function).
One way I've thought of is
_Alignas(struct dirent) char direntbuf[len];
struct dirent *entryp = (struct dirent*) direntbuf;
This should give a correctly aligned allocation, but it violates strict aliasing. However, the buffer is never accessed via a char* so the most likely problem, the compiler reordering accesses to the buffer via different types, cannot occur.
Another way could be by alloca(), which returns a void*, avoiding strict aliasing problems. However, alloca() does not seem to guarantee alignment the way malloc() and friends do. To always get an aligned buffer, something like
void *alloc = alloca(len + _Alignof(struct dirent));
struct dirent *direntbuf = (struct dirent*)((uintptr_t)&((char*)alloc)[_Alignof(struct dirent)]&-_Alignof(struct dirent));
would be needed. In particular, the cast to char * is needed to perform arithmetic on a pointer, and the cast to uintptr_t is needed to do the binary &. This doesn't look more well-defined than allocating a char[].
Is there a way to avoid manual memory management when allocating a struct dirent?
What about defining this:
#include <stddef.h> /* For offsetof */
#include <dirent.h>
union U
{
struct dirent de;
char c[offsetof(struct dirent, d_name) + NAME_MAX + 1]; /* NAME_MAX is POSIX. */
};
The readdir_r function signature is:
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
And direct is a struct like this:
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported
by all file system types */
char d_name[256]; /* filename */
};
You have to pass a pointer to readdir_r but how you allocate memory for the dirent structure is entirely up to you.
You could do it like this and use a stack variable.
struct dirent entry = {0};
...
readdir_r(DIR*, &entry, &returned);

Calling a user defined function in kernel space from user space application program

I have written a user defined function in my device driver and I want to call it from user space application program. How do I achieve this?
What I mean by user defined function is, any function other than the kernel defined functions. Pointers to which is defined in struct file_operations, as below.
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*readv) (struct file *, const struct iovec *, unsigned long,
loff_t *);
ssize_t (*writev) (struct file *, const struct iovec *, unsigned long,
loff_t *);
};
For eg. in my driver I've the following,
struct file_operations fops = {
.read = my_read,
.write = my_write,
};
and I can call these functions from user space application program using the calls read and write.
I also have a function named user_defined in kernel source and my question is how do I call this from user space program?
Well, what you have there is normally referred to as "syscall". I suggest you read into the kernel developer documentation on how to expose a new syscall. On the userspace side, the libc provides you a function syscall, that you can use to call into kernel space. But normally you write a wrapper around it.
However introducing new syscalls should be avoided. The preferred way to call into kernel space is to use sysfs and expose the user space callable functions as files therein.
The quicker & easiest way is to write an ioctl() & call that ioctl() from userspace application. Writing a system call will also do but we should avoid writing a new system call & it is time consuming also. For writing ioctl you can refer following links:
TPLD
LJ
LDD3

C void Pointer on mainframe

I'm currently working on modifying a dump program, but I can't figure out how to properly navigate with a void pointer. Below is the function that I'm working in, and the instruction that I'm trying to execute. I've tried casting mem to a struct, but I'm not sure of the sytnax and I keep getting an error. For the code below, the specific error I'm getting is:
47 | mem = mem->tcbtio
===========> .........a..............................................
*=ERROR===========> a - CCN3122 Expecting pointer to struct or union.
Here is my function:
void hexdump(void *mem, unsigned int len)
{
mem = mem->tcbtio;
...
}
Here are my struct defintions:
struct psa {
char psastuff[540];
struct tcb *psatold;
char filler[4];
struct ascb *psaaold;
};
struct tcb {
struct prb *tcbrb;
char tcbstuff[8];
struct tiot *tcbtio;
};
struct tiot {
char tiocnjob[8];
char tiocpstn[8];
char tiocjstn[8];
};
I need to keep it as a void pointer, as I need to cast it to char and int later on in the function.
It seems as you are expecting to find a tcb struct, starting at the address pointed by mem, but the aim of the code is obscure and the question not clear.
If this is really the case, you can try this:
mem = ((struct tcb *)mem)->tcbtio;
You cannot dereference a void pointer. You can think it this way if you have a void pointer, how will compiler know what type of address it is holding. And by doing mem = mem->tcbtio how much offset it has to make.
Modify your function as:
void hexdump(void *mem, unsigned int len)
{
struct tcbtio *mem2;
mem2 = ((struct tcb*) mem) -> tcbtio;
...
// Use mem2 later
}

can't access a member variable in struct array in struct

I am making a C program, which needs to access a struct array in a struct.
The definition looks like below
struct def_world
{
bool lock;
char tilemap;
def_tile tile[100][100];
struct def_tile
{
bool lock;
char kind;
def_obj * obj;
void * evt;
};
struct def_obj
{
bool lock;
int indexOfTable;
bool frozen;
char x,y;
char kind;
char face;
char * msg;
char * ip;
};
in the main function, I want to access world's tile[3][3]'s obj's face.
I initialize world as
def_world world={0,};
but the following lines make errors
world.tile[3][3].obj=newobj();//newobj() returns def_obj type
world.tile[3][3].obj->face;
any idea how to access obj's face?
Try these lines instead:
world.tile[3][3]->obj=newobj();//newobj() returns def_obj type
world.tile[3][3]->obj.face;
Explanation:
world.tile[3][3] is a def_tile. It's obj field isn't def_obj, but rather def_obj*. Therefore, to get the def_obj that it points to, you should use ->obj.
Inside def_obj, face is just a char, so you would access it with .face.

Resources