I am trying to execute a linux terminal command from a linux kernel module in linux 5.10 by using call_usermodehelper, which is called from within a netfilter hook, but since from what i know it's running in softirq context i just can't seem to be able to execute it either way. Using 'UMH_WAIT_EXEC' i get the scheduling while atomic: nc/16886/0x00000101
upon sending the udp packet that i am watching for with the filter and if i use 'UMH_NO_WAIT' i get a null reference. The code looks something like this:
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);
}
}
How can i run that program from the softirq context of the netfilter hook?
I fixed this by using scheduling.
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(&my_work.work);
}
}
--snip--
static int __init module_init(void)
{
//--snip--
INIT_WORK(&my_work.work, bash_work_handler);
}