我已经向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
标题中搜索但无法找到与用户名有关的任何内容。
任何人都可以帮我解决这个问题吗?
答案 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临界区中执行此操作。我很确定内核会告诉你即使没有发生错误,只要你启用了调试选项。