使用fakeroot模擬root權限執行程序(轉)


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操作文件一樣。但是,實際上系統中文件的權限還是原來的權限。

$ ls foo $ ls -l total 0 -rw-r--r-- 1 kghost staff 0 Feb 11 14:17 foo $ fakeroot # id uid=0(root) gid=0(root) groups=0(root),50(staff),100(users) # ls -l total 0 -rw-r--r-- 1 root root 0 Feb 11 14:17 foo # touch bar # ls -l -rw-r--r-- 1 root root 0 Feb 11 14:17 bar -rw-r--r-- 1 root root 0 Feb 11 14:17 foo # chown www-data:www-data foo # ls -l total 0 -rw-r--r-- 1 root root 0 Feb 11 14:17 bar -rw-r--r-- 1 www-data www-data 0 Feb 11 14:17 foo # exit $ ls -l total 0 -rw-r--r-- 1 kghost staff 0 Feb 11 14:17 bar -rw-r--r-- 1 kghost staff 0 Feb 11 14:17 foo

像這樣執行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)

LD_LIBRARY_PATH=/usr/lib/libfakeroot LD_PRELOAD=libfakeroot-sysv.so

libfakeroot-sysv.so導出了以下函數

Table 1. test

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM