You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法从可加载内核模块执行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 03:07:58