#Linux的边边角角# 之 "EPERM"错误和setuid魔法

    在上一篇文章(http://my.oschina.net/u/2310891/blog/621672)的结尾处抛出了一个问题,即在正常情况下能够使用普通用户身份执行地ping命令为何在使用了strace跟踪后会报出"EPERM(Operation not permitted)"的错误?

    错误出在这一句:

socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = -1 EPERM (Operation not permitted)

    这是由于创建raw socket时需要root权限造成的,有由socket syscall调用的inet_create函数的实现为证:

err = -EPERM;
if (sock->type == SOCK_RAW && !kern &&
    !ns_capable(net->user_ns, CAP_NET_RAW))
        goto out_rcu_unlock;

    这就有点奇怪了,在执行ping程序时并没有使用root权限,为何能够正常运行,而在使用strace跟踪后又会报错呢?

    沉思两秒后,我们先来看看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用户的权限。

    这就是为什么能够直接执行ping程序而并不会出现EPERM错误的原因了。

    但是strace时出错的原因还没有找到。

    我们知道,strace和shell的基本实现都是fork+execv的模式,那么为什么会造成这种差异呢,下面一步步来验证:

    1. 编写一个小程序tcp_client,其主要内容是创建一个raw socket,然后执行它:

$ 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





转载于:https://my.oschina.net/u/2310891/blog/624704

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux错误码65280对应的错误号(errno)是126,表示执行一个命令时发生了错误。以下是常见的Linux错误号及其对应的错误: 1. EPERM (1):操作不允许 2. ENOENT (2):文件或目录不存在 3. ESRCH (3):没有这样的进程 4. EINTR (4):系统调用被中断 5. EIO (5):输入/输出错误 6. ENXIO (6):没有这样的设备或地址 7. E2BIG (7):参数列表太长 8. ENOEXEC (8):执行格式错误 9. EBADF (9):文件描述符无效 10. ECHILD (10):没有这样的子进程 11. EAGAIN (11):资源暂时不可用 12. ENOMEM (12):内存不足 13. EACCES (13):权限不足 14. EFAULT (14):错误的地址 15. ENOTBLK (15):块设备必须使用块IO 16. EBUSY (16):设备或资源忙 17. EEXIST (17):文件已存在 18. EXDEV (18):跨文件系统链接 19. ENODEV (19):操作不支持设备 20. ENOTDIR (20):不是目录 21. EISDIR (21):是目录 22. EINVAL (22):无效的参数 23. ENFILE (23):文件打开太多 24. EMFILE (24):文件描述符打开太多 25. ENOTTY (25):不是终端设备 26. ETXTBSY (26):文本文件忙 27. EFBIG (27):文件太大 28. ENOSPC (28):没有空间 29. ESPIPE (29):无效的seek 30. EROFS (30):只读文件系统 31. EMLINK (31):链接太多 32. EPIPE (32):捕获信号管道 33. EDOM (33):数学参数超出定义域 34. ERANGE (34):数学结果不可表示 35. EDEADLK (35):资源死锁避免 36. ENAMETOOLONG (36):文件名太长 37. ENOLCK (37):没有可用的记录锁 38. ENOSYS (38):函数不支持 39. ENOTEMPTY (39):目录不为空 40. ELOOP (40):太多的符号链接 41. ENOMSG (42):没有消息的标识符 42. EIDRM (43):标识符已删除 43. ECHRNG (44):通道范围不正确 44. EL2NSYNC (45):Level 2不同步 45. EL3HLT (46):Level 3被挂起 46. EL3RST (47):Level 3重置 47. ELNRNG (48):Link number超出范围 48. EUNATCH (49):Protocol driver不可用 49. ENOCSI (50):没有CSI结构可用 50. EL2HLT (51):Level 2被挂起 51. EBADE (52):无效的交换 52. EBADR (53):无效的请求描述符 53. EXFULL (54):交换空间已满 54. ENOANO (55):没有对应的自动识别对象 55. EBADRQC (56):无效的请求描述符或参数 56. EBADSLT (57):Slot不存在 57. EBFONT (59):无效字体文件格式 58. ENOSTR (60):设备不是流 59. ENODATA (61):没有数据可用 60. ETIME (62):计时器已过期 61. ENOSR (63):没有记录可用 62. ENONET (64):网络不可用 63. ENOPKG (65):包没有安装 64. EREMOTE (66):对象是远程的 65. ENOLINK (67):链路不存在 66. EADV (68):广告错误 67. ESRMNT (69):Srmount错误 68. ECOMM (70):通信错误 69. EPROTO (71):协议错误 70. EMULTIHOP (72):多跳跃I / O 71. EDOTDOT (73):RFS特定错误 72. EBADMSG (74):错误的消息 73. EOVERFLOW (75):值太大以便于定义 74. ENOTUNIQ (76):名称不唯一 75. EBADFD (77):文件描述符在错误状态 76. EREMCHG (78):远程地址已更改 77. ELIBACC (79):无法访问共享库 78. ELIBBAD (80):共享库损坏 79. ELIBSCN (81):没有共享库文本段 80. ELIBMAX (82):共享库表已满 81. ELIBEXEC (83):无法执行共享库 82. EILSEQ (84):无效的或不完整的多字节序列 83. ERESTART (85):无需重新启动系统调用 84. ESTRPIPE (86):管道流不支持 85. EUSERS (87):太多用户 86. ENOTSOCK (88):套接字操作的目标不是套接字 87. EDESTADDRREQ (89):需要目标地址 88. EMSGSIZE (90):消息太长 89. EPROTOTYPE (91):错误的协议类型 90. ENOPROTOOPT (92):协议不可用 91. EPROTONOSUPPORT (93):协议不支持 92. ESOCKTNOSUPPORT (94):套接字类型不支持 93. EOPNOTSUPP (95):操作不支持 94. EPFNOSUPPORT (96):协议族不支持 95. EAFNOSUPPORT (97):地址族不支持 96. EADDRINUSE (98):地址已在使用中 97. EADDRNOTAVAIL (99):不能分配所需的地址 98. ENETDOWN (100):网络已关闭 99. ENETUNREACH (101):网络不可达 100. ENETRESET (102):网络连接已重置 101. ECONNABORTED (103):连接被中止 102. ECONNRESET (104):连接被重置 103. ENOBUFS (105):没有缓冲区可用 104. EISCONN (106):套接字已连接 105. ENOTCONN (107):套接字未连接 106. ESHUTDOWN (108):不能执行发送,套接字已关闭 107. ETOOMANYREFS (109):太多参考:无法分配请求的资源 108. ETIMEDOUT (110):连接超时 109. ECONNREFUSED (111):连接被拒绝 110. EHOSTDOWN (112):主机已关闭 111. EHOSTUNREACH (113):主机不可达 112. EALREADY (114):操作已经在进行中 113. EINPROGRESS (115):操作正在进行中 114. ESTALE (116):Stale NFS文件句柄 115. EUCLEAN (117):结构取消 116. ENOTNAM (118):不是XENIX命名文件 117. ENAVAIL (119):No XENIX semaphores available 118. EISNAM (120):Is a named type file 119. EREMOTEIO (121):远程I / O错误 120. EDQUOT (122):Quota exceeded 121. ENOMEDIUM (123):没有中介信息 122. EMEDIUMTYPE (124):中介错误 123. ECANCELED (125):操作被取消 124. ENOKEY (126):没有KEY值 125. EKEYEXPIRED (127):KEY已过期 126. EKEYREVOKED (128):KEY已被撤销 127. EKEYREJECTED (129):KEY被拒绝 128. EOWNERDEAD (130):所有者已死 129. ENOTRECOVERABLE (131):无法恢复

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值