【问题标题】:copy data from linux kernel space to user space将数据从linux内核空间复制到用户空间
【发布时间】:2017-11-07 13:31:34
【问题描述】:

我正在添加一个内核函数来修改进程指定pid的niceprio值。

代码如下:

SYSCALL_DEFINE5(mysetnice, pid_t, pid, int, flag, int, nicevalue, void __user *, prio, void __user *, nice)
{
    if (pid < 0 || (flag != 1 && flag != 0)) {
        return EFAULT;
    }
    if (nice == NULL || prio == NULL) {
        return EFAULT;
    }
    struct task_struct *p;
    for_each_process(p) {
        if (p->pid == pid) {
            if (flag == 1) {
                set_user_nice(p, nicevalue);
                printk("change nice=%d of pid=%d\n", nicevalue, pid);
            }
            printk("pid:%d,current nice:%d, prio:%d\n",pid,task_nice(p),task_prio(p));
            copy_to_user(prio,(const void*)task_prio(p),sizeof(int));
            copy_to_user(nice,(const void*)task_nice(p),sizeof(int));
            return 0;
        }
    }
    return EFAULT;

}

在用户范围内,我写了一个这样的测试函数:

int main()
{
    int pid = 0;
    int flag = 0;
    int nicevalue = 0;
    int prio = 0;
    int nice = 0;
    int ret;

    printf("please input the params: pid, flag, nicevalue\n");
    while(~scanf("%d %d %d", &pid, &flag, &nicevalue))
    {
        ret = syscall(__NR_mysyscall, pid, flag, nicevalue, (void *)&prio, (void *)&nice);
        if (ret != 0)
        {
            printf("syscall error! error code:%d\n", ret);
            return 0;
        }
        printf("pid:%d, flag:%d, nicevalue:%d, prio:%d, nice:%d\n", pid, flag, nicevalue, prio + 100, nice);
    }

    return 0;
}

但我发现我无法获得nice 的值,而prio 始终是100。那么如何将数据从内核范围复制到用户范围呢?

【问题讨论】:

    标签: c linux kernel


    【解决方案1】:

    代码质量一般都很差。

    SYSCALL_DEFINE5(mysetnice, pid_t, pid, int, flag, int, nicevalue, void __user *, prio, void __user *, nice)
    {
        if (pid < 0 || (flag != 1 && flag != 0)) {
            return EFAULT;
    

    错误代码是否定的。 IE。这应该是 -EFAULT,这可以在其他系统调用中看到。对于这种特殊情况,EFAULT 本身是一个极差的选择。通常 invalid 参数会导致 EINVAL。

        }
        if (nice == NULL || prio == NULL) {
            return EFAULT;
        }
        struct task_struct *p;
        for_each_process(p) {
    

    你是从哪里弄来的?

    有 0 个理由走流程列表。寻找翻译 pid -> task_struct * 的方法留作练习。提示:有些系统调用将 pid 作为参数。

    由于锁定不足(或者更确切地说:缺少)锁定,遍历本身是不正确的。

            if (p->pid == pid) {
                if (flag == 1) {
                    set_user_nice(p, nicevalue);
                    printk("change nice=%d of pid=%d\n", nicevalue, pid);
                }
                printk("pid:%d,current nice:%d, prio:%d\n",pid,task_nice(p),task_prio(p));
    

    printk 中缺少日志级别。检查任何现有的 printk 以了解我的意思。

                copy_to_user(prio,(const void*)task_prio(p),sizeof(int));
    

    不仅没有错误检查,而且第二个参数显然不正确。

                copy_to_user(nice,(const void*)task_nice(p),sizeof(int));
                return 0;
            }
        }
        return EFAULT;
    

    这个应该是 ESRCH。

    }
    

    【讨论】:

      【解决方案2】:

      问题是,您必须提供源值的地址,而不是值本身。尝试类似:

      int val = task_prio(p);
      copy_to_user(prio,(const void*)&val,sizeof(int));
      

      nice 也一样,那么它应该可以按预期工作。

      【讨论】:

        猜你喜欢
        • 2016-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多