Skip to the content.

Linux Modes and Permissions - UID/GID

setUID and setGID bit values make sense only on executable files. It servers no purpose on normal text files.

setUID If setuid bit is set on a (executable) file it causes the program to run as it’s owner, no matter who executes it.

setGID If setgid bit is set on a (executable) file, it causes the program to run as a member of the group that owns it, no matter who executes it.

Note:: To set setuid/setgid bit that program must be group-executable or other-executable.
The Linux kernel ignores the setuid and setgid bits on shell scripts. These bits work only on binary (compiled) executables.

Both the above points are very important. The first one is a requirement for setuid/gid to work. As a matter of fact, setting the setuid/gid are privilege modifications beneficial to anyone other than the owner of the file. The second point means that if a user tries to set it on a regular file or a script (exception are perl scrips), it sets the bit without showing any error message.

eipe@eipe-system:~/share$ ls -l total 12 -rwxr-xr– 1 eipe dev 7 2010-12-12 16:39 lister.sh -rwxr-sr– 1 eipe egroup 3 2010-12-16 20:34 list.sh -rwSrwSr– 1 eipe egroup 22 2010-12-15 00:05 rfile

list.sh is a shell script which is group-executable and uid bit is also set. But still when tom tries,

tom@eipe-system:/home/eipe/share$ ./list.sh bash: ./list.sh: Permission denied

rfile is a text file (which is of course not executable) and it’s uid bit is set.

tom@eipe-system:/home/eipe/share$ cat»rfile bash: rfile: Permission denied

To understand more about permissions let’s look at the concept of user and group. A user or group ID represents the permission level. We could view it from 3 angles.

  1. Perception of the user: The user who has logged into the system. The id of this user is called the real user ID and his primary group is called real group ID.
  2. Perception of the file: A file created by any user associates permissions to it by assigning the permissions for owner (himself), group and others.
  3. Perception of the process: A process which is running has permissions attached to it just like in the case of a file. Commonly known as the effective user ID. Normally, when a user executes a file, the process which results in this execution has the same permissions as those of the user.

When a user executes a file, the process which results in the execution of the file gets the same permissions as those of the user. Within a system, it’s the permission level on the process (effective user ID) that matters. Because that determines what the process is capable of doing. Check out the tmp directory and the passwd and shadow file.

eipe@eipe-system:/$ ls -ld tmp drwxrwxrwt 16 root root 4096 2010-12-21 22:52 tmp eipe@eipe-system:/$ ls -l etc/passwd -rw-r–r– 1 root root 1734 2010-12-16 20:14 etc/passwd eipe@eipe-system:/$ ls -l etc/shadow -rw-r—– 1 root shadow 1379 2010-12-16 20:15 etc/shadow

The listing shows that passwd is readable by all, but shadow is unreadable by group and others. Now how is that a user (other than the root) is able to change his password and other account information without having group/other write permission on both the passwd and shadow file.

Well, this is how Unix solves the problem.

eipe@eipe-system:/$ ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 37100 2010-09-03 15:58 /usr/bin/passwd

This is another passwd file that helps out other users. You can notice a ‘s’ there. This represents the mode set-user-id (SUID). This let’s the process have the privileges of the owner/creator (rather than the current user) during the instance of the program.

Thus when a non privileged user executes passwd, the effective UID of the process is not the user’s, but of root’s – the owner of the program. This SUID privilege is then used by passwd program to edit /etc/shadow.

Let’s create a executable file that prints something useful. :-)

eipe@eipe-system:~$ cat /etc/passwd eipe: x:1000:1000:Eipe,,,:/home/eipe:/bin/bash tom: x:1001:1001:Tom,,,,:/home/tom:/bin/bash

Write the below c program and save it as printid.c

#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>

int main(void)
{
    printf(
        "Real       UID = %d\n"
        "Effective UID = %d\n"
        "Real      GID = %d\n"
        "Effective GID = %d\n",
        getuid(),
        geteuid(),
        getgid(),
        getegid()
    );
    return 0;
}

