exploring the users "as whom" processes operate
Note: please follow the instructions carefully in
terms of where you run the commands from. Running them from terminal windows
within a GUI interface for example rather than the virtual terminals indicated
won't produce the target result of the exercise.
The exercise to perform
Linux provides several independent "virtual terminals." You can switch your monitor back and forth between them with the special keystroke combinations <ctrl>-<alt>-<Fn> where Fn is a function key and n represents the vitrual terminal's number. When you boot, you are in virtual terminal 1 at first. However, press ctrl-alt-F5 and you will be in virtual terminal 5 for example. If you want to go back to virtual terminal 1 and resume whatever you were doing there, ctrl-alt-F1 puts you back. Different users can log in and operate independently within their own terminals this way. We will employ several virtual terminals in this exercise.
Log in on virtual terminal 1 as root. Create new user accounts "tom" "dick"
and "harry" having "password" as their password. Create tom
for example, by:
useradd tom
passwd tom
Use ftp from a server (designated by the instructor) to get:
fork9a.c
ids.c
Examine the source code for both. fork9a.c is a super-simple shell that identifies the user as whom it is running, asks the user for a command, then fork/exec's it (i.e., causes it to run). ids.c shows how to get the real and effective user id's for a process and print them.
Compile these, for example:
gcc fork9a.c -o dshell
gcc ids.c -o ids
Make sure the resulting binaries are world-executable, for example:
chmod o+x dshell ids
and copy them into /usr/local/bin, where they will be accessible to other users:
cp dshell /usr/local/bin
cp ids /usr/local/bin
Go to virtual terminal 2 (ctrl-alt-F2); login there as user tom. A running shell will result. This shell process will have a PID (process id number) and an associated user. Use the ps command to reveal information about tom's shell:
ps -ef
From the output 1) verify tom is the user for this process, 2) verify it is associated with terminal 2 (tty2), 3) identify and write down its PID.
Go to virtual terminal 3 (ctrl-alt-F3); login there as user dick. Another running shell will result. Using the ps command to reveal information about dick's shell:
ps -ef --header
From the output 1) verify dick is the user for this process, 2) verify it is associated with terminal 3 (tty3), 3) identify and write down its PID (2nd column). Note that tom's earlier bash process is still visible, along with dick's.
Construct a process family tree. Have dick run:
ps -ef --header | less
You will see (scroll to the bottom of the output) 3 processes by dick and 1 by tom. For each, write its PID and the command/program of which it is an instance. Note that not only the PID but also the PPID (parent process' s id) is shown. Using that, find the parent processes for each of tom's and dick's processes, and then the parent process for each of those. Trace the process genaeology back up to the common, first process. What is that "original" process in linux called? Write a process genaeology family tree:
Each box represents a process. In each box write 1) the PID, 2) the command that the process is running, 3) the user as whom it's doing so. When finished, look at a similar representation of the same information by having root run the following command in his terminal 1:
pstree -pu
Study the pstree information in terminal 1 and the ps information in terminal 3 side by-side. Understand the mechanism they depict of successive process launches and consequent parent-child relationships, user identities that inhere to each process, and inheritance of those identities by default. Note the exceptions to that default, where a child does not have the same UID as its parent. When finished quit out of "less" (lowercase q keystroke).
Let's briefly explore process UID inheritance:
Become tom, by going to virtual terminal 2 (ctrl-alt-F2) where tom is running
a shell. There, run dshell. From within dshell, run /usr/local/bin/ids.
Become dick, by going to virtual terminal 3 (ctrl-alt-F3) where dick is
running a shell. There, run dshell. From within dshell, run /usr/local/bin/ids.
When "dshell" shows you its process user ids (real and effective), where did they come from? That is, if they're 505, why 505? When "ids" shows you its process user ids, where did it get them (same question)? The process user ids of a process derive from where?
Now, below, let's look are departures and variations to process UID inheritance.
Using the su command
As dick, terminate dshell (ctrl-C). Rerun it, but this time run it through the "su" command which lets you determine a user id for the process different from your own. Run dshell as follows:
su tom -c dshell
(you will have to give tom's password). Again run /usr/local/bin/ids from within dshell and pay attention to the user ids shown. Now terminate dshell running by dick but as tom, and run it by dick as root:
su -c dshell
If you omit a user specification, "root" is the user as whom the command will be run by default. Again run /usr/local/bin/ids from within dshell and pay attention to the user ids shown. Now terminate dshell running by dick but as root. Run simply:
su
If you omit the program specification, bash is the program that will be run by default. The result is a "root shell." After observing the root shell by giving the root user's password, return to dick's shell by "exit"ing.
Using the SUID permission on executable files
Return to virtual terminal 1 where the shell is running as root. Execute the following:
ls -l /usr/local/bin/ids
chown harry /usr/local/bin/ids
chmod +s /usr/local/bin/ids
ls -l /usr/local/bin/ids
Return to virtual terminal 3 where the shell is running as dick. Execute:
ids
Note the difference between the real and effective user ids reported. /usr/local/bin/ids is said to be "set UID" to its owner, and its owner is harry.
Using sudo
As root, start a few "sleep" processes and then observe their presence:
sleep 1000 &
sleep
2000 &
sleep 3000 &
ps -ef
jobs
Switch to virtual terminal 2 in order to be tom. There, try to kill the sleep processes that user root just started:
killall sleep
It didn't work. Try it another way, through sudo:
sudo killall sleep
Give tom's password when prompted. Still didn't work. It needs to be configured in order to work. Switch back to terminal 1 in order to be root. There, add the following line to the file /etc/sudoers:
tom ALL=(root) /usr/bin/killall sleep
You can add this line using an editor, like vi. If you don't know how to use the rather unwieldy vi, this command will append the line:
echo "tom ALL=(root) /usr/bin/killall sleep" >> /etc/sudoers
Return to virtual terminal 2 and again as tom try:
sudo killall sleep
When prompted for a password, give tom's not root's. Return to virtual terminal 1 and as root:
jobs
Where are the sleep processes? Did it work?
When finished be sure to go to each of your 3 terminals and log out:
exit
Questions:
1. In the above process diagram you found there are 2 parent-child pairs in
which the child has a UID that isn't the same as the parent's. One of them
appears in this list. Which one is it?
a. d-f
b. d-g
c. a-c
d. b-c
e. c-e
2. In box e of the diagram what is the command you wrote?
a. su
b. ps
c. ssh
d. bash
e. less
3. In box e of the diagram what is the username you wrote?
a. tom
b. dick
c. harry
d. root