setuid and setgid setuid is a flag that allows an application to temporarily change the permissions of the user running the process by setting the effective user id to the program's owner user id. setgid is a flag that allows an application to temporarily change the permissions of the group running the process by setting the effective group id to the program owner's group id. When a binary executable file has been given the setuid attribute, normal users on the system can execute this file and gain the privileges of the user who owns the file (commonly root) within the created process. When root privileges have been gained within the process, the application can then perform tasks on the system that regular users normally would be restricted from doing. The invoking user will be prohibited by the system from altering the new process in any way, such as by using ptrace, LD_LIBRARY_PATH or sending signals to it (signals from the terminal will still be accepted, however). Due to the increased likelihood of security flaws, many operating systems ignore the setuid attribute when applied to executable shell scripts. The presence of setuid executables justifies the fact that the chroot system call is not available to non-root users on Unix. The setuid and setgid bits are normally set with the command chmod by setting the high-order octal to 4 or 2 (or 6 to set both). `chmod 6711` will set the setuid and setgid bit (6) make the file read/write/executable for the owner (7) and executable by the group and others (11). All chmod flags are octal, and the least significant bit of the high-order octal is used for a special mode known as the sticky bit. Most implementations of the chmod command also support symbolic arguments to set these bits. This is shown in the demonstration below as the 'chmod ug+s' command. The setuid and setgid flags, when set on a directory, have an entirely different meaning. Setting the setgid permission on a directory (chmod g+s) causes new files and subdirectories created within it to inherit its group, rather than the primary group of the user who created the file (the owner is never affected, only the group). Newly created subdirectories inherit the setgid bit. Note that setting the setgid permission on a directory only affects the group of new files and subdirectories created after the setgid bit is set, and is not applied to existing entities. Setting the setgid bit on existing subdirectories must be done manually, with a command such as the following: find /path/to/directory -type d -print0 | xargs -0 chmod g+s or [root@foo]# find /path/to/directory -type d -exec chmod g+s {} \; The setuid permission set on a directory is ignored on UNIX and GNU/Linux systems. FreeBSD can be configured to interpret it similarly to setgid, namely, to force all files and sub-directories to be owned by the top directory owner. To disable a setuid util: chmod a-s /path/to/util To disable a setgid util: chmod a-g /path/to/util -------------------------------------------------------------------------------- The demonstration C program below simply obtains and reveals the real and effective user and group id currently assigned to the process. The commands shown first compile the process as user `bob` and subsequently use `chmod` to establish the setuid ad setgid bits. The `su` command, itself a client of the setuid feature, is then used to assume the id of `alice`. The effectiveness of the `chmod` command is checked with 'ls -l', and finally the demonstration program is run, revealing the expected identity change, consistent with the /etc/passwd file. Note that the demonstration program listed below will silently fail to change the effective UID if run on a volume mounted with the 'nosuid' option. [bob@foo]$ cat /etc/passwd alice:x:1007:1007::/home/alice:/bin/bash bob:x:1008:1008::/home/bob:/bin/bash [bob@foo]$ cat printid.c #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main(void) { printf("Real UID\t= %d\n", getuid()); printf("Effective UID\t= %d\n", geteuid()); printf("Real GID\t= %d\n", getgid()); printf("Effective GID\t= %d\n", getegid()); return EXIT_SUCCESS; } [bob@foo]$ gcc -Wall printid.c -o printid [bob@foo]$ chmod ug+s printid [bob@foo]$ su alice [alice@foo]$ ls -l -rwsr-sr-x 1 bob bob 6944 2007-11-06 10:22 printid [alice@foo]$ ./printid Real UID = 1007 Effective UID = 1008 Real GID = 1007 Effective GID = 1008 -------------------------------------------------------------------------------- The Sticky Bit The sticky bit was introduced in the Fifth Edition of Unix in 1974 for use with pure executable files. When set, it instructed the operating system to retain the text segment of the program in swap space after the process exited. This speeded subsequent executions by allowing the kernel to make a single operation of moving the program from swap to real memory. Thus, frequently-used programs like editors would load notably faster. One notable problem with "stickied" programs was replacing the executable (for instance, during patching); to do so required removing the sticky bit from the executable, executing the program and exiting to flush the cache, replacing the binary executable, and then restoring the sticky bit. Currently, this behavior is only operative in HP-UX. Solaris appears to have abandoned this in 2005. The 4.4-Lite release of BSD retained the old sticky bit behavior but it has been subsequently dropped from OpenBSD (as of release 3.7) and FreeBSD (as of release 2.2.1); it remains in NetBSD. No version of Linux has ever supported the traditional behavior. The most common use of the sticky bit today is on directories, where, when set, items inside the directory can be renamed or deleted only by the item's owner, the directory's owner, or the superuser; without the sticky bit set, any user with write and execute permissions for the directory can rename or delete contained files, regardless of owner. Typically this is set on the /tmp directory to prevent ordinary users from deleting or moving other users' files. This feature was introduced in 4.3BSD in 1986 and today it is found in most modern Unix systems. The sticky bit can be set using the chmod command and can be set using its octal mode 1000 or by its symbol t (s is already used by the setuid bit). For example, to add the bit on the directory /usr/local/tmp, one would type chmod +t /usr/local/tmp. Or, to make sure that directory has standard tmp permissions, one could also type chmod 1777 /usr/local/tmp. In Unix symbolic file system permission notation, the sticky bit is represented by the letter t in the final character-place. For instance, on Solaris 8, the /tmp directory, which by default has the sticky-bit set, shows up as: $ ls -ld /tmp drwxrwxrwt 4 root sys 485 Nov 10 06:01 /tmp If the sticky-bit is set on a file or directory without the execution bit set for the others category (non-user-owner and non-group-owner), it is indicated with a capital T: # ls -l test -rw-r--r-- 1 root other 0 Nov 10 12:57 test # chmod +t test; ls -l test -rw-r--r-T 1 root other 0 Nov 10 12:57 test