Отправка структуры из ядра в пользовательскую область через netlink
Я пытаюсь отправить структуру из LKM в пользовательскую область, основываясь на этом ответе: сокеты Netlink в C с использованием ядра Linux 3.X
Код из самого ответа отлично компилируется, но когда я пытаюсь отправить struct
вместо char *
Я получаю segfaults в userland.
Это то, что я меняю:
netlinkKernel.c
Я добавить:
typedef struct test{
int a;
char *b;
} s_test;
и заменить
char *msg = "Hello from kernel";
---
msg_size = strlen(msg);
---
strncpy(nlmsg_data(nlh),msg,msg_size);
с
s_test x;
x.a = 42;
x.b = "The answer";
---
msg_size(sizeof(x));
---
memcpy(nlmsg_data(nlh), &x, msg_size);
netlinkUser.c
Я добавляю ту же структуру и заменяю
printf("Received message payload: %s\n", (char *)NLMSG_DATA(nlh));
с
s_test *x = (s_test *)NLMSG_DATA(nlh);
printf("Received message payload: %d - %s\n", x->a, x->b);
В чем проблема?
1 ответ
Вот ваша проблема: ваша структура содержит указатель на другую память в пространстве ядра (char *b
). Однако то, что вы отправляете в пространство пользователя, это только указатель в структуре, а не тот другой бит памяти ("The answer"
). Кроме того, даже если вы должны были также отправить дополнительную память, b
по-прежнему является указателем на виртуальные адреса ядра.
Лучше всего сделать массив ба чар и скопировать данные в b.
Указатели внутри данных, передаваемых между процессами или между процессом и ядром, как правило, очень проблематичны. системные вызовы, использующие структуры указателей, например man 2 recvmsg
, не просто передавайте дословно указатели между пользовательским пространством и ядром, вместо этого ядро делает отдельный доступ к пользовательскому пространству для разрешения каждого указателя.