Episode 007 – Chmod and Unix Permissions

Anyone using a Linux based system for some period of time will eventually have to deal with permissions. From setting a script executable to fixing group access to a directory, understanding the basics of Linux file permissions is a must have skill, and very simple to learn.

Linux and other Unix based systems have three simple permissions: Read (r), Write (w), and Execute (x). These permissions are granted on three levels: Owning Users (u), Owning Groups (g), and Others (o). You can easily see the permissions of any given file or directory by issuing:

ls -l file/directory_name

The output would be something like this:

-rw-r–r–   1   dann   users   59   Mar   20   10:19   error.log

The first column “-rw-r–r–” provides the permissions for the file. This error log has the following permissions:

  • read and write permissions for the owner (dann)
  • read permissions for the owning group (users)
  • read permissions for everyone else

Now if you look closely at this list of permissions you will see that there is an extra “-” before the three permission groupings. That first column indicates if the object is a special type of file like a directory or a character device.

File permissions on directories are pretty straight forward. Read access grants a user the ability to “read” the file. They can open the file and look at the contents of the file using a command like “cat” or opening the file in a text editor. The latter, though, does not grant write permissions. Write permission is an exclusive write and grants the ability to edit a file or even delete a file. Finally, execute permissions grants the ability to execute the file, to run it as a program or script. This later concept is important. If you create a shell script and attempt to run it like so:

./myshellscript.sh

It will more than likely fail claiming: “Permissions denied.” You must first grant executable permission to run this script (or execute it with a shell like sh or bash).

Directory permissions operate a bit differently than file permissions. The read permission grants the ability for a user to list files in a directory.  If that is the only permission you have in that directory you can list the files in that directory but you cannot view the contents of those files even if you have the proper permissions to do so. The execute permission on a directory provides the rights to view a file and to change directory (cd) into that directory. If you have execute right to a directory and not read, you can cd into the directory, you can access files by name in that directory, but you cannot attempt to list all files or access files by wildcards. Thus:

ls -l * or even ls -l

Will result in the “Permission denied” error if you do not have read access to that directory.

The write permission grants you the ability to alter or delete contents of that directory. Even if the contents on the directory do not grant you explicit write ability, you can delete the contents of that directory if you have the write permission to that directory. You will be asked if you want to “remove write-protected ….” but if you say yes, the file or object will be deleted.

There are three other permissions that are available:

  • Sticky bit
  • Set UID
  • Set GID

Sticky bit is a special permission is primarily for directory use and restricts the deletion of a file to allowable only by the owner of the file. This is commonly used for a /tmp directory where you want global read, write, and executable access but you do not want others to be able to delete files you own under that directory. If the sticky bit is set you will see it listed in place of the executable permission for the others directory permissions:

ls -ld /tmp

Reveals the following permissions for the /tmp directory:

rwxrwxrwt

The SetUID and SetGID bits operate similarly. SetUID runs or executes a file as the owners privileges. SetGID does the same thing but executes a file as the owning groups privilege level. For example, if you have a shell script owned by root that has the sticky bit set and you have executable permissions to that file, the script will run as root, not as your user when you execute it.

If the SetGID bit is set on a directory then files and subdirectories created under that parent directory will inherit the same group ownership as the parent directory. This mechanism exists to facilitate a shared directory where users that are in the same group can potentially read, write, and execute files in that directory without having to worry about changing permissions or ownership. On some systems setting the SetUID bit on a directory will cause files and directories created under the parent to retain the owning user as the parent directory. Note that in both intances, these ownerships will only be set for newly created files and directories after the SetGID or SetUID bits have been set. Existing files would have to be changed manually with the chmod command.

Understanding file permissions is only half the battle. Knowing how to change file permission is the next step. Changing file permission can be accomplished using the chmod command which stands for “change file mode bits.” The chmod command, at the very least, requires two parameters: The permissions to be set and what to set those permissions on:

chmod u=rwx,go=rx error.log

