Проблема с сокетом netlink: зависание ядра

#linux #linux-kernel #netlink

#linux #linux-ядро #netlink

Вопрос:

Я пытаюсь использовать сокеты netlink для обмена сообщениями между пользовательским пространством и пространством ядра … я отправляю сообщение из пользовательского пространства в пространство ядра, и все работает хорошо, но когда я пытаюсь ответить из пространства ядра, система зависает. В частности, я планирую с помощью рабочей очереди функцию, которая создает сообщение и отправляет в пространство пользователя с помощью функции netlink_unicast…вот некоторый код ядра:

 void wq_func(struct work_queue *wq)
{
  struct sk_buff *resp = alloc_skb(NLMSG_LENGTH(100), GFP_KERNEL);
  if (!resp)
  {
     printk(KERN_INFO "alloc_skb failed");
     return;
  }

  struct nlmsghdr *nlh = (struct nlmsghdr *)skb_put(resp, NLMSG_LENGTH(100));
  memset(nlh, 0, NLMSG_LENGTH(100));
  nlh->nlmsg_len = NLMSG_LENGTH(100);
  nlh->nlmsg_pid = 0;
  nlh->nlmsg_flags = 0;
  strcpy(NLMSG_DATA(nlh), "From kernel: Yes i'm here!");
  NETLINK_CB(resp).pid = 0;
  NETLINK_CB(resp).dst_group = 0;

  printk(KERN_INFO "Trying to send a netlink message to pid %d", pid);
  int err = netlink_unicast(s, resp, pid, MSG_DONTWAIT);
  if (err < 0)
    printk(KERN_ALERT "Error sending message to user-space");
  kfree_skb(resp);
}
DECLARE_WORK(wq, wq_func);

static void input_nl(struct sk_buff *buff)
{
  printk(KERN_INFO "Received message socket NETLINK_TEST");
  if (buff == NULL)
  {
    printk(KERN_ALERT "NULL sk_buff!");
    return;
  }
  struct nlmsghdr *nlh = (struct nlmsghdr *)buff->data;
  printk(KERN_INFO "Received netlink message from pid %d: %s", nlh->nlmsg_pid,       NLMSG_DATA(nlh));

  pid = nlh->nlmsg_pid;

  schedule_work(amp;wq);
}

int __init knl_init()
{
  printk(KERN_INFO "knl module loaded");

  s = netlink_kernel_create(amp;init_net, NETLINK_TEST, 0, input_nl, NULL, THIS_MODULE);

  if (s == NULL)
    return -1;
  return 0;
}
  

Если я пытаюсь прокомментировать вызов netlink_unicast, ядро не зависает. Из пользовательского пространства я могу правильно отправить сообщение. Я помню, что тот же код хорошо работал в прошлом, и я очень удивлен этой странной ошибкой сейчас.

Есть идеи?

Спасибо вам всем!


Я попытался удалить вызов kfree_skb после вызова netlink_unicast и все works…so почему система зависает при этом вызове? Где я должен освободить выделенный sk_buff?

Комментарии:

1. в какой-то момент netlink стал внутренне синхронным, попробуйте без schedule_work() вызова.

Ответ №1:

netlink_unicast() получает право собственности на skb и освобождает его самостоятельно.

Комментарии:

1. А, ладно … это была недостающая концепция! Спасибо caf!

Ответ №2:

После вызова netlink_unicast вы не можете освободить struct sk_buff