在上一篇文章(http://my.oschina.net/u/2310891/blog/621672)的結尾處拋出了一個問題,即在正常狀況下可以使用普通用戶身份執行地ping命令爲什麼在使用了strace跟蹤後會報出"EPERM(Operation not permitted)"的錯誤?shell
錯誤出在這一句:
小程序
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = -1 EPERM (Operation not permitted)
這是因爲建立raw socket時須要root權限形成的,有由socket syscall調用的inet_create函數的實現爲證:
socket
err = -EPERM; if (sock->type == SOCK_RAW && !kern && !ns_capable(net->user_ns, CAP_NET_RAW)) goto out_rcu_unlock;
這就有點奇怪了,在執行ping程序時並無使用root權限,爲什麼可以正常運行,而在使用strace跟蹤後又會報錯呢?tcp
沉思兩秒後,咱們先來看看ping程序文件的屬性:
函數
$which ping /bin/ping $ls -l /bin/ping -rwsr-xr-x 1 root root 35712 Nov 8 2011 /bin/ping
發現一些不同了吧,有一個不太常見的標誌「s」混進了權限位中,google一下rws,很快你就會明白其中的奧祕了,簡而言之就是若是我使用root權限爲某個程序文件加入了uid權限,那麼以後即便經過普通用戶的身份執行該程序,也同樣可以得到root用戶的權限。
ui
這就是爲何可以直接執行ping程序而並不會出現EPERM錯誤的緣由了。
this
可是strace時出錯的緣由尚未找到。
google
咱們知道,strace和shell的基本實現都是fork+execv的模式,那麼爲何會形成這種差別呢,下面一步步來驗證:
spa
1. 編寫一個小程序tcp_client,其主要內容是建立一個raw socket,而後執行它:.net
$ ls -l -rwxrwxr-x 1 yyy yyy 13207 Feb 25 11:10 tcp_client $ ./tcp_client raw socket create failed, errno: 1, Operation not permitted
因爲程序的全部者和執行者都是yyy,所以在建立原始套接字的時候不出意外的失敗了。
2. 施展setuid魔法的時候到了,請仔細看下面的步驟:
$ sudo cp tcp_client tcp_client_chmod $ ls -l -rwxr-xr-x 1 root root 13207 Feb 25 15:12 tcp_client_chmod $ chmod u+s tcp_client_chmod chmod: changing permissions of `tcp_client_chmod': Operation not permitted $ sudo !! sudo chmod u+s tcp_client_chmod $ ls -l -rwsr-xr-x 1 root root 13207 Feb 25 15:12 tcp_client_chmod $ ./tcp_client_chmod raw socket create success! Usage: ./tcp_client serverip serverport
噔噔噔噔,這下使用普通用戶權限也可以執行須要root權限的程序啦。
爲什麼在cp的時候要使用sudo呢?
這是由於咱們原來的程序文件全部者是yyy用戶,而程序的執行須要root權限,所以咱們要先將文件全部者變爲root用戶,而後再應用setuid,纔會有奇效。
3. 接下來咱們寫一個小程序myshell,讓它經過fork+execv的模式來執行tcp_client_chmod:
$ ./myshell ./tcp_client_chomd parent 18375 wait for 18376 child 18376 do execv! raw socket create success! Usage: ./tcp_client serverip serverport
事實證實,即便咱們使用普通用戶的身份來執行myshell,且在myshell中沒有作任何setuid相關的操做,依然可以正確執行須要root權限的程序,也就是說經過execv調用是沒有問題的。
這下又迷惑了:爲何strace不行呢?
玄機就藏在man strace中:
SETUID INSTALLATION If strace is installed setuid to root then the invoking user will be able to attach to and trace processes owned by any user. In addition setuid and setgid programs will be executed and traced with the correct effective privileges. Since only users trusted with full root privileges should be allowed to do these things, it only makes sense to install strace as setuid to root when the users who can execute it are restricted to those users who have this trust. For example, it makes sense to install a special version of strace with mode `rwsr- xr--', user root and group trace, where members of the trace group are trusted users. If you do use this feature, please remember to install a non-setuid version of strace for ordinary lusers to use. BUGS Programs that use the setuid bit do not have effective user ID privileges while being traced.
啊哈,原來是一個Bug呀!
另外看一下咱們系統中安裝的strace程序,沒有按照"SETUID INSTALLATION"中說明的安裝爲setuid形式,所以默認狀況下也就沒法跟蹤其餘用戶所擁有的進程:
$ which strace /usr/bin/strace $ ls -l /usr/bin/strace -rwxr-xr-x 1 root root 314192 May 27 2011 /usr/bin/strace