Setuid, setgid, and sticky bit explained
Linux has 3 types of access to files and directories: reading, writing, and execution permissions.
Reading permission grants users access to read files while writing permissions allow users to edit or remove files, execution permissions allow them to run files.
These permissions can be applied with differences for the file owner, users belonging to the file’s group, and all users (not the owner nor group users).
The bit setuid, setgid and sticky allow you to implement additional restrictions or privileges without changing the permissions table.
Regular Linux permissions were deeply explained at Linux Permissions Explained, a recommended reading before continuing with this tutorial. The current tutorial focuses on flags setuid, setgid, and sticky to “inherit” the file owner or group permissions to users with restricted access and prevent non-privileged users from removing files they don’t own.
Understanding the bit SETUID:
The following screenshot shows the content of the directory LinuxHintSetUID and the file permissions:
As you can see, all files belong to the user and group linuxhint; the file tutorial.txt has read and writing permissions for the owner, reading permissions for users of the same group, and no permissions at all for other users.
If a user other than the file owner, who doesn’t belong to the group, tries to read the file, he will fail because of the lack of permissions for all users or other users.
The following screenshot shows the user torvalds unsuccessfully tried to access the tutorial.txt file.
Now let’s suppose the user linuxhint wants to keep tutorial.txt restricted while allowing users to read it only through a specific application. This can be achieved using the flag setuid.
In other words, the user torvalds won’t be able to read the file tutorial.txt. Still, he will run the reader-owned by the user linuxhint, inheriting his permissions during the execution process. This is possible if the owner adds the setuid bit to the file’s permission table, instructing the file to be always processed as by the owner and with owner privileges even if executed by another user like torvalds.
NOTE: You can use the C code below to reproduce the following examples. Compile running cc code.c -o reader
Reader application code:
#include
int main() {
char c[1000];
FILE *fptr;
if ((fptr = fopen(“tutorial.txt”, “r”)) == NULL) {
printf(“Error! File cannot be opened.”);
// Program exits if the file pointer returns NULL.
exit(1);
}
sleep(5);
// reads text until newline is encountered
fscanf(fptr, “%[^n]”, c);
printf(“Data from the file:n%s”, c);
fclose(fptr);
return 0;
}
Before proceeding, let’s see what happens if the user torvalds, who has permissions to run the application reader, executes the reader before linuxhint applies the setuid flag.
As you can see, torvalds managed to run the reader, a C program designed to read tutorial.txt with the following permissions table, but the reader failed to grant him access to tutorial.txt because torvalds hasn’t permissions to read it.
Reader permissions table is shown below:
–rwxr–xr–x 1 linuxhint linuxhint reader
Now let’s see what happens when linuxhint adds the setuid flag to the reader permissions table by running:
If you run ls -l , you’ll notice the permissions table changed, and the program name appears in red, alerting you about possible risk. The new permissions table looks like this:
The new S I highlighted in blue shows the file has the setuid flag; every time the file is executed, the process will belong to the file owner independently of who executes the program. Since the owner will execute the file before the system, the execution will inherit the owner’s permissions. That’s why now, after linuxhint added the setuid flag, the user torvalds must be able to read tutorial.txt through the reader.
NOTE: Torvalds can run the reader because all users have execution rights; if linuxhint removes execution permissions for all users, torvalds won’t be able to run it.
The setuid flag defines the file as by the owner, and the user who executes it will inherit owner permissions, but setuid does not define who can execute the file.
As you can see, torvalds managed to read “Data from the file:
You shouldn’t be able to read this”.
If while torvalds runs the script, I run the following ps command, you will see a difference between the real user (RUSER) and the effective user (USER) of the process 4332 (reader).
ps –ao pid,uid,ruser,user,rgroup,egroup,command
The screenshot above shows despite the real user running reader is torvalds or another user, the file is always processed as by linuxhint, with his permissions, and that’s why torvalds can see the file only through the application.
The setuid flag can be removed by running:
Understanding the bit SETGID:
Setgid is similar to setuid, but instead of changing the user who processes the file, it replaces the effective group for the filegroup, granting access according to the group permissions.
If the bit setgid is applied to a directory, all files created within the directory will belong to the directory’s group.
The following screenshot shows torvalds has no permission to read tutorial.txt, only the owner and the group can read the file. Even with a reader, Torvalds can’t read the file because he has no permissions, and no setuid bit was added.
Let’s see what happens after linuxhint adds setgid:
-rwxr-sr-x: As you can see in the permission table, now the S is on the group column, which means when the program is executed, it will always run with its own group privileges.
So let’s see what happens when torvalds tries to access tutorial.txt again using reader:
Torvalds managed to read tutorial.txt; let’s see what the ps command shows on the reader’s process:
ps –ao pid,uid,ruser,user,rgroup,egroup,command
As you can see in process 6713, the user running the file is torvalds, but the Effective group is linuxhint, the file’s group; that’s why torvalds could access tutorial.txt with reader’s group permissions.
The setgid bit can be removed by running:
Understanding the Sticky Bit:
Another permission bit is the sticky bit, which, if defined, prevents non-privileged users from removing content. If the Sticky bit is applied, only the owner or the root can remove files, but not all users, even if they have writing permissions.
The following example shows the user linuxhint adds the sticky bit to the current directory:
drwxr-xr-t: As you can see now, there is a T at the end of the permissions table of the LinuxHintSetUID directory. This means users can’t remove files they don’t own within the directory, even if they have writing permissions.
The following screenshot shows permissions for a file called “something” under the directory LinuxHintSetUID with the special sticky bit:
As you can see, despite having writing permissions both on the directory and on the file, torvalds can’t remove the file something:
I hope you found this tutorial on setuid, setgid, and sticky bit useful. Keep following LinuxHint for more Linux tips and tutorials.