最近在搞android里面的su(不是为了做root提权,那是别的部门干的事)。学习了一些新东西,挺有意思。
以下文章假定你的android设备已经被root了,有获取root权限的能力,或者在Linux环境下。
SU这个程序嘛,说简单一点就是让你的程序能够以android/linux里面最高的root权限执行。例如通常情况下,在android里面运行的apk是没有root权限的,所以你想以root权限去启动一个进程,你得写代码:
runtime.getRuntime().exec("su -c myProgram");
这样,启动的myProgram程序就具有root权限了。SU程序为什么有这样的特性呢?能让普通用户启动的程序变成属于超级用户root的程序呢?
这就必须得提到Linux的特殊文件权限位了。
我们来看一下su程序的属性:
shell@android:/data # ls /system/bin/su -l
ls /system/bin/su -l
-rwsr-sr-x root shell 97385 2014-03-04 11:33 su
rwx我们知道分别代表的是 读/写/执行 权限,可是su这个程序在本来的x位置却不是写的x而是
s属性。s代表什么意思呢?请看下文介绍。
以下说明来自鸟哥的论坛(http://phorum.vbird.org/viewtopic.php?t=20256)
Set UID
还有一篇英文(http://www.tutorialspoint.com/unix/unix-file-permission.htm)以passwd程序为例
SUID and SGID File Permission:
Often when a command is executed, it will have to be executed with special privileges in order to accomplish its task.
As an example, when you change your password with the passwd command, your new password is stored in the file /etc/shadow.
As a regular user, you do not have read or write access to this file for security reasons, but when you change your password, you need to have write permission to this file. This means that the passwdprogram has to give you additional permissions so that you can write to the file /etc/shadow.
Additional permissions are given to programs via a mechanism known as the Set User ID ( SUID) and Set Group ID ( SGID) bits.
When you execute a program that has the SUID bit enabled, you inherit the permissions of that program's owner. Programs that do not have the SUID bit set are run with the permissions of the user who started the program.
This is true for SGID as well. Normally programs execute with your group permissions, but instead your group will be changed just for this program to the group owner of the program.
The SUID and SGID bits will appear as the letter "s" if the permission is available. The SUID "s" bit will be located in the permission bits where the owners execute permission would normally reside. For example, the command
$ ls -l /usr/bin/passwd -r-sr-xr-x 1 root bin 19031 Feb 7 13:47 /usr/bin/passwd* $
Which shows that the SUID bit is set and that the command is owned by the root. A capital letter S in the execute position instead of a lowercase s indicates that the execute bit is not set.
If the sticky bit is enabled on the directory, files can only be removed if you are one of the following users:
The owner of the sticky directory
The owner of the file being removed
The super user, root
To set the SUID and SGID bits for any directory try the following:
$ chmod ug+s dirname $ ls -l drwsr-sr-x 2 root root 4096 Jun 19 06:45 dirname $上文加粗的地方特别提到了,如果owner和group两个位置的执行权限没有设置的话,那么设置了SUID或者SGID后出现的将是大写的S,而不是小写的s.
礼物上文提到了sticky bit的作用,如果sticky bit在某一目录上有设置,那么这个目录里面的文件只能被三种用户所删除:
1 目录的所有者
2 文件的所有者
3 root超级用户
维基百科的sticky bit词条也说明了“When the sticky bit is set, only the item's owner, the directory's owner, or the superuser can rename or delete files.”所以上面鸟哥论坛里面介绍sticky bit作用时少说了一种情况:设置了sticky bit的目录的所有者也是可以删除或者重命名目录下的文件的。
只需要一个函数stat就可以了。如下代码获取/system/bin/su程序的属性(包括特殊权限位)
struct stat results;
stat("/system/bin/su", &results);
printf("permission is %#o\n", results.st_mode);
printf("user READ permission: %d\n", (bool)(results.st_mode & S_IRUSR));
printf("user WRITE permission: %d\n", (bool)(results.st_mode & S_IWUSR));
printf("user Exec permission: %d\n", (bool)(results.st_mode & S_IXUSR));
printf("group READ permission: %d\n", (bool)(results.st_mode & S_IRGRP));
printf("group WRITE permission: %d\n", (bool)(results.st_mode & S_IWGRP));
printf("group Exec permission: %d\n", (bool)(results.st_mode & S_IXGRP));
printf("other READ permission: %d\n", (bool)(results.st_mode & S_IROTH));
printf("other WRITE permission: %d\n", (bool)(results.st_mode & S_IWOTH));
printf("other Exec permission: %d\n", (bool)(results.st_mode & S_IXOTH));
printf("SUID permission: %d\n", (bool)(results.st_mode & S_ISUID));
printf("SGID permission: %d\n", (bool)(results.st_mode & S_ISGID));
printf("Sticky Bit permission: %d\n", (bool)(results.st_mode & S_ISVTX));
permission is 0106755
user READ permission: 1
user WRITE permission: 1
user Exec permission: 1
group READ permission: 1
group WRITE permission: 0
group Exec permission: 1
other READ permission: 1
other WRITE permission: 0
other Exec permission: 1
SUID permission: 1
SGID permission: 1
Sticky Bit permission: 0
PS:上面的代码里面%#o会在打印出来的8进制数值前面加0。如果用%#x,那么打印出来的16进制前面会自动加0x,这样我们就不需要用0x%x来格式化输出了。