Hack #57: 使用fakeroot模擬root權限執行程序
fakeroot是什么
例如Debian在生成package的時候,編譯完之后,不能立刻在當前環境執行make install,需要執行make install DESTDIR=$(pwd)/debian/tmp把生成的文件安裝到build目錄的里面$(pwd)/debian/tmp。然后使用那個目錄里面的全部內容生成Debian包(實際上包里面還會包含control和maintainer script等)。 這個包里面的文件所有者必須是root,所以需要以root來執行打包命令。但是應該避免在制作Debian包的時候使用root權限。 為了解決這個矛盾,fakeroot被開發出來了。在fakeroot環境中,操作文件就像使用root操作文件一樣。但是,實際上系統中文件的權限還是原來的權限。
|
像這樣執行fakeroot后會在fakeroot環境中啟動一個shell。這個shell中就像擁有root權限一樣。執行id(1)命令會提示為root,並且文件的所有者也會變成root。新生成的文件所有者也是root,還可以把現有文件的所有者改成其他人。 但是實際上變更的只反應在fakeroot環境內部。退出fakeroot環境后就能看到實際上的文件屬性。 在制作Debian包的時候,需要使用root權限來執行某些命令。本來是應該使用sudo來運行這些命令的,但是通常情況下是使用fakeroot模擬root運行。
fakeroot的實現
fakeroot僅僅是簡單的shell script。簡單來說fakeroot做下面的事情。 * 啟動faked,獲取FAKEROOTKEY * 設置環境變量FAKEROOTKEY,LD_LIBRARY_PATH,LD_PRELOAD。執行命令(默認是shell)
faked是管理虛擬的文件所有者,文件權限信息的守護進程。 在fakeroot中執行的命令會加載由LD_LIBRARY_PATH,LD_PRELOAD環境變量指定的一個動態鏈接庫(/usr/lib/libfakeroot/libfakeroot-sysv.so)
|
libfakeroot-sysv.so導出了以下函數
| getuid() |
geteuid() |
getguid() |
getegid() |
| mknod() |
|||
| chown() |
fchown() |
lchown() |
|
| chmod() |
fchmod() |
||
| mkdir() |
|||
| lstat() |
fstat() |
stat() |
|
| unlink() |
remove() |
rmdir() |
rename() |
這些函數會使用FAKEROOTKEY與faked通訊,返回虛擬的所有者與權限信息。
/usr/lib/libfakeroot-sysv.so
與faked通訊的庫文件是/usr/lib/libfakeroot/libfakeroot-sysv.so,但是/usr/lib/libfakeroot-sysv.so也是存在的。這個文件是在fakeroot中運行suid程序所必須的。 fakeroot中會設定LD_LIBRARY_PATH環境變量。設定LD_LIBRARY_PATH后LD_PRELOAD就不需要是完整路徑了。但是如果LD_PRELOAD不使用完整路徑,suid的程序會忽略LD_LIBRARY_PATH而直接在/lib與/usr/lib中尋找LD_PRELOAD指定的庫文件。如果LD_PRELOAD指定的文件沒有找到這個suid的程序就會啟動失敗。所以會存在/usr/lib/libfakeroot-sysv.so這樣一個suid的dummy庫,在運行suid程序的時候通過LD_PRELOAD加載這個庫,就跟沒有加載任何東西一樣,正常執行。 * 普通的程序 使用LD_LIBRARY_PATH=/usr/lib/libfakeroot LD_PRELOAD=libfakeroot-sysv.so,通過preload加載/usr/lib/libfakeroot/libfakeroot-sysv.so的與faked通訊 * suid的程序 無視LD_LIBRARY_PATH, 使用LD_PRELOAD=libfakeroot-sysv.so,通過preload加載/usr/lib/libfakeroot-sysv.so,因為這是一個dummy庫,就與這個庫不存在一樣,程序正常執行。
總結
例如Debian生成package這樣,在必須使用root的時候,使用fakeroot模擬root權限。fakeroot使用libfakeroot-sysv.so庫文件中的函數與faked通訊管理文件權限信息。
— Fumitoshi Ukai
