UID from /proc

GitHub

Summary: Using the /proc/self/loginuid file

Marked: Thu May 30 2024

Category: Other

Reviewed: ✅

After discussing the previous approach, I realized that the /proc/self/loginuid would be a viable option to get the UID of the user who ran the program. However, this was initially thought to be as /proc/self/status which contains the UIDs of the process, which looks like this:

Uid:    1000    0    0    0

This should work technically, however, when I run it from the rust program, it seems wrong.

fn get_uid() -> u32 {
    let uid = fs::read_to_string("/proc/self/status").unwrap();
    let uid = uid.lines().find(|line| line.starts_with("Uid:")).unwrap();
    let uid = uid.split_whitespace().nth(1).unwrap();
    uid.parse::<u32>().unwrap()
}

It spits out 0 which is the UID of the root user and when I println! the file contents of the /proc/self/status file, it shows the wrong UIDs.

Uid:    0    0    0    0

This was quite confusing to say the least. However, after digging around a bit more and looking up at some forums, I found out that sudo actually works by forking into a process to the root user and then running the program. So the actual program that is reporting the UIDs is the sudo process and not the actual program. Hence, the UIDs are wrong.

However, it turns out that when such a thing does happen, any type of escalation, be it from sudo or doas, the /proc/self/loginuid file is set to the UID of the user who ran the program.

So I ended up using the following code to get the UID of the user who ran the program:

fn get_uid() -> u32 {
    let uid = fs::read_to_string("/proc/self/loginuid").unwrap();
    uid.parse::<u32>().unwrap()
}

As simple as that, I was able to get the UID of the user who ran the program.

I am testing it more, but it looks quite promising.