在linux系统调用中查找用户名

时间:2015-06-30 22:19:40

标签: linux kernel system-calls

我已经向Linux内核添加了一个系统调用,如下所示:

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/list.h>
#include <linux/cred.h>
#include <asm/uaccess.h>

asmlinkage int sys_os_pid_to_uid(int pid, int* puid)
{
    struct task_struct* task;

    rcu_read_lock();

    for_each_process(task)
    {
        if (task->pid == (pid_t) pid)
        {
            copy_to_user(puid, &(task->cred->uid.val), sizeof(task->cred->uid.val));
        }
    }

    rcu_read_unlock();
    return 0;
}

获取进程ID(pid)并确定正在执行它的用户的用户ID(puid)。

现在,我的问题开始了:我想为这个系统调用添加另一个参数,即char *username,它将包含ID为puid的用户的用户名。我在cred.h标题中搜索但无法找到与用户名有关的任何内容。 任何人都可以帮我解决这个问题吗?

4 个答案:

答案 0 :(得分:1)

内核不知道用户名;它只处理用户ID。将用户名解析为用户ID(反之亦然)完全由用户空间中的font-size: 0 libc函数系列(getpwent()getpwuid()等)处理。

请注意,您的系统调用有点多余;通过getpwnam()上的stat()或阅读/proc/$pid来获取流程的用户ID已经很简单了。

答案 1 :(得分:1)

你没有找到它的原因是因为没有一个:task_struct,并且内核一般不会保留有关给定用户对应的用户名的内存信息ID。这是完全没必要的,会增加接口和代码的混乱,并且会消耗内存而没有任何额外的好处:关于用户的所有内容都用数字用户ID表示和存储。比较简单,节省了记忆。

你不应该/不能在系统调用中执行此操作。

我建议您编写一个包装器用户空间函数来调用您的系统调用,然后调用getpwuid(3)getpwuid_r(3)将用户ID转换为用户名。请注意,这将在用户空间中完成,而不是在内核空间中完成。

答案 2 :(得分:1)

我很确定用户名的唯一概念是在用户空间中,基于/ etc / passwd(通常,但可能是其他来源,如NIS或LDAP)。如果您更改/ etc / passwd中现有条目的用户名,则用户立即成为该新用户名,就像更改/ etc / hosts中的主机名条目一样,会更改本地计算机的IP地址的有效主机名&#39; s透视。它只是一个查找/名称解析。存储对象都将包含用户ID,而不是用户名。

您可能希望跟踪命令&#34; getent&#34;和&#34; id&#34;等等。另请参阅lib调用getpwuid()。通常,如果不总是,syscalls(内核空间)处理uids。

答案 3 :(得分:0)

但这有什么意义呢?你刚刚玩内核吗? uid可以在/ proc中找到。正如其他人所指出的,必须在用户空间中解析用户名。

我忍不住问你从哪里接受这个循环,因为它显然非常低效。在这里迭代所有进程是有理由的,并且通过读取也必须找到它的系统调用的来源,可以很容易地找到获得给定pid的task_struct的方法。杀(2)

最后,我还要注意有问题的代码是不正确的。 copy_to_user可能导致页面错误,您无法在rcu临界区中执行此操作。我很确定内核会告诉你即使没有发生错误,只要你启用了调试选项。