Linux/Unix Permissions

Share
Linux/UNIX-style permissions can be intimidating to newcomers, particularly if you’re seeing a bunch of chmod commands using only numeric permissions values. Many users simply start using chmod 777 as a catchall, to ensure that they have proper permissions, but this defeats the system security permissions are meant to achieve. But understanding, and properly employing, permissions isn’t all that hard. Let’s start with some basic concepts.

  • UID/GID:

If you log into a *nix box, and run ls -l at a prompt, you’ll probably see something like this:

total 196
drwxr-xr-x 34 jacob jacob  4096 Apr  2 16:30 Maildir
-rw-r--r--  1 jacob jacob     7 Jan 13 13:04 foo
-rw-------  1 jacob jacob 67046 Oct 11 17:39 sent
[...]

Now, to live your life day-to-day, you don’t need to understand that much of what you see here. These files belong to me (user jacob), Maildir is a directory (note the d at the beginning of its line) and they have file dates. Now let’s try ls -ln:

total 196
drwxr-xr-x 34 1000 1000  4096 Apr  2 16:30 Maildir
-rw-r--r--  1 1000 1000     7 Jan 13 13:04 foo
-rw-------  1 1000 1000 67046 Oct 11 17:39 sent
[...]

Hm. Owned by 1000. That’s different. Well, we’ve encountered our first concept, UID and GID. The U and G stand for “user” and “group”, respectively, and ID is… identifier. So, within the system, user 1000 is jacob, for everything that uses standard *nix accounts. The command id will give us more info:

uid=1000(jacob) gid=1000(jacob) groups=1000(jacob),4(adm),33(www-data)

So, I’m user 1000, as we determined. My primary group (the group which files created by me get by default) is a group named jacob as well. On most modern systems, a group is created to match each user at the time of the user’s creation, but not always. On my MacBook Pro, for example, id returns:

uid=501(jacob) gid=20(staff) groups=20(staff),403(com.apple.access_ssh),204(_developer), 100(_lpoperator),98(_lpadmin),81(_appserveradm),80(admin),79(_appserverusr),61(localaccounts),12(everyone),401(com.apple.access_screensharing),402(com.apple.sharepoint.group.1)

So, I (and other users added to this laptop), are added to a staff group, rather than an individual group. This can be important, since, if you make your personal files group-readable (or writable, or executable), others on the box in this group will have access to them.

Going back to my Linux box:

uid=1000(jacob) gid=1000(jacob) groups=1000(jacob),4(adm),33(www-data)

We see that I’m also members of the adm and www-data groups. The groups used for various tasks often vary widely between distributions, but on this (Debian) server, my user has access to most logs under /var/log/ (adm) and is able to work in the /var/www/ directory used by Apache, the webserver (www-data).

Those of you who feel you have a sufficient grasp of the nature of UID/GID can skip to the next section. For those interested in how those ideas are managed, we can find them in our /etc/passwd and /etc/group files:

$ grep jacob /etc/passwd
jacob:x:1000:1000:Jacob,,,:/home/jacob:/bin/bash

$ grep -E 1000\|4\|33 /etc/group -w
adm:x:4:jacob
www-data:x:33:jacob
jacob:x:1000:

man 5 passwd and man 5 group will tell you about those files, but they contain the information that defines the users, groups, and the relationships between them for the system.

  • Standard permissions:

Alright, back to our home directory:

total 196
drwxr-xr-x 34 jacob jacob  4096 Apr  2 18:32 Maildir
-rw-r--r--  1 jacob jacob     7 Jan 13 13:04 foo
-rw-------  1 jacob jacob 67046 Oct 11 17:39 sent

From left to right, we have: permissions, link counts, user, group, size, date, and file name. The last three are fairly understandable, and the second has to do with the nature of *nix filesystems (interesting, but not relevant here. Ask me if you really want to know.). We’ve already explored what the user and group do and mean, so on to the real reason you’re here.

drwxr-xr-x
-rw-r--r--
-rw-------

Our understanding will be best helped if we put some spaces in here, so:

d	rwx	r-x	r-x
-	rw-	r--	r--
-	rw-	---	---

Much better. Again, from left to right, we have file type, user permissions, group permissions, and other (non-owner/non-group) permissions. The file type here shows we have either a directory (d) or regular file. Those are far and away the two most common you’ll encounter, but:

