繁体   English   中英

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

[英]finding the username in a linux system call

我已经向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标题中搜索但无法找到与用户名有关的任何内容。 谁能帮我解决这个问题?

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

请注意,您的系统调用有点多余; 通过调用/proc/$pid上的stat()或通过读取/proc/$pid/status来获取进程的用户ID已经微不足道了。

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM