Directly view the kernel's running process table and system variables
The /proc filesystem contains a representation of the kernel's live process table. By manipulating files and directories in /proc, you can learn about (and fiddle with) all sorts of parameters in the running system. Be warned that poking around under /proc as root can be extraordinarily dangerous, as root has the power to overwrite virtually anything in the process table. One slip of a redirector, and Linux will very obligingly blow away your entire kernel memory, without so much as a "so long and thanks for all the kcore."
Here are some examples of interesting things to do with /proc. In these examples, we'll assume that you're using a recent kernel (about 2.4.18 or so) and that you are logged in as root. Unless you're root, you will only be able to view and modify processes owned by your uid.
First, let's take a look at a lightly loaded machine:
root@catlin:/proc# ls 1/ 204/ 227/ 37/ bus/ hermes/ loadavg scsi/ version 1039/ 212/ 228/ 4/ cmdline ide/ locks self@ 1064/ 217/ 229/ 5/ cpuinfo interrupts meminfo slabinfo 1078/ 220/ 230/ 6/ devices iomem misc stat 194/ 222/ 231/ 698/ dma ioports modules swaps 197/ 223/ 232/ 7/ driver/ irq/ mounts sys/ 2/ 224/ 233/ 826/ execdomains kcore net/ sysvipc/ 200/ 225/ 254/ 827/ filesystems kmsg partitions tty/ 202/ 226/ 3/ apm fs/ ksyms pci uptime
The directories consisting of numbers contain information about every process running on the system. The number corresponds to the PID. The rest of the files and directories correspond to drivers, counters, and many other internals of the running kernel. The interface operates just as any other file or device in the system, by reading from and writing to each entry as if it were a file. Suppose you want to find out which kernel is currently booted:
root@catlin:/proc# cat version Linux version 2.4.18 (root@catlin) (gcc version 2.95.3 20010315 (release)) #2 Sat Jun 22 19:01:17 PDT 2002
Naturally, you could find much of that out by simply running uname -a, but this way cuts out the middle man (and actually does what uname does internally).
Interested in how much RAM we have installed? Take a look at kcore:
root@catlin:/proc# ls -l kcore -r-------- 1 root root 201330688 Aug 28 21:39 kcore
Looks like we have 192MB installed in this machine (201330688/1024/1024 == 192, more or less). Notice the restricted file permissions? That is the system's defense against anyone attempting to read the memory directly. Of course, you're root and can do whatever you like. There's nothing preventing you from running grep or strings on kcore and looking for interesting tidbits. This is the system memory, and things get cached in there until overwritten (making it possible to hunt down accidentally lost data or track down naughty people doing things they oughtn't). Grovelling over kcore is actually not much fun and is typically only a method used by the very desperate (or very bored).
Some other notable status files:
root@catlin:/proc# cat interrupts CPU0 0: 34302408 XT-PIC timer 1: 2 XT-PIC keyboard 2: 0 XT-PIC cascade 3: 289891 XT-PIC orinoco_cs 8: 1 XT-PIC rtc 9: 13933886 XT-PIC eth0 10: 25581 XT-PIC BusLogic BT-958 14: 301982 XT-PIC ide0 NMI: 0 ERR: 0
These are the system counters for every interrupt that has ever been called, its number, and the driver that called it.
root@catlin:/proc# cat partitions major minor #blocks name 8 0 8971292 sda 8 1 8707198 sda1 8 2 257040 sda2 3 64 29316672 hdb 3 65 29310561 hdb1
This is a list of all of the hard disk partitions (and devices) that were discovered at boot, along with their respective sizes. Here we have a 9GB SCSI disk, and a 30GB IDE disk. All available partitions are represented here, regardless of whether they are currently mounted (making it a handy reference to see if there are any unmounted disks on the system).
Let's leave the system parameters and take a look at the structure of an individual process.
root@catlin:/proc# cd 1 root@catlin:/proc/1# ls -l total 0 -r--r--r-- 1 root root 0 Aug 28 22:05 cmdline lrwxrwxrwx 1 root root 0 Aug 28 22:05 cwd -> // -r-------- 1 root root 0 Aug 28 22:05 environ lrwxrwxrwx 1 root root 0 Aug 28 22:05 exe -> /sbin/init* dr-x------ 2 root root 0 Aug 28 22:05 fd/ -r--r--r-- 1 root root 0 Aug 28 22:05 maps -rw------- 1 root root 0 Aug 28 22:05 mem lrwxrwxrwx 1 root root 0 Aug 28 22:05 root -> // -r--r--r-- 1 root root 0 Aug 28 22:05 stat -r--r--r-- 1 root root 0 Aug 28 22:05 statm -r--r--r-- 1 root root 0 Aug 28 22:05 status
There are three interesting symlinks in this directory.
cwd points to the current working directory of
this process (you can, for example,
/proc/3852/cwd to land in the directory from which process
ID 3852 was run.) The exe link points to full
path to the binary that was called, and
points to the notion of the root directory that this process has. The
root link will almost always be /, unless it has
executed a chroot.
The cmdline and environ files contain the command line as it was originally called and the processes complete environment. These are separated by NULL characters, so to see them in a more human readable form, try this:
root@catlin:/proc/1# cat environ |tr '\0' '\n' HOME=/ TERM=linux BOOT_IMAGE=catlin
(or for a better example, try this on /proc/self/environ, the environment of the currently running process):
root@catlin:/proc/1# cat /proc/self/environ |tr '\0' '\n' PWD=/proc/1 HOSTNAME=catlin.nocat.net MOZILLA_HOME=/usr/lib/netscape ignoreeof=10 LS_OPTIONS= --color=auto -F -b -T 0 MANPATH=/usr/local/man:/usr/man:/usr/X11R6/man LESSOPEN=|lesspipe.sh %s PS1=\u@\h:\w\$ PS2=> ...
and so on. This can be tremendously handy for use in shell scripts (or other programs) where you need specific information about running processes. Just use it with care, and remember that unprivileged users can usually only access information about their own processes.
# ls -d /proc/* |grep [0-9]|wc -l; ps ax |wc -l
This will give you a quick spot check of the number of running processes versus the number that ps actually reports. Many rootkits install a hacked ps that allows a miscreant to hide processes (by simply not displaying them when ps runs). You may hide from ps, but it's much more difficult to hide from /proc. If the second number is considerably larger than the first (particularly if you run it several times in a row) then you might want to consider taking your box offline for further inspection. Quickly.