在普通的 Linux 系统中,只要可执行文件设置了 s 权限,就可以调用 setuid(0) 将自身提升到 root。例如,我们编写下面的一段程序:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
void print(void) {
printf(
" UID GID \n"
"Real %d Real %d \n"
"Effective %d Effective %d \n",
getuid (), getgid (),
geteuid(), getegid()
);
}
int main(void) {
print();
setuid(0);
print();
return 0;
}
该程序会先打印出自己的 uid 和 gid,然后执行 setuid(0) 提升权限,然后再打印 uid 和 gid 看效果。
假设编译出来的文件是 test,通过 chown 和 chmod 将其设置 s 权限:
ls -l test
-rwsr-sr-x root root 2636 2012-02-07 11:28 test
此时,执行 test 的结果可能是:
UID GID
Real 501 Real 20
Effective 0 Effective 0
UID GID
Real 0 Real 20
Effective 0 Effective 0
也就是说,在 setuid(0) 之前,uid = 501,执行 setuid(0) 之后,uid = 0,已经提升到 root 权限了。
但是,同样的程序,放到 Android 系统里,却遇到了问题。我们首先用下面的命令把编译好的 Android binary 复制到手机里:
adb push test /data/local
然后设置 /data/local/test 文件的 owner,可执行权限和 s 权限。然后执行 test,结果成了:
UID GID
Real 2000 Real 2000
Effective 2000 Effective 2000
UID GID
Real 2000 Real 2000
Effective 2000 Effective 2000
可见,uid 和 gid 都没有变化,setuid() 没有生效。为什么呢?检查了半天,最后发现,是 Android kernel 对 setuid() 进行了修改,只有在 /system 分区下,s 权限才起作用。将 test 文件复制到 /system 分区下,设置 s 权限后,执行的结果就成了:
UID GID
Real 2000 Real 2000
Effective 0 Effective 0
UID GID
Real 0 Real 2000
Effective 0 Effective 0
转载:http://blog.csdn.net/quaful/article/details/7225065