eipe@eipe-system:~$ ls -l | grep printid -rwxr-xr-x 1 eipe egroup 252 2010-12-22 15:45 printid.c eipe@eipe-system:~$ gcc -o printid printid.c

eipe@eipe-system:~$ ls -l | grep printid -rwxr-xr-x 1 eipe egroup 7249 2010-12-22 16:24 printid -rwxr-xr-x 1 eipe egroup 252 2010-12-22 15:45 printid.c eipe@eipe-system:~$ ./printid Real UID = 1000 Effective UID = 1000 Real GID = 1000 Effective GID = 1000

Now tom logs in. (Better if done on another shell window)

eipe@eipe-system:~$ su tom Password: tom@eipe-system:/home/eipe$ cd /home/eipe tom@eipe-system:/home/eipe$ ./printid Real UID = 1001 Effective UID = 1001 Real GID = 1001 Effective GID = 1001

Now we set the suid bit on the file.

eipe@eipe-system:~$ chmod u+s printid eipe@eipe-system:~$ ls -l | grep printid -rwsr-xr-x 1 eipe egroup 7249 2010-12-22 16:24 printid -rwxr-xr-x 1 eipe egroup 252 2010-12-22 15:45 printid.c

Again tom logs in.

tom@eipe-system:/home/eipe$ ./printid Real UID = 1001 Effective UID = 1000 Real GID = 1001 Effective GID = 1001

Now we conclude that tom is able to run the file (because it’s group or other-executable) and the program now turned into a process, get’s all the privileges of eipe (because it’s uid is set). Most of the cases this poses a lot of security complications and so setuid is advised to be used very carefully)

Now lets change sgid.

eipe@eipe-system:~$ chmod g+s printid eipe@eipe-system:~$ ls -l | grep printid -rwsr-sr-x 1 eipe egroup 7249 2010-12-22 16:24 printid -rwxr-xr-x 1 eipe egroup 252 2010-12-22 15:45 printid.c

Again tom logs in.

tom@eipe-system:/home/eipe$ ./printid Real UID = 1001 Effective UID = 1000 Real GID = 1001 Effective GID = 1000

Similar to SUID, SGID also grants privileges and access rights to the process running the command, but instead of receiving those of the file’s owner it receives those of the file’s group.

When SGID is set on a directory it has a special meaning.

Files created in a directory with SGID set will inherit the same group ownership as the directory itself, not the group of the user who created the file.

We create a directory for our dev group - “devdir”.

eipe@eipe-system:~$ cat /etc/group egroup:x:1000: tgroup:x:1001: dev:x:1002:eipe,tom

eipe@eipe-system:~$ mkdir devdir

Now we change the group of the devdir to dev.

eipe@eipe-system:~$ chgrp dev devdir eipe@eipe-system:~$ ls -l | grep dev drwxr-xr-x 2 eipe dev 4096 2010-12-22 17:51 devdir

We create a file and check it’s group.

eipe@eipe-system:~/devdir$ cat>fileone eipe@eipe-system:~/devdir$ ls -l total 0 -rw-r–r– 1 eipe egroup 0 2010-12-22 17:52 fileone

Now we set the dir’s setgid.

eipe@eipe-system:~$ chmod g+s devdir eipe@eipe-system:~$ ls -l |grep dev drwxr-sr-x 2 eipe dev 4096 2010-12-22 17:52 devdir drwxrwxr-t 2 eipe dev 4096 2010-12-16 20:34 share

We create a second file in devdir.

eipe@eipe-system:~$ cd devdir eipe@eipe-system:~/devdir$ cat>filetwo eipe@eipe-system:~/devdir$ ls -l total 0 -rw-r–r– 1 eipe egroup 0 2010-12-22 17:52 fileone -rw-r–r– 1 eipe dev 0 2010-12-22 17:54 filetwo

Now any file created within devdir get’s it’s default group as dev. If the directory is given group-writable then tom could also cd in and create his files which could be also in dev group.