Executing this command will set the following permissions:

  • Owning User = Read, write, execute
  • Owning Group = Read, execute
  • All Others = Read, execute

There are two different ways to represent permissions: Symbolic and octal. The previous example is using symbolic representation which uses “r” to represent “read,” “w” to represent “write,” “x” to represent “execute,” “t” to represent “sticky bit,” and “s” to represent “setuid or setgid bit.” These permission are specified against “ugoa” whiich is:

  • u = owning user
  • g = owning group
  • o = all others
  • a = everyone

You can use chmod to set the permission for the owning user, owning group, and all others or specifically for one more more of the three sets. Furthermore you can explicitly set the permission or add and subtract permissions using “+/-”:

chmod u+w *.log
chmod u+x,go-x *.sh
chmod g+w *.txt

The first example adds the write permission for all files that end in “.log” in the current directory. It changes no other permission for the owner, owning group or all others. The second example adds the execute permission for the owning user if she does not have it, subtracts the executable permission for the owning group and all others if they have it for all files ending in “.sh” in the current directory. Finally the third example adds the write permission to all files ending in “.txt” in the current directory to the owning group.

The octal method for setting the permissions makes use of the octal value for each permission:

  • r = 4 or 0
  • w = 2 or 0
  • x = 1 or 0
  • s = 4 (for user) or 0 (or unspecified)
  • s = 2 (for group) or 0 (or unspecified)
  • t = 1 or 0 (or unspecified)

The summation of each permission, values 0-7, represent the permission for each of the “ugo.” The following examples show how to represent the permission values in octal format:

rwx = 7 (r+w+x = 4+2+1)
r-x =  5 (r+0+x = 4+0+1)
rw- = 6 (r+w+0 = 4+2+)
r– = 4 (r+0+0 = 4+0+0)

When specifying in octal you must explicitly set the values for all three otherwise you results apply to the right most group and work towards the left:

chmod 7 file = ——rwx on file
chmod 27 file = —-w-rwx on file

Be aware of this as it is always good form to specify the octal value for all three, “ugo.”

Specifying the special permissions: SetUID, SetGID, and sticky bit are options in octal format but when setting them they represent the left most column and add like the permission for ugo. To set the sticky bit on a directory you would issue:

chmod 1777 /var/www/groupsave

To set the SetUID on a script:

chmod 4755 somescript.sh

Finally, to add SetGID bit on a script:

chmod 2755 somescript.sh

The 4th left most bit, while reserves for special permissions, is optional to set. If you are not specifying any special permission you can leave this bit blank or set “0″ in the 4th column:

chmod 0755 *.log

The chmod command has a few flags that can be passed. Probably one of the most frequently used flags is “-r” or “–recursive.” This flag will set the permissions for all files and directories and recurse setting the permission as such in sub-directories.

For safety purposes there is the “–preserve-root” which fails to operate recursively on  ”/” or the root directory.  So issuing:

chmod -R –preserve-root *

While at the “/” or root directory will fail. This is not set by default so be careful. The options –no-preserve-root is default.

The -v or –verbose option will output the value for every file processed and report whether or not the permissions were changed and what they were changed to. By default only errors are reported and these can mostly be suppressed with the -f, –silet, or –quiet flag. Or you can take the middle road with the -c or –changes flag that reports only files that have permissions set/changed.

Finally there is the –reference=FILE which sets the permissions based upon the permissions of the FILE specified.  Thus if a file called happy has permissions 777 and you execute:

chmod –reference=~/happy *.log

All the files ending in “.log” in the current directory will have the same permissions as the file happy in your home directory, which in this case is 777 (rwxrwxrwx).

Understanding file permissions and how to manipulate them is key part of administering any Linux file system.

Bibliography:

  • man chmod
  • info file permissions

 

If the video is not clear enough view it off the YouTube website and select size 2 or full screen.  Or download the video in Ogg Theora format:

Thank you very much.

 

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>