在上一篇文章(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