Practical UNIX & Internet Security

Practical UNIX & Internet SecuritySearch this book
Previous: B.3 SUID and SGID Files Appendix C Next: C.2 Creating Processes

C. UNIX Processes

This appendix provides technical background on how the UNIX operating system manages processes. The information presented in this chapter is important to understand if you are concerned with the details of system administration or are simply interested in UNIX internals, but we felt that it was too technical to present early in this book.

C.1 About Processes

UNIX is a multitasking operating system. Every task that the computer is performing at any moment - every user running a word processor program, for example - has a process . The process is the operating system's fundamental tool for controlling the computer.

Nearly everything that UNIX does is done with a process. One process displays the word login: on the user's terminal and reads the characters that the user types to log into the system. Another process controls the line printer. On a workstation, a special process called the "window server" displays text in windows on the screen. Another process called the "window manager" lets the user move those windows around.

At any given moment, the average UNIX operating system might be running anywhere from ten to several hundred different processes; large mainframes might be running several thousand. UNIX runs at least one process for every user who is logged in, another process for every program that every user is running, and another process for every hard-wired terminal that is waiting for a new user to log in. UNIX also uses a variety of special processes for system functions.

C.1.1 Processes and Programs

A process is an abstraction of control that has certain special properties associated with it. These include a private stack, values of registers, a program counter, an address space containing program code and data, and so on. The underlying hardware and operating system software manage the contents of registers in such a way that each process views the computer's resources as its "own" while it is running. With a single processor, only one process at a time is actually running, with the operating system swapping processes from time to time to give the illusion that they are all running concurrently. Multi-processor computers can naturally run several processes with true synchronicity.

Every UNIX process has a program that it is running, even if that program is part of the UNIX operating system (a special program). Programs are usually referred to by the names of the files in which they are kept. For example, the program that lists files is called /bin/ls and the program that runs the line printer may be called /usr/lib/lpd.

A process can run a program that is not stored in a file in either of two ways:

  • The program's file can be deleted after its process starts up. In this case, the process's program is really stored in a file, but the file no longer has a name and cannot be accessed by any other processes. The file is deleted automatically when the process exits or runs another program.

  • The process may have been specially created in the computer's memory. This is the method that the UNIX kernel uses to begin the first process when the operating system starts up. This usually happens only at start-up, but some programming languages such as LISP can load additional object modules as they are running.

Normally, processes run a single program and then exit. However, a program can cause another program to be run. In this case, the same process starts running another program.

C.1.2 The ps Command

The ps command gives you a snapshot of all of the processes running at any given moment. ps tells you who is running programs on your system, as well as which programs the operating system is spending its time executing.