$ ls -l /dev/ | sed 's/^\(.\).*/\1/' | sort -u
b
c
d
l
p
s

In order, these are block special, character special, directory, symbolic link, fifo (named pipe), and socket. In-depth dissection of these is well-beyond the scope of a permissions discussion, but, these types are integral to the functioning of the system.

So, returning to the remaining 3 columns of permission data:

rwx	r-x	r-x
rw-	r--	r--
rw-	---	---

We have user permissions, group permissions, and other permissions (the permission you have if you are neither the owner of the file, nor in the group to which the file belongs). The permission letters correspond to read, write, and execute. Read and write permissions work as you might expect, with one small exception. Directories require you to have execute permission to act on their contents.

$ mkdir bar
$ touch bar/foo
$ chmod -x bar
$ ls -ld bar
drw-r--r-- 2 jacob jacob 4096 Apr  2 18:51 bar
$ ls -l bar
ls: cannot access bar/foo: Permission denied
total 0
-????????? ? ? ? ?            ? foo

The interesting thing to note is that I can access the listing of bar (I can see foo in there), but I cannot read any information about foo since I don’t have execute permissions.

Execute permissions are also used to determine which files can be treated as executable files. This includes scripts run with an interpreter:

$ cat >>script.sh <<EOF
> #!/bin/sh
>
> echo "Run successfully"
> EOF
$ ./script.sh
-bash: ./script.sh: Permission denied
$ sh script.sh
Run successfully
$ chmod +x script.sh
Run successfully
$ ./script.sh

Since sh is able to read the file, it can perform the steps listed in it, but in order to have the system call the interpreter itself (treating the file as an executable), it must have execute permissions.

  • Symbolic permission strings:

So, how do we change permissions on a file? Well, the tool we’ll be using, chmod, is discussed at the bottom of this page. But let’s talk about how to define the permissions we want.

According to the man page:

The format of a symbolic mode is [ugoa...][[+-=][perms...]...], where perms is either zero or more letters from the set rwxXst, or a single letter from the set ugo.  Multiple symbolic modes can be given, separated by commas.

Ok. That sounds a little complicated. ugoa represents user, group, other, and all users, respectively. Omitting that portion of the format is the same as giving the value a. Otherwise, if we think about our 3-column layout, u is the first column, g is the second, o is the third, and a is all 3. You can supply more than one, so, for example, to remove write permissions from group and other, you would use chmod go-w file.

The second term, [+-=], does what you would probably expect. + adds the relevant permission, without affecting the others, - deletes it, and = sets the entire column to whatever permissions you’ve select (effectively removing all permissions, then just adding the ones you’ve defined).

The third term, perms is either zero or more letters from the set rwxXst, or a single letter from the set ugo. The first half of that disjunction means you can set (or clear) any of read, write, execute, eXecute if directory, setuid/setguid, and sticky. The last two will be covered in the special permissions section down at the bottom, as their behavior is slightly odd. So, assuming I wanted to make all the files in my home directory rw-------, and the directories rwx------, I would use: chmod u=rwX,go-rwx * to make those changes.

The second half of the or-statement above tells you how to copy permissions. Say I had just run the command above, and decided I really wanted rw-rw----/rwxrwx--- on everything, I could then copy all the user permissions to the group field like this: chmod g=u *.

  • Octal permissions:

Now for the arcane stuff. Because programmers enjoy sticking by the old way of doing things, you will often see permissions modified as octal strings (the 777/775/666/664/etc permissions you might have seen). This isn’t so bad, if you think in binary. Note:

7 = 4 + 2 + 1 = 111b
6 = 4 + 2     = 110b
5 = 4 +     1 = 101b
4 = 4         = 100b
3 =     2 + 1 = 011b
2 =     2     = 010b
1 =         1 = 001b
0 =           = 000b

So, an octal numeral represents 3 bits. And we have 3 permissions we need to manage: read, write, execute. Well, that’s certainly convenient.

Octal Binary Permissions
7 111 rwx
6 110 rw-
5 101 r-x
4 100 r--
3 011 -wx
2 010 -w-
1 001 --x
0 000 ---

