Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending a struct from kernel to userland via netlink

I'm trying to send a struct from a LKM to userland, based on this answer: Netlink Sockets in C using the 3.X linux kernel

The code from the answer itself is perfectly compilable, but when I try to send a struct instead of a char *, I get segfaults in userland.

This is what I change:

netlinkKernel.c

I add:

typedef struct test{
    int a;
    char *b;
} s_test;

and replace

char *msg = "Hello from kernel";

---

msg_size = strlen(msg);

---

strncpy(nlmsg_data(nlh),msg,msg_size);

with

s_test x;
x.a = 42;
x.b = "The answer";

---

msg_size(sizeof(x));

---

memcpy(nlmsg_data(nlh), &x, msg_size);

netlinkUser.c

I add the same struct and replace

printf("Received message payload: %s\n", (char *)NLMSG_DATA(nlh));

with

s_test *x = (s_test *)NLMSG_DATA(nlh);
printf("Received message payload: %d - %s\n", x->a, x->b);

Where is the problem?

like image 400
alexandernst Avatar asked Sep 22 '13 14:09

alexandernst


1 Answers

Here's your problem: your structure contains a pointer to other memory in kernel space (char *b). However, what you are sending to user space is only the pointer in the structure and not that other bit of memory ("The answer"). In addition, even if you were to also send the additional memory, b still is a pointer to kernel virtual addresses.

Your best bet is to make b a char array and copy the data into b.

Pointers inside data sent between processes or between a process and the kernel are generally very problematic. system calls that use structures of pointers, e. g. man 2 recvmsg, do not just send the pointers verbatim between user space and kernel, instead, the kernel does separate access to userspace to resolve each pointer.

like image 135
DoxyLover Avatar answered Oct 10 '22 02:10

DoxyLover