[英]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.