简体   繁体   English

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

[英]finding the username in a linux system call

I have added a system call to Linux kernel that looks like this: 我已经向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;
}

It gets a process ID ( pid ) and determines the user ID ( puid ) of the user who is executing it. 它获取进程ID( pid )并确定正在执行它的用户的用户ID( puid )。

Now, my problem begins: I want to add another argument to this system call, that is, char *username , which will contain the username of the user whose ID is puid . 现在,我的问题开始了:我想为这个系统调用添加另一个参数,即char *username ,它将包含ID为puid的用户的用户名。 I searched in the cred.h header but was unable to find anything concerned with the username. 我在cred.h标题中搜索但无法找到与用户名有关的任何内容。 Can anyone help me solve this? 谁能帮我解决这个问题?

The kernel is not aware of usernames; 内核不知道用户名; it only deals with user IDs. 它只处理用户ID。 Resolving usernames to user IDs and vice versa is handled entirely in userspace by the getpwent() family of libc functions ( getpwuid() , getpwnam() , etc). 将用户名解析为用户ID(反之亦然getpwent()由libc函数的getpwent()系列( getpwuid()getpwnam()等)完全在用户空间中处理。

Note that your system call is somewhat redundant; 请注意,您的系统调用有点多余; it's already trivial to get the user ID of a process by calling stat() on /proc/$pid , or by reading /proc/$pid/status . 通过调用/proc/$pid上的stat()或通过读取/proc/$pid/status来获取进程的用户ID已经微不足道了。

The reason you didn't find it is because there isn't one: task_struct , and the kernel in general, does not keep in-memory information about the username corresponding to a given user ID. 您没有找到它的原因是因为没有一个: task_struct ,并且内核通常不会保留有关与给定用户ID相对应的用户名的内存中信息。 That is utterly unnecessary, would add clutter to the interfaces and code, and would consume memory without any added benefit: everything regarding users is represented and stored with numeric user ids. 这是完全没必要的,会增加接口和代码的混乱,并且会消耗内存而没有任何额外的好处:关于用户的所有内容都用数字用户ID表示和存储。 Comparison is easy and memory is saved. 比较简单,节省了内存。

You shouldn't / can't do this in a syscall. 你不应该/不能在系统调用中执行此操作。

I suggest you write a wrapper user-space function that invokes your syscall and then calls getpwuid(3) or getpwuid_r(3) to convert from the user ID to the username. 我建议你编写一个包装器用户空间函数来调用你的系统调用,然后调用getpwuid(3)getpwuid_r(3)将用户ID转换为用户名。 Note that this is to be done in user-space, not in kernel space. 请注意,这将在用户空间中完成,而不是在内核空间中完成。

I'm pretty sure the only concept of username is in userspace, based on the /etc/passwd (usually, but could be other sources like NIS or LDAP). 我很确定用户名空间的唯一概念是基于/ etc / passwd(通常,但可能是其他来源,如NIS或LDAP)。 If you change the username of an existing entry in /etc/passwd, the user immediately becomes that new username, much like changing a hostname entry in /etc/hosts changes the effective hostname of an IP address from your local computer's perspective. 如果更改/ etc / passwd中现有条目的用户名,则用户立即成为该新用户名,就像更改/ etc / hosts中的主机名条目一样,从本地计算机的角度更改IP地址的有效主机名。 Its just a lookup / name resolution. 它只是一个查找/名称解析。 Storage objects will all contain the user ID, not the username. 存储对象都将包含用户ID,而不是用户名。

You may want to trace the commands "getent" and "id" among others. 您可能希望跟踪命令“getent”和“id”等。 Also look at lib call getpwuid(). 另请参阅lib调用getpwuid()。 Usually, if not always, syscalls (kernel space) handle uids. 通常,如果不是总是,syscalls(内核空间)处理uids。

But what is the point of this? 但这有什么意义呢? Are you just playing with the kernel? 你刚刚玩内核吗? uid can be found in /proc. uid可以在/ proc中找到。 As was noted by others, username has to be resolved in userspace. 正如其他人所指出的,必须在用户空间中解析用户名。

I cannot help but ask where did you take this loop from, as it is obviously terribly inefficient. 我不禁要问你从哪里接受这个循环,因为它显然非常低效。 There is 0 reason to iterate over all processes here, and the way to obtain task_struct for a given pid can be easily found by reading sources of a syscall which also has to find it - eg kill(2) 在这里迭代所有进程是有理由的,并且通过读取也必须找到它的系统调用的源代码,可以很容易地找到获取给定pid的task_struct的方法 - 例如kill(2)

Finally, I also have to note the code in question is obvoiusly incorrect. 最后,我还要注意有问题的代码是不正确的。 copy_to_user can result in a page fault which you cannot take while in rcu critical section. copy_to_user可能导致页面错误,您无法在rcu临界区中执行此操作。 I'm pretty sure the kernel would have told you that even without the fault occuring if only you had debug options enabled. 我很确定内核会告诉你即使没有发生错误,只要你启用了调试选项。

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

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