Finding username in linux system call

I added a system call to the Linux kernel that looks like this:

#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 the process id ( pid

) and defines the user id ( puid

) of the user who is executing it.

Now my problem starts: I want to add another argument to this system call, that is char *username

, one that will contain the username of the user ID puid

. I searched in the title cred.h

but couldn't find anything related to username. Can anyone help me solve this problem?

+3


source to share


4 answers


The reason you didn't find it is because it doesn't exist: task_struct

and the kernel as a whole does not store information in memory about the username corresponding to the given user ID. This is completely optional, adds clutter to interfaces and code, and consumes memory without any additional benefit: everything about users is represented and stored with numeric user IDs. The comparison is easy and the memory is saved.

You shouldn't / can't do this in syscall.



I suggest you write a user-space-wrapper function that calls your syscall and then calls getpwuid(3)

or getpwuid_r(3)

to convert from user id to username. Note that this must be done in user space, not kernel space.

+1


source


The kernel does not know usernames; it only deals with user IDs. Resolution of usernames to user IDs and vice versa is handled entirely in user space by the getpwent()

libc ( getpwuid()

, getpwnam()

etc.) family of functions .



Note that your system call is somewhat redundant; it is already trivial to get the user id of a process by calling stat()

on /proc/$pid

, or by reading /proc/$pid/status

.

+1


source


I'm pretty sure the only concept of username in userspace is based on / etc / passwd (this can usually be from other sources like NIS or LDAP). If you change the username of an existing entry in the / etc / passwd file, the user will immediately become such a new username, like changing the hostname entry in / etc / hosts, changing the effective hostname of the IP address from the perspective of your local machine. It's just search / name resolution. All storage objects will contain a user ID, not a username.

You can track the commands "getent" and "id" among others. Also take a look at lib call getpwuid (). Usually, if not always, syscalls (kernel space) handles uids.

+1


source


But what is the point of this? Are you just playing with the core? uid can be found in / proc. As noted by others, the username must be resolved in user space.

I can't help but ask where you got this loop from, as it is clearly horribly inefficient. There are 0 reasons to iterate over all processes here, and the way to get the task_struct for a given pid can be easily found by reading the syscall sources, which should also find it - for example kill (2)

Finally, I should also point out that the code in question is not correct. copy_to_user can result in a page error that you cannot execute while in a critical section of rcu. I'm sure the kernel will tell you that even without error if you only had debug options.

0


source







All Articles