LKM Запускает call_usermodehelper с крючка netfilter

#c #linux #module #linux-kernel #netfilter

Вопрос:

Я пытаюсь выполнить команду терминала Linux из модуля ядра Linux в linux 5.10 с помощью call_usermodehelper, который вызывается из крючка сетевого фильтра, но поскольку я знаю, что он работает в контексте softirq, я просто не могу выполнить его в любом случае. Используя «UMH_WAIT_EXEC», я получаю scheduling while atomic: nc/16886/0x00000101 при отправке udp-пакета, который я ищу с помощью фильтра, и если я использую «UMH_WAIT», я получаю пустую ссылку. Код выглядит примерно так:

 static unsigned int hfunc(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{          

        // --snipp--
    
        if (ntohs(udph->dest) == 1337) {
            
             char *argv[4];
             char *envp[4];
             argv[0] = "/bin/bash";
             argv[1] = "-c";
             argv[2] = "/bin/ls";
             argv[3] = NULL;

             envp[0] = "HOME=/";
             envp[1] = "TERM=linux";
             envp[2] = "PATH=/sbin:/usr/sbin:/bin:/usr/bin";
             envp[3] = NULL;

             call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
   }
}
 

Как я могу запустить эту программу из контекста softirq крючка netfilter?

Ответ №1:

Я исправил это с помощью планирования.

 static struct nf_hook_ops *nfho = NULL;

struct work_arg_struct {
    struct work_struct work;
    char *data;
};

static struct work_arg_struct my_work;

void bash_work_handler(struct work_struct *work){

    struct work_arg_struct *work_arg;
    work_arg = container_of(work, struct work_arg_struct, work);
    // --snip--

    call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
    return;
}
static unsigned int hfunc(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
{   
  if (ntohs(udph->dest) == 1337) {
        // setup arguments
        schedule_work(amp;my_work.work);
             
   }
}

--snip--

static int __init module_init(void)
{
 //--snip--
 INIT_WORK(amp;my_work.work, bash_work_handler);
}