添加一个简单的系统调用到Linux内核

问题描述 投票:1回答:2

我刚刚向linux内核添加了一个系统调用。它只需要一个char*参数名称并打印Hello名称。

这是系统调用代码:

asmlinkage long sys_hello(char* name) { printk("Hello %s \n", name); return 0; }

这是应该运行系统调用以进行测试的代码:

int main() 
{
    long int amma  = syscall(318,"Winston");
    printf("Returned %lu \n" ,amma);  
    return 0; 
}

但是当我运行它时,我得到一个被杀死的输出。有关解决此问题的任何想法提前致谢。

linux ubuntu linux-kernel system-calls kill-process
2个回答
4
投票

您的代码在内核上下文中执行,而包含数据的缓冲区来自用户空间。如果需要处理来自用户空间的某些字符串,请使用strncpy_from_user()函数将其复制到内核内存中。如果您不遵循该方案并且只是尝试直接访问数据,则会导致内存访问冲突。

一个更好的解决方案(基于您的代码)看起来有点像这样:

asmlinkage long sys_hello(char* name) {
    long  nb_symbols;
    char *name_internal;
    long  i;

    /*
     * Estimate the buffer length sufficient
     * to accommodate the string
     */
    for (i = 1; ; ++i) {
        nb_symbols = strnlen_user(name, i);
        if (nb_symbols <= 0)
            return -EFAULT;

        if (nb_symbols < i)
            break;
    }

    /* Allocate the storage */
    name_internal = kmalloc(nb_symbols + 1, GFP_KERNEL);
    if (name_internal == NULL)
        return -ENOMEM;

    if (strncpy_from_user(name_internal, name, nb_symbols + 1) !=
        nb_symbols) {
        kfree(name_internal);
        return -EFAULT;
    }

    printk("The 'name' is '%s'\n", name_internal);
    kfree(name_internal);

    return 0;
}

但请注意,这样的循环(在我的示例中为一个循环)可能不是缓冲区长度估计的可接受解决方案。理想情况下,您可以删除它并使用固定长度的静态char数组来使用strncpy_from_user()


0
投票

这是如何不编写内核代码的经典示例之一 - 它尝试直接访问用户空间缓冲区,这是一个极端禁忌。

如果你遇到了崩溃,那可能就是SMAP。很难说,因为你没有提供日志。

所以真正的问题是:你从哪里采取上述措施?你在做大学课程吗?

© www.soinside.com 2019 - 2024. All rights reserved.