Linux – UID/GID of a process from, when not from the process’s cred pointer

linux-kernelprivilegesprocessprocess-managementvirtual machine

Circumstances

I'm having a lecture on "Cloud Security" at University, and am currently doing a project on virtual machine introspection.

Goal of my exercise was to escalate privileges of some process to root privileges, which I accomplished by "borrowing" the pointer to struct cred from init, using volatility and libvmi. Basically just like some rootkits do, but from one VM to another. I can prove the effect of this method by escalating privileges of some process, which repeatedly tries to write to protected memory. Just like that:

#!/bin/bash
while true
do
    echo 1 >> /etc/test
    id
    sleep 2
done

This leads to the following output (at the time, when privileges change):

# last time permission is denied
./test.sh: line 3: /etc/test: Permission denied
uid=1000(tester) gid=1000(tester)groups=1000(tester),24(cdrom),
25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),
111(scanner),115(bluetooth)

# tada, magic

# now I'm root
uid=0(root) gid=0(root) groups=0(root)

The Question

So I can prove some process (bash in above example) has root privileges now. But when I look at the process using ps u or directly via /proc/$PID, UID and GID don't seem to have changed.

Output of ps -A u | grep 2368:

Before:

# ...
tester    2368  0.0  0.9  23556  4552 pts/2    S+   22:24   0:00 -bash

After:

# ...
tester    2368  0.0  0.9  23556  4552 pts/2    S+   22:24   0:00 -bash

Nothing has changed here.

Also /proc/$PID/status hasn't changed:

~# cat /proc/2368/status | grep Uid
Uid:    1000    1000    1000    1000
~# cat /proc/2368/status | grep Gid
Gid:    1000    1000    1000    1000

So can you explain, why they don't change there, and where that information came from, when they are not taken from the process's struct cred, which has obviously been changed.

Best Answer

Tasks do not have a struct cred. They have two struct cred's:

 * A task has two security pointers.  task->real_cred points to the objective
 * context that defines that task's actual details.  The objective part of this
 * context is used whenever that task is acted upon.
 *
 * task->cred points to the subjective context that defines the details of how
 * that task is going to act upon another object.  This may be overridden
 * temporarily to point to another security context, but normally points to the
 * same context as task->real_cred.

I checked which one /proc shows you, but you can probably guess :-P.

(See fs/proc/, using https://elixir.bootlin.com . The procfs "status" file is defined in fs/proc/base.c.)

Related Question