Joseph Muia
GitHub / LinkedIn

Fun with Device Files, TTYs, and File Permissions

/dev/

I was reading a bit about /dev/ and device files.

There are a bunch of different devices and you can ls -lh /dev/ to show some of them. Here are a few on my laptop:

vagrant@ubuntu-xenial:~$ ls -lh /dev/
total 0
crw------- 1 root root     10, 235 May  1 12:18 autofs
drwxr-xr-x 2 root root         260 May  1 12:17 block
drwxr-xr-x 2 root root          80 May  1 12:17 bsg
crw-rw---- 1 root disk     10, 237 May  1 12:18 loop-control
brw-rw---- 1 root disk      7,   0 May  1 12:18 loop0
crw-rw-rw- 1 root root      1,   3 May  1 12:18 null
crw------- 1 root root     10,   1 May  1 12:18 psaux
crw-rw-rw- 1 root tty       5,   2 May  1 13:08 ptmx
drwxr-xr-x 2 root root           0 May  1 12:17 pts
brw-rw---- 1 root disk      8,   0 May  1 12:18 sda
lrwxrwxrwx 1 root root          15 May  1 12:17 stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root          15 May  1 12:17 stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root          15 May  1 12:17 stdout -> /proc/self/fd/1
crw-rw-rw- 1 root tty       5,   0 May  1 12:18 tty
crw-rw---- 1 root dialout   4,  65 May  1 12:18 ttyS1
crw-rw-rw- 1 root root      1,   9 May  1 12:18 urandom
crw-rw---- 1 root tty       7,   0 May  1 12:18 vcs
crw-rw-rw- 1 root root      1,   5 May  1 12:18 zero

You might recognize some of them, especially stdin, stdout, urandom, and null. Here is an overview of some of the devices found in /dev/.

Another thing I want to point out is the first character of each line, the file type. You may be familiar with - for regular files, d for directories, and l for symbolic links. In this list you will also see c for character devices and b for block devices. Everything is a file in UNIX, even devices. There are other file types, as well, like p for named pipes and s for sockets.

TTYs

I’m going to focus on the c character devices. In particular, you’ll notice that pts, tty, and ttyS1 (all types of terminals) are character devices.

Cool! So, if each terminal is just a file, if I want to send a message to another terminal can I just write to it?

vagrant@ubuntu-xenial:~$ tty
/dev/pts/0
vagrant@ubuntu-xenial:~$ echo "Hi /dev/pts/1!" > /dev/pts/1
vagrant@ubuntu-xenial:~$ tty
/dev/pts/1
vagrant@ubuntu-xenial:~$ Hi /dev/pts/1!

Awesome. I can even send the bell character \a to make the other terminal ring.

vagrant@ubuntu-xenial:~$ tty
/dev/pts/1
vagrant@ubuntu-xenial:~$ echo -e 'Hey /dev/pts/0! \a' > /dev/pts/0
vagrant@ubuntu-xenial:~$ tty
/dev/pts/0
vagrant@ubuntu-xenial:~$ Hey /dev/pts/0! <ding!>

File permissions

Fun. But I’m just sending myself messages (since both terminals are the vagrant user).

I added another user tnargav which is using pts/1:

vagrant@ubuntu-xenial:~$ who
vagrant  pts/0        May  2 02:11 (10.0.2.2)
tnargav  pts/1        May  2 02:14 (10.0.2.2)

Let’s try it out:

vagrant@ubuntu-xenial:~$ echo "Hi /dev/pts/1!" > /dev/pts/1
-bash: /dev/pts/1: Permission denied

Boo. Okay, that makes sense though, I shouldn’t be able to just send another user messages.

What if I update the file permissions?

tnargav@ubuntu-xenial:~$ chmod a+w /dev/pts/1
vagrant@ubuntu-xenial:~$ echo "Hi tnargav!" > /dev/pts/1
tnargav@ubuntu-xenial:~$ Hi tnargav!

Neat, no magic here, just standard UNIX file permissions.

write(1)

I think most systems have write(1) which allows you to send messages to another user. A quick peek at the source code and it seems like it checks group permissions.


Published on May 02 2018