ruid, euid, suid usage in Linux
ruid, euid, suid usage in Linux
- RUID(Real User ID)
- The actual owner of a process
- It is used in signal transmission. A unprivileged process can signal to the another process when the RUID, EUID is the same as RUID, SUID of the another process
- EUID(Effective User ID)
- Generally, UID and EUID is the same
- EUID is changed by executable file that is configured SetUID authority
- EUID temporarily stores another account’s UID
- The authority of a process is determined according to the UID stored in the EUID
- SUID(Saved set-user-ID)
- SUID is used when a process’s authority is recovered after lowered
- When process’s authority is changed to lower. previous EUID is stored at SUID
- Then, when the lowered authority is recovered to original authority, the SUID is stored at EUID
Note that, the setuid bit has no effect on scripts in Linux-based systems like Ubuntu.
Experiments
First, let’s create one C file named test.c
, as below:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
uid_t ruid, euid, suid;
getresuid(&ruid, &euid, &suid);
printf("EUID: %d, RUID: %d, SUID: %d\n", ruid, euid, suid);
system("cat file-read-only-by-root"); // file-read-only-by-root: -r-------- root root
setreuid(geteuid(), geteuid());
getresuid(&ruid, &euid, &suid);
printf("EUID: %d, RUID: %d, SUID: %d\n", ruid, euid, suid);
system("cat file-read-only-by-root"); // file-read-only-by-root: -r-------- root root
return 0;
}
gcc -o test test.c
sudo chown root:ubuntu test # Here ubuntu is the normal user
Without setting setuid bit, the result of executing test
is as below:
$ ./test
EUID: 1000, RUID: 1000, SUID: 1000
cat: file-read-only-by-root: Permission denied
EUID: 1000, RUID: 1000, SUID: 1000
cat: file-read-only-by-root: Permission denied
Then we setuid for test file and execute it again,
sudo chmod u+s test
$ ./test
EUID: 1000, RUID: 0, SUID: 0
cat: file-read-only-by-root: Permission denied
EUID: 0, RUID: 0, SUID: 0
Testing
From digging deeply, we find out the problem in the first system("cat file-read-only-by-root")
is that Bash Script bans the setuid option. However, if we directly use fopen->fread
or open->read
, it would be fine. The new C file is as follows:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFF_SIZE 100
void read_file() {
FILE *fp;
char buffer[BUFF_SIZE];
/* Open file for both reading and writing */
fp = fopen("file-read-only-by-root", "r");
/* Read and display data */
fread(buffer, BUFF_SIZE - 1, sizeof(char), fp);
printf("%s\n", buffer);
fclose(fp);
}
int main()
{
uid_t ruid, euid, suid;
getresuid(&ruid, &euid, &suid);
printf("EUID: %d, RUID: %d, SUID: %d\n", ruid, euid, suid);
read_file(); // file-read-only-by-root: -r-------- root root
setreuid(geteuid(), geteuid());
getresuid(&ruid, &euid, &suid);
printf("EUID: %d, RUID: %d, SUID: %d\n", ruid, euid, suid);
read_file(); // file-read-only-by-root: -r-------- root root
return 0;
}
Then we add setuid option and test again,
$ ./test
EUID: 1000, RUID: 0, SUID: 0
Testing
EUID: 0, RUID: 0, SUID: 0
Testing
References
[1] https://cysecguide.blogspot.com/2016/10/difference-among-ruid-euid-suid.html