Some of you might be looking towards the bottom of that table, and wondering what on earth you would ever do with -wx, -w-, or --x permissions. And rightly so. It shows you’ve been paying attention, and I commend you for it. You will usually only find the numbers 7, 6, 5, 4, 0 used in chmod commands, since 3, 2, and 1 don’t make a whole lot of sense.

So, we can convert a command block to octal, and back, so what do we have:

total 196
drwxr-xr-x 34 jacob jacob  4096 Apr  2 19:02 Maildir
-rw-r--r--  1 jacob jacob     7 Jan 13 13:04 foo
-rw-------  1 jacob jacob 67046 Oct 11 17:39 sent

Ok. My Maildir directory has rwxr-xr-x permissions. That means I have full rights over it, anyone in my jacob group (hopefully no one else!) has read and execute permission on it, allowing them to browse it and, likely, its subdirectories, but not make changes, and all other users on the system have read and execute as well. Hmm. That seems suboptimal, but this is a very limited-access system, so I’m ok with this, for now. This would appear to translate to 755 permissions.

My foo file can be both read and written by me, and read by both members of my group, and everyone else. This equates to 644 permissions.

My sent file has the most restrictive permissions of these three. I can read and write it, but neither other members of my group, nor anyone else can manipulate this file at all. (Note that the root user ignores the requirement for permissions to modify the system. They have carte blanche to do what they like.) These settings translate into 600 permissions.

Note, that unlike symbolic permissions specifications, you must set the entire permission string, exactly as you want it. You are unable to modify or conditionally set only a portion of permissions. Not for the faint of heart.

So, how do we use the permissions? Well, impatient reader, that will be covered in the next section, called:

  • chown/chgrp/chmod:

Modifying permissions is easy; just be careful when mucking about with them as superuser. Many things are what they are for a very good reason, and tracking down a permissions problem isn’t always trivial. That being said, here’s the tools you need to take permissions into your own hands:

  • chown:

Predictably, chown lets you change the owner of a file. You probably won’t be able to do this, usually, unless you’re root, or you’re making a file has a UID not currently on the system:

$ sudo touch bar
$ ls -l bar
-rw-r--r-- 1 root root 0 Apr  2 19:23 bar
$ sudo chown jacob bar
$ ls -l bar
-rw-r--r-- 1 jacob root 0 Apr  2 19:23 bar

(sudo allow you to run commands as another user. In this case, I’m running them as root.)

chown will also let you change group. If you did chown jacob:www-data bar, then bar’s GID would be set to that of www-data. If you did chown jacob: bar, then bar’s GID would be jacob’s primary group (jacob in this case). man chown for more info.

  • chgrp:

chgrp is simpler. It just changes the group. chgrp jacob bar. man chgrp for more.

  • chmod:

This is probably why you’re here. Well, you’ve been extremely patient to wade through this particularly lengthy discourse on the nature of permissions. Stay tuned next week for…

No, that’s a joke. chmod is the primary tool for changing permissions. It is powerful. The main syntax is chmod {permission specifier} file. And, as you know by now, we can define permissions any number of ways.

  • Special permissions:

Above, I mentioned some special permissions. They are the setuid and setguid bits, and the sticky bit. In symbolic notation, you would prefix an additional hex digit, before the standard 3, that represents these bits. The right column below is in addition to the normal bits:

7 --s--s--t
6 --s--s---
5 --s-----t
4 --s------
3 -----s--t
2 -----s---
1 --------t

setuid and setgid make your perform execute functions, including modification of directory entries, as though your uid/gid was the uid/gid of the file, respectively. If you set them on a directory, then setuid will make files you create within the directory be owned by whomever owns the directory, not necessarily you. If you use setgid, then the group of new files will be the same as the directory.

If set on executables, then, when they are run, it will be as though it had been run by the owner/group of the file. This can allow users additional privileges, so be careful about using this. For example, if you were to do the following: chown root /bin/bash; chmod u+s /bin/bash, then any user who ran /bin/bash would have root privileges.

The sticky bit, on modern systems, will only allow file owners to remove/rename files if they are the owner of the file or directory containing it. So, you could have a file with 1777 permissions, and, while other people could write to it, they couldn’t remove or rename it. This is most often used on shared filesystems or directories, such a /tmp.

So, there you have it. Linux/UNIX-style permissions. That wasn’t so bad, now was it?

Share

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>