一、說明
2.1 背景說明
在上家公司的時候想實現應用進程不使用root用戶啟動,但開發反饋像配置網卡等命令就是得用root來執行的,領導朋友說可以通過setuid解決這個問題。
由於物聯網設備畢竟是和硬件強相關的改造動作可能比較大又可能遺漏某些意想不到的地方,並沒有着手處理root啟動的問題。
所以自己對setuid使用不是很清楚,但也就沒更進一步研究。最近總感覺這問題留在這讓人很不舒服,所以就再來研究一下。
2.2 setuid的作用
setuid的程序,任何用戶執行時,都以setuid程序文件所屬的用戶的身份運行。
一般使用場景是,對歸屬root的程序進行setuid,以便普通用戶有root用戶的權限。
二、setuid實現
演示操作:setuid前普通用戶不能刪除root用戶的文件,setuid后普通用戶可以刪除root用戶的文件。
2.1 環境准備
將以下代碼保存成test.c:
#include <stdio.h> #include <unistd.h> int main() { printf("the uid is: %d\n", geteuid()); sleep(5); // system("rm -f test.txt"); remove("test.txt"); return 0; }
將其編譯成可執行文件test:
gcc test.c -o test
創建搭配使用的test.txt:
touch test.txt
最終環境如下:
2.2 未setuid前刪除文件失敗
如下所示,未setuid前,用戶身份就是普通用戶(uid是1000),未能成功刪除屬於root的test.txt文件。
2.3 setuid后文件刪除成功
如下所示,setuid(即對文件進行chmod +s)后,還是普通用戶執行,但程序報運行自己的是root用戶(uid是0),且確實能成功刪除屬於root用戶的test.txt文件。
此時使用也可以ps看到雖是普通用戶執行,但ps顯示的是root用戶。
三、setuid不可用的情況
3.1 shell腳本s權限無效
由於腳本s權限會導致較大的安全隱患,所以Linux調整成了只認可二進制可執行文件的s權限,而忽略腳本類可執行文件的s權限。腳本類包括shell、python等等。
3.2 子進程不繼承s權限
腳本類文件s權限不受認可,那么可不可以先用C寫個程序賦予s權限,然后在C里通過system()等函數調用腳本,從而通過“傳遞”實現腳本s權限呢。
答案是不行的。不僅system()調用腳本不行,system()調用二進制可執行文件也不具有s權限。
本質原因是,system()是通過fork()建立子進程,fork()建立子進程時把子進程歸屬uid而歸屬euid。
參考: