UNIX一切皆文件的思想正確嗎
一切皆XX,這一看就是本質(zhì)論以及整體論信徒的吶喊!
引.關(guān)于樹(shù)型模型
樹(shù)型模型和一切皆文件沒(méi)有直接的關(guān)系,只是它們的經(jīng)歷很類(lèi)似。
近期看了一本老婆買(mǎi)的書(shū),《視覺(jué)繁美》。在古代,人們對(duì)樹(shù)情有獨(dú)鐘,最終包括組織架構(gòu),包括分類(lèi)都變成了樹(shù),讀到了后面的章節(jié),我才發(fā)現(xiàn),原來(lái)樹(shù)型模型并不是一切的本質(zhì),它是在公元前10000左右的美索不達(dá)米亞的新月地帶人為產(chǎn)生的,即農(nóng)業(yè)革命導(dǎo)致了人們產(chǎn)生了樹(shù)型模型的觀念。
樹(shù)型模型,很有秩序感,任意兩節(jié)點(diǎn)之間都是單向連通,任何節(jié)點(diǎn)都可以追溯和被追溯,一切顯得很完美。它甚至可以囊括世間萬(wàn)物。以分類(lèi)學(xué)為例子,古希臘哲學(xué)家波菲利的樹(shù)是一個(gè)典型,他事先定義了一切的屬性,然后用“有該屬性”還是“沒(méi)有該屬性”對(duì)事物進(jìn)行分類(lèi),最終所有的東西都可以在這棵樹(shù)上找到一個(gè)葉子作為自己的位置。
當(dāng)一切在樹(shù)型模型下都運(yùn)行得很美好的時(shí)候(包括經(jīng)濟(jì),政治,公司經(jīng)營(yíng)等),人們發(fā)現(xiàn)了原來(lái)更本質(zhì)的思想是互聯(lián)的思想,于是當(dāng)鏈接成了一切的時(shí)候,樹(shù)型模型就不再適用了。今天,我們處在一個(gè)復(fù)雜網(wǎng)絡(luò)的時(shí)代,復(fù)雜網(wǎng)絡(luò)無(wú)所不在,包括交際圈,城市,股票,氣象,以及我們的大腦本身。然而并不能因此否定提出“一切都是樹(shù)”的古人,正是因?yàn)樗麄兊哪P秃?jiǎn)單,人類(lèi)文明才會(huì)誕生并發(fā)展,今天我們迷茫于混沌,最終我們會(huì)發(fā)現(xiàn),混沌是有序的混沌。
我想說(shuō)的是,雖然一些觀點(diǎn)最終被證明是錯(cuò)的,但是一開(kāi)始的時(shí)候必須那么說(shuō),因?yàn)楹?jiǎn)單是引起前進(jìn)的動(dòng)力,當(dāng)遇到阻礙物或者瓶頸的時(shí)候,事情會(huì)橫向發(fā)展,即朝著復(fù)雜和混亂方面發(fā)展,但是復(fù)雜和混亂不是目標(biāo),而是試圖找一個(gè)繼續(xù)向上的洞,或許要做些調(diào)整,然后越過(guò)障礙后繼續(xù)簡(jiǎn)單向上,正如植物生長(zhǎng)一樣,生機(jī)勃勃。一切皆文件是UNIX的信條之一,如今它也遇到了一些挑戰(zhàn)。
關(guān)于一切皆文件的反例
procfs,進(jìn)程文件系統(tǒng)。是UNIX系統(tǒng)中展示進(jìn)程狀態(tài)以及相關(guān)數(shù)據(jù)的一個(gè)內(nèi)存文件系統(tǒng)。它有著古老的歷史,可能在最開(kāi)始就成了“一切皆文件”的事實(shí)上的布道者,你看,就連進(jìn)程狀態(tài)也都可以表現(xiàn)成文件。
一切皆文件,其最原始的含義是這樣的,即文件操作擁有統(tǒng)一且簡(jiǎn)單的接口,在計(jì)算機(jī)的公元前10000年那個(gè)年代,人們把所有的操作都可以歸結(jié)為讀,寫(xiě),控制,因此read,write,ioctl就成了最古老的文件操作集,如果試圖將所有的操作都?xì)w到文件操作,那就要建立一系列的映射,這些映射抽象出了機(jī)制和策略,這個(gè)映射是一對(duì)多的,一個(gè)統(tǒng)一的操作原語(yǔ)表示機(jī)制,而多個(gè)不同的操作實(shí)現(xiàn)表現(xiàn)為策略,最終,VFS誕生了!
有了VFS,人們就方便了,將一切都實(shí)現(xiàn)為一個(gè)文件系統(tǒng)。直到今天Linux還在做這樣的事,并且好像不像UNIX那樣會(huì)停下來(lái),當(dāng)然,這是后話(huà)。當(dāng)這種事情做的足夠多的時(shí)候,當(dāng)安全需求越來(lái)越多的時(shí)候,正如IP網(wǎng)絡(luò)后來(lái)面對(duì)的問(wèn)題一樣,簡(jiǎn)單的基于屬主的ACL便不足以映射一切的安全控制規(guī)則。問(wèn)題的關(guān)鍵在于,VFS導(dǎo)致出現(xiàn)的文件系統(tǒng)類(lèi)型以及數(shù)量是不受控制的,而UNIX的文件ACL卻是確定的,因此就需要作平行于VFS的另一個(gè)映射,也就是另一個(gè)機(jī)制到策略的映射,如果可以,我可以管它叫VACL。
然而,沒(méi)有出現(xiàn)VACL,因?yàn)锳CL的粒度太粗,其語(yǔ)義僅僅針對(duì)文件屬主,它只是說(shuō)“能還是不能”,并無(wú)法表示“能的話(huà),必須怎么做”,可是后來(lái),出現(xiàn)了類(lèi)似波菲利樹(shù)型分類(lèi)的一個(gè)東西,叫做“能力”,就是說(shuō),將能想到的所有的操作都用一個(gè)二進(jìn)制位表示,如果一個(gè)實(shí)體有這個(gè)操作的權(quán)限,則其為1,否則為0,這樣就產(chǎn)生了UNIX的能力模型,即POSIX Cap,一切都顯得很完美。但是,不同于后來(lái)的大眾分類(lèi)索引法取代樹(shù)型分類(lèi)索引法(實(shí)際上,直到今天還有人鼓吹樹(shù)型模型!),POSIX Cap并不是很好用。procfs同樣也不適合用Cap來(lái)管理安全性!
procfs中應(yīng)有盡有。該文件系統(tǒng)的內(nèi)容是自動(dòng)生成的,每一個(gè)進(jìn)程在里面有一個(gè)目錄,目錄下存在該進(jìn)程的屬性,試問(wèn),誰(shuí)來(lái)定義針對(duì)這些文件的操作的Cap,如果是系統(tǒng),那么系統(tǒng)在生成一個(gè)進(jìn)程的時(shí)候,如何知道怎么定義;如果是用戶(hù),那么無(wú)疑在fork/exec和procfs之間增加了一個(gè)HOOK,這太復(fù)雜了。procfs的本來(lái)的目的很簡(jiǎn)單,有兩類(lèi):
- 導(dǎo)出系統(tǒng)信息
- 導(dǎo)出進(jìn)程信息
不管怎樣都是為了增強(qiáng)其調(diào)試功能。不管怎樣,都不能試圖使用procfs來(lái)做一些違反UNIX原則的事。第一個(gè)問(wèn)題在于procfs導(dǎo)出的信息包括進(jìn)程的地址空間,隔離進(jìn)程地址空間是UNIX乃至所有操作系統(tǒng)的根本原則,只要將其展示在procfs,就可能會(huì)被read,write,mmap...很多的UNIX,包括BSD,都因?yàn)檫@個(gè)出過(guò)事情,因此后來(lái)的版本就干脆去掉了procfs;第二個(gè)問(wèn)題在于內(nèi)核空間該不該處理信息格式的問(wèn)題,由于VFS是HOOK在內(nèi)核態(tài)的,因此各種實(shí)際文件系統(tǒng)的操作也在內(nèi)核態(tài)實(shí)現(xiàn),于是就會(huì)有大量的格式化的操作在內(nèi)核進(jìn)行,然而不應(yīng)該再內(nèi)核做這些,如果直接導(dǎo)出二進(jìn)制數(shù)據(jù),卻又違反了procfs的本意。為什么不修補(bǔ)漏洞和問(wèn)題而干脆讓procfs下課,這正是體現(xiàn)了UNIX設(shè)計(jì)上的純粹主義,與之相反是Linux的折中主義。
#p#
圍繞著procfs的去留,有很多的辯論,辯論圍繞兩方面:
- procfs應(yīng)該下課:完全使用sysctl接口來(lái)代替procfs。既然作為進(jìn)程屬性一部分的地址空間無(wú)法導(dǎo)出,那么何必保留另外90%+呢?
- procfs應(yīng)該保留:考慮到sysctl并不是在每一個(gè)UNIX系統(tǒng)都是標(biāo)準(zhǔn)的工具集的一部分導(dǎo)致的互操作的問(wèn)題,建議保留統(tǒng)一接口的procfs。
不管怎樣,都是圍繞著UNIX哲學(xué)問(wèn)題的爭(zhēng)論。Linux卻完全拋開(kāi)這些,實(shí)現(xiàn)了自己的procfs。
Linux的折中
Linux沒(méi)有拋棄procfs,而是修補(bǔ)了它的關(guān)鍵問(wèn)題,至于另外一些不關(guān)鍵的問(wèn)題,Linux社區(qū)并不在意。在procfs的VFS操作集的定義上,Linux采用了以下的定義:
- #define mem_write NULL
- #ifndef mem_write
- //一個(gè)嚇人的注釋?zhuān)?nbsp;
- /* This is a security hazard */
- static ssize_t mem_write(struct file * file, const char * buf,
- ...
- #endif
- static struct file_operations proc_mem_operations = {
- .llseek = mem_lseek,
- //read操作有很多限制,不允許訪(fǎng)問(wèn)別的進(jìn)程的地址空間
- .read = mem_read,
- //NULL定義write操作
- .write = mem_write,
- .open = mem_open,
- //沒(méi)有mmap的實(shí)現(xiàn)
- };
這就避免了安全問(wèn)題!
Linux正在一切皆文件的路上越走越遠(yuǎn),并且還將繼續(xù)走下去,如今你能看到很多非常規(guī)的FS,比如procfs,sysfs,devfs,debugfs,cpuset,cgroup,sockfs等等...Linux小心翼翼地對(duì)包括procfs在內(nèi)的一切非常規(guī)文件系統(tǒng)進(jìn)行管理,哪些可以read,哪些可以write,哪些要嚴(yán)禁怎樣等等,都要經(jīng)過(guò)周密考慮,想來(lái)也只有Linux這種開(kāi)放的開(kāi)發(fā)平法平臺(tái)才敢這么做吧,有了任何漏洞可以馬上被找出來(lái)然后最快的速度給與修正!