Most system administrators routinely use the ps command to see why their computers are running so slowly; system administrators should also regularly use the command to look for suspicious processes. (Suspicious processes are any processes that you don't expect to be running. Methods of identifying suspicious processes are described in detail in earlier chapters.)

C.1.2.1 Listing processes with systems derived from System V

The System V ps command will normally only print the processes that are associated with the terminal on which the program is being run. To list all of the processes that are running on your computer, you must run the program with the -ef options. The options are:




List all processes


Produce a full listing

For example: /bin/ps -ef
    root     0     0 64   Nov 16 ?        0:01 sched
    root     1     0 80   Nov 16 ?        9:56 /etc/init -
    root     2     0 80   Nov 16 ?        0:10 pageout
    root     3     0 80   Nov 16 ?       78:20 fsflush
    root   227     1 24   Nov 16 ?        0:00 /usr/lib/saf/sac -t 300
    root   269     1 18   Nov 16 console  0:00 /usr/lib/saf/ttymon -g -    root    97     1 80   Nov 16 ?        1:02 /usr/sbin/rpcbind
    root   208     1 80   Nov 16 ?        0:01 /usr/dt/bin/dtlogin
    root    99     1 21   Nov 16 ?        0:00 /usr/sbin/keyserv
    root   117     1 12   Nov 16 ?        0:00 /usr/lib/nfs/statd
    root   105     1 12   Nov 16 ?        0:00 /usr/sbin/kerbd
    root   119     1 27   Nov 16 ?        0:00 /usr/lib/nfs/lockd
    root   138     1 12   Nov 16 ?        0:00 /usr/lib/autofs/automoun    root   162     1 62   Nov 16 ?        0:01 /usr/lib/lpsched
    root   142     1 41   Nov 16 ?        0:00 /usr/sbin/syslogd
    root   152     1 80   Nov 16 ?        0:07 /usr/sbin/cron
    root   169   162  8   Nov 16 ?        0:00 lpNet
    root   172     1 80   Nov 16 ?        0:02 /usr/lib/sendmail -q1h
    root   199     1 80   Nov 16 ?        0:02 /usr/sbin/vold
    root   180     1 80   Nov 16 ?        0:04 /usr/lib/utmpd
    root   234   227 31   Nov 16 ?        0:00 /usr/lib/saf/listen tcp
 simsong 14670 14563 13 12:22:12 pts/11   0:00 rlogin next
    root   235   227 45   Nov 16 ?        0:00 /usr/lib/saf/ttymon
 simsong 14673 14535 34 12:23:06 pts/5    0:00 rlogin next
 simsong 14509     1 80 11:32:43 ?        0:05 /usr/dt/bin/dsdm
 simsong 14528 14520 80 11:32:51 ?        0:18 dtwm
 simsong 14535 14533 66 11:33:04 pts/5    0:01 /usr/local/bin/tcsh
 simsong 14529 14520 80 11:32:56 ?        0:03 dtfile -session dta003TF
    root 14467     1 11 11:32:23 ?        0:00 /usr/openwin/bin/fbconso simsong 14635 14533 80 11:48:18 pts/12   0:01 /usr/local/bin/tcsh
 simsong 14728 14727 65 15:29:20 pts/9    0:01 rlogin next
    root   332   114 80   Nov 16 ?        0:02 /usr/dt/bin/rpc.ttdbserv    root 14086   208 80   Dec 01 ?        8:26 /usr/openwin/bin/Xsun :0 simsong 13121 13098 80   Nov 29 pts/6    0:01 /usr/local/bin/tcsh
 simsong 15074 14635 20 10:48:34 pts/12   0:00 /bin/ps -ef

Table 27.2 describes the meaning of each field in this output.

Field in ps Output (System V)

Table C.1: Feild in ps Output (System V)




The username of the person running the command


The process's identification number (see next section)


The process ID of the process's parent process


The processor utilization; an indication of how much CPU time the process is using at the moment


The time that the process started executing


The controlling terminal for the process


The total amount of CPU time that the process has used


The command that was used to start the process

C.1.2.2 Listing processes with Berkeley-derived versions of UNIX

With Berkeley UNIX , you can use the command:

ps -auxww

to display detailed information about every process running on your computer. The options specified in this command are:




List all processes


Display the information in a user-oriented style


Include information on processes that do not have controlling ttys


Include the complete command lines, even if they run past 132 columns

For example:[1]

[1] Many Berkeley-derived versions also show a start time (START) between STAT and TIME.

ps -auxww

simsong   1996 62.6  0.6 1136 1000 q8 R      0:02 ps auxww
root       111  0.0  0.0   32   16 ?  I      1:10 /etc/biod 4
daemon     115  0.0  0.1  164  148 ?  S      2:06 /etc/syslog
root       103  0.0  0.1  140  116 ?  I      0:44 /etc/portmap
root       116  0.0  0.5  860  832 ?  I     12:24 /etc/mountd -i -s
root       191  0.0  0.2  384  352 ?  I      0:30 /usr/etc/bin/lpd
root        73  0.0  0.3  528  484 ?  S <    7:31 /usr/etc/ntpd -n
root         4  0.0  0.0    0    0 ?  I      0:00 tpathd
root         3  0.0  0.0    0    0 ?  R      0:00  idleproc
root         2  0.0  0.0 4096    0 ?  D      0:00  pagedaemon
root       239  0.0  0.1  180  156 co I      0:00  std.9600 console 
root         0  0.0  0.0    0    0 ?  D      0:08  swapper
root       178  0.0  0.3  700  616 ?  I      6:31 /etc/snmpd
root       174  0.0  0.1  184  148 ?  S      5:06 /etc/inetd
root       168  0.0  0.0   56   44 ?  I      0:16 /etc/cron
root       132  0.0  0.2  452  352 co I      0:11 /usr/etc/lockd
jdavis     383  0.0  0.1  176   96 p0 I      0:03 rlogin hymie
ishii     1985  0.0  0.1  284  152 q1 S      0:00 /usr/ucb/mail bl
root     26795  0.0  0.1  128   92 ?  S      0:00 timed
root     25728  0.0  0.0  136   56 t3 I      0:00 telnetd
jdavis     359  0.0  0.1  540  212 p0 I      0:00 -tcsh (tcsh)
root       205  0.0  0.1  216  168 ?  I      0:04 /usr/local/cap/atis
kkarahal 16296  0.0  0.4 1144  640 ?  I      0:00 emacs 
root       358  0.0  0.0  120   44 p0 I      0:03 rlogind
root     26568  0.0  0.0    0    0 ?  Z      0:00 <exiting>
root     10862  0.0  0.1  376  112 ?  I      0:00 rshd

The fields in this output are described in Table 27.3 . Individual STAT characters are described in Tables C-3, C-4, and C-5.

Table C.2: Fields in ps Output (Berkeley-derived)




The username of the process. If the process has a UID (described in the next section) that does not appear in /etc/passwd , the UID is printed instead.[2]


The process's identification number


The percentage of the system's CPU and memory that the process is using


The amount of virtual memory that the process is using


The resident set size of the process - the amount of physical memory that the process is occupying


The terminal that is controlling the process


A field denoting the status of the process; up to three letters (four under SunOS) are shown


CPU time used by the process


The name of the command (and arguments)

[2] If this happens, follow up to be sure you don't have an intruder.

Table C.3: . Runnability of Process (First Letter of STAT Field)




Actually running or runnable


Sleeping (sleeping > 20 seconds)


Idle (sleeping < 20 seconds)






In page wait


In disk wait



Table C.4: . Whether Process Swapped (Second Letter of STAT Field)




In core


Swapped out


A process that has exceeded a soft limit on memory requirements

Table C.5: . Whether Process Is running with Altered CPU Schedule (Third Letter of STAT Field)




The process is running at a low priority


nice (a number greater than 0).


The process is running at a high priority.

NOTE: Because command arguments are stored in the process's own memory space, a process can change what appears on its command line. If you suspect that a process may not be what it claims to be, type:

ps -c

This causes ps to print the name of the command stored in the kernel. This approach is substantially faster than the standard ps , and is more suitable for use with scripts that run periodically. Unfortunately, the ps -c display does not include the arguments of each command that is running.

C.1.3 Process Properties

The kernel maintains a set of properties for every UNIX process. Most of these properties are denoted by numbers. Some of these numbers refer to processes, while others determine what privileges the processes have.

C.1.3.1 Process identification numbers (PID)

Every process is assigned a unique number called the process identifier, or PID . The first process to run, called init , is given the number 1. Process numbers can range from 1 to 65535.[3] When the kernel runs out of process numbers, it recycles them. The kernel guarantees that no two active processes will ever have the same number.

[3] Some versions of UNIX may allow process numbers in a range different from 1 to 65535.

C.1.3.2 Process real and effective UID

Every UNIX process has two user identifiers: a real UID and an effective UID .

The real UID ( RUID ) is the actual user identifier ( UID ) of the person who is running the program. It is usually the same as the UID of the actual person who is logged into the computer, sitting in front of the terminal (or workstation).

The effective UID ( EUID ) identifies the actual privileges of the process that is running.

Normally, the real UID and the effective UID are the same. That is, normally you have only the privileges associated with your own UID . Sometimes, however, the real and effective UID can be different. This occurs when a user runs a special kind of program, called a SUID program, which is used to accomplish a specific function (such as changing the user's password). SUID programs are described in Chapter 4, Users, Groups, and the Superuser .

C.1.3.3 Process priority and niceness

Although UNIX is a multitasking operating system, most computers that run UNIX can run only a single process at a time.[4] Every fraction of a second, the UNIX operating system rapidly switches between many different processes, so that each one gets a little bit of work done within a given amount of time. A tiny but important part of the UNIX kernel called the process scheduler decides which process is allowed to run at any given moment and how much CPU time that process should get.

[4] Multiprocessor computers can run as many processes at a time as they have processors.

To calculate which process it should run next, the scheduler computes the priority of every process. The process with the lowest priority number (or the highest priority) runs. A process's priority is determined with a complex formula that includes what the process is doing and how much CPU time the process has already consumed. A special number, called the nice number or simply the nice , biases this calculation: the lower a process's nice number, the higher its priority, and the more likely that it will be run.

On most versions of UNIX , nice numbers are limited from -20 to +20. Most processes have a nice of 0. A process with a nice number of +19 will probably not run until the system is almost completely idle; likewise, a process with a nice number of -19 will probably preempt every other user process on the system.

Sometimes you will want to make a process run slower. In some cases, processes take more than their "fair share" of the CPU , but you don't want to kill them outright. An example is a program that a researcher has left running overnight to perform mathematical calculations that isn't finished the next morning. In this case, rather than killing the process and forcing the researcher to restart it later from the beginning, you could simply cut the amount of CPU time that the process is getting and let it finish slowly during the day. The program /etc/renice lets you change a process's niceness.

For example, suppose that Mike left a program running before he went home. Now it's late at night, and Mike's program is taking up most of the computer's CPU time:

ps aux | head -5 

mike     211 70.0   6.7  2.26M  1.08M   01  R   4:01   cruncher 
mike     129  8.2  15.1  7.06M  2.41M   01  S   0:48   csh  
donna    212  7.0   7.3  2.56M  1.16M   p1  S   1:38   csh 
michelle 290  4.0  11.9  14.4M  1.91M   03  R   19:00  rogue % 

You could slow down Mike's program by renicing it to a higher nice number.

For security reasons, normal users are only allowed to increase the nice numbers of their own processes. Only the superuser can lower the nice number of a process or raise the nice number of somebody else's process. (Fortunately, in this example, we know the superuser password!)



/etc/renice +4 211 

211: old priority 0, new priority 4  
ps u211 

mike  211  1.5  6.7  2.26M   1.08M   01  R  N  4:02  cruncher

The N in the STAT field indicates that the cruncher process is now running at a lower priority (it is "niced"). Notice that the process's CPU consumption has already decreased. Any new processes that are spawned by the process with PID 211 will inherit this new nice value, too.

You can also use /etc/renice to lower the nice number of a process to make it finish faster.[5] Although setting a process to a lower priority won't speed up the CPU or make your computer's hard disk transfer data faster, the negative nice number will cause UNIX to run a particular process more than it runs others on the system. Of course, if you ran every process with the same negative priority, there wouldn't be any apparent benefit.

[5] Only root can renice a process to make it faster. Normal processes can't even change themselves back to what they were (if they've been niced down). Normal users can't even raise the priority of their processes to the value at which they were started.

Some versions of the renice command allow you to change the nice of all processes belonging to a user or all processes in a process group (described in the next section). For instance, to speed up all of Mike's processes, you might type:

renice -2 -u mike

Remember, processes with a lower nice number run faster.

Note that because of the UNIX scheduling system, renicing several processes to lower numbers is likely to increase paging activity if there is limited physical memory, and therefore adversely impact overall system performance.

What do process priority and niceness have to do with security? If an intruder has broken into your system and you have contacted the authorities and are tracing the phone call, slowing the intruder down with a priority of +10 or +15 will limit the damage that the intruder can do without hanging up the phone (and losing your chance to catch the intruder). Of course, any time that an intruder is on a system, exercise extreme caution.

Also, running your own shell with a higher priority may give you an advantage if the system is heavily loaded. The easiest way to do so is by typing:

renice -5 $$

The shell will replace the $$ with the PID of the shell's process.

C.1.3.4 Process groups and sessions

With Berkeley-derived versions of UNIX , including SVR4 , each process is assigned a process ID ( PID ), a process group ID, and a session ID. Process groups and sessions are used to implement job control.

For each process, the PID is a unique number, the process group ID is the PID of the process group leader process, and the session ID is the PID of the session leader process. When a process is created, it inherits the process group ID and the session ID of its parent process. Any process may create a new process group by calling setpgrp() and may create a new session by calling the UNIX system call setsid() . All processes that have the same process group ID are said to be in the same process group.

Each UNIX process group belongs to a session group. This is used to help manage signals and orphaned processes. Once a user has logged in, the user may start multiple sets of processes, or jobs, using the shell's job-control mechanism. A job may have a single process, such as a single invocation of the ls command. Alternatively, a job may have several processes, such as a complex shell pipeline. For each of these jobs, there is a process group. UNIX also keeps track of the particular process group which is controlling the terminal. This can be set or changed with ioctl() system calls. Only the controlling process group can read or write to the terminal.

A process could become an orphan if its parent process exits but it continues to run. Historically, these processes would be inherited by the init process but would remain in their original process group. If a signal were sent by the controlling terminal (process group), then it would go to the orphaned process, even though it no longer had any real connection to the terminal or the rest of the process group.

To counter this, POSIX defines an orphaned process group. This is a process group where the parent of every member is either not a member of the process group's session, or is itself a member of the same process group. Orphaned process groups are not sent terminal signals when they are generated. Because of the way in which new sessions are created, the initial process in the first process group is always an orphan (its ancestor is not in the session). Command interpreters are usually spawned as session leaders so they ignore TSTP signals from the terminal.