无法从可加载内核模块执行Bash脚本求助
内核模块调用
call_usermodehelper执行Bash脚本失败排查 问题场景
通过内核模块的call_usermodehelper函数调用Bash脚本时,脚本无法启动;模块编译无报错,dmesg也未显示异常。此前调用仅含chmod命令的简单脚本完全正常。
内核模块代码
#include <linux/module.h> /* 所有模块必备 */ #include <linux/kernel.h> /* KERN_INFO所需 */ #include <linux/init.h> /* 宏定义所需 */ #include <linux/kmod.h> #include <linux/moduleparam.h> MODULE_LICENSE( "GPL" ); static char *mystring = "blah"; module_param(mystring, charp, 0000); MODULE_PARM_DESC(mystring, "一个字符串参数"); static int __init hello_start(void) { printk(KERN_INFO "加载rooted模块...\n"); pr_info("mystring参数值:%s\n", mystring); char* argv[] = {"/bin/bash", "home/grim-reaper/kernel/FocusModule/focusmyman.sh", NULL}; static char* envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL }; call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); return 0; } static void __exit hello_end(void){ printk(KERN_INFO "退出.\n"); char* argv[] = {"/bin/bash", "home/grim-reaper/script-remove.sh", NULL}; static char* envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL }; call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); } module_init(hello_start); module_exit(hello_end);
对应Bash脚本
#!/bin/bash if [ -f ~/kernel/FocusModule/focus.txt ]; then echo "文件存在且为常规文件" else touch focus.txt fi while true; do active_window=$(xdotool getwindowfocus getwindowname) echo "$active_window" >> ~/kernel/FocusModule/focus.txt sleep 5 done
问题排查与解决方案
1. 路径错误
- 问题:内核环境无默认工作目录,脚本路径
home/grim-reaper/...缺少开头的/,属于相对路径无法被正确解析;同时脚本中的~/会因内核设置的HOME=/解析为/kernel/...,而非预期的用户家目录路径。 - 修复:
- 内核模块中脚本路径改为绝对路径:
"/home/grim-reaper/kernel/FocusModule/focusmyman.sh" - 脚本中所有
~/替换为绝对路径/home/grim-reaper/
- 内核模块中脚本路径改为绝对路径:
2. X11环境变量缺失
- 问题:
xdotool依赖X服务器,内核启动的进程默认没有DISPLAY和XAUTHORITY环境变量,无法访问用户的X会话。 - 修复:在
envp数组中添加X相关变量:static char* envp[] = { "HOME=/home/grim-reaper", "TERM=linux", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", "DISPLAY=:0", // 根据实际X显示号调整,通常为:0 "XAUTHORITY=/home/grim-reaper/.Xauthority", NULL };
3. 进程执行模式问题
- 问题:使用
UMH_WAIT_EXEC会让内核等待脚本执行完成,但脚本是无限循环,会导致模块加载过程卡住,后续逻辑无法执行。 - 修复:
- 如果不需要等待脚本结束,改用
UMH_NO_WAIT,让脚本后台运行:call_usermodehelper(argv[0], argv, envp, UMH_NO_WAIT); - 或者在脚本中添加后台执行标记,比如修改调用参数为
"/bin/bash", "-c", "/path/to/script.sh &", NULL
- 如果不需要等待脚本结束,改用
4. 权限与用户上下文问题
- 问题:内核模块以root身份执行脚本,但
xdotool需要访问普通用户的X会话,root默认没有权限访问用户的X资源。 - 修复:通过
su切换到普通用户身份执行脚本,修改内核模块中的argv:char* argv[] = { "/bin/su", "grim-reaper", "-c", "/home/grim-reaper/kernel/FocusModule/focusmyman.sh", NULL };
修改后的代码示例
修改后的内核模块(加载部分)
static int __init hello_start(void) { printk(KERN_INFO "加载rooted模块...\n"); pr_info("mystring参数值:%s\n", mystring); char* argv[] = { "/bin/su", "grim-reaper", "-c", "/home/grim-reaper/kernel/FocusModule/focusmyman.sh", NULL }; static char* envp[] = { "HOME=/home/grim-reaper", "TERM=linux", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", "DISPLAY=:0", "XAUTHORITY=/home/grim-reaper/.Xauthority", NULL }; call_usermodehelper(argv[0], argv, envp, UMH_NO_WAIT); return 0; }
修改后的Bash脚本
#!/bin/bash FOCUS_DIR="/home/grim-reaper/kernel/FocusModule" FOCUS_FILE="$FOCUS_DIR/focus.txt" if [ -f "$FOCUS_FILE" ]; then echo "文件存在且为常规文件" >> "$FOCUS_FILE" else mkdir -p "$FOCUS_DIR" touch "$FOCUS_FILE" fi while true; do active_window=$(xdotool getwindowfocus getwindowname 2>> "$FOCUS_FILE") echo "$(date +'%Y-%m-%d %H:%M:%S') - $active_window" >> "$FOCUS_FILE" sleep 5 done
内容的提问来源于stack exchange,提问作者Aniket Raj
相关产品推荐
相关产品推荐

