Let's test the access controls in the example running processes as user bookuser. Most processes run in the context of the user that invoked them (excluding setuid and getuid programs), so any command we invoke should inherit our user's permissions. We can view it by issuing:
My user, bookuser, is USER bookuser, GROUP bookuser and SUPGRP sudo and fuse.
To test for read access, we can use the cat command, which opens the file and prints its content to stdout:
We can introspect the syscalls executed by running the strace command and viewing the output:
The output can be quite verbose, so I am only showing the relevant parts. We can see that cat invoked the open syscall and obtained the file descriptor 3. We can use that descriptor to find other accesses via other syscalls. Later we will see a read occurring on file descriptor 3, which returns 365, the number of bytes read. If we didn't have permission to read from hello.txt, the open would fail, and we would never have a valid file descriptor for the file. We would additionally see the failure in the strace output.
Now that read permission is verified, let's try write. One simple way to do this is to write a simple program that writes something to the existing file. In this case, we will write the line my new text\n (refer to write.c.)
Compile the program using the following command:
Now run using the newly compiled program:
On verification, you will see:
As you can see, the write succeeded and returned 12, the number of bytes written to hello.txt. No errors were reported, so the permissions seem in check so far.
Now let's attempt to execute hello.txt and see what happens. We are expecting to see an error. Let's execute it like a normal command:
This is exactly what we expected, but let's invoke it with strace to gain a deeper understanding of what failed:
The execve system call, which launches processes, failed with EACCESS. This is just the sort of thing one would hope for when no execute permission is given. The Linux access controls worked as expected!
Let's test the access controls in the context of another user. First, we'll create a new user called testuser using the adduser command:
Verify the USER, GROUP, and SUPGRP of testuser:
Since the USER and GROUP do not match any of the permissions on a.S, all accesses will be subject to the OTHERS permissions checks, which if you recall, is read only (0664).
Start by temporarily working as testuser:
As you can see, we are still in bookuser's home directory, but the current user has been changed to testuser.
We will start by testing read with the cat command:
Similar to the earlier example, testuser can read the data just fine, as expected.
Now let's move on to write. The expectation is that this will fail without appropriate access:
As expected, the syscall operation failed. When we attempt to execute hello.txt as testuser, this should fail as well:
Now we need to test the group access permissions. We can do this by adding a supplementary group to testuser. To do this, we need to exit to bookuser, who has permissions to execute the sudo command:
Now let's check the groups of testuser:
As a result of the previous usermod command testuser now belongs to two groups: testuser and bookuser. That means when testuser accesses a file or other object (such as a socket) with the group bookuser, the GROUP permissions, rather than OTHERS, will apply to it. In the context of hello.txt, testuser can now read from and write to the file, but not execute it.
Switch to testuser by executing the following command:
Test read by executing the following command:
As before, testuser is able to read the file. The only difference is that it can now read the file through the access permissions of OTHERS and GROUP.
Test write by executing the following command:
This time, testuser was able to write the file as well, instead of failing with the EACCESS permission error shown before.
Attempting to execute the file should still fail:
These concepts are the foundation of Linux access control permission bits, users and groups.