在最近的安卓开发过程中,为了便于调试,厂家提供了一个root的版本给到我们,但是我发现系统中没有su命令。由于我在调试过程中经常涉及到切换用户,所以没有这个命令还是很麻烦的。
于是我根据AOSP的源码,自己编译了一个su命令,并推送到系统中,运行是可以的。
当我从root用户,切换为shell用户时,通过su进行切换完全没有问题;但是当我从shell用户切换为root用户时,我遇到了如下问题:
$su root
$su: setgid failed: Operation not permitted
通过万能的GPT,我了解到su的权限中可能存在问题,正常AOSP编译打包到系统后的su权限如下所示:
-rwsr-x--- 1 root shell 50K 2009-01-01 08:00 /system/xbin/su
这里的s权限表明其具有SUID位,允许su提权。所以要解决这个问题,我们可以通过chmod来手动设置SUID权限:
chmod 6755 /system/bin/su
在配置之后,总算是可以从shell用户切换为root用户了。
问题来了,什么是SUID呢,作为长时间接触Linux&Android的开发者,我也经常使用chmod,但还是第一次看到这样设置文件权限的。带着这样的问题,我再对Linux下的文件权限进行了探索。
Linux系统中的任何一个文件,一定会具备两个属性:所属用户,以及所属用户组,我们可以通过chown来修改文件所属用户,通过chgrp来修改文件所属用户组;
在DAC权限体系中,任何文件都会涉及到权限,权限可以细分为用户权限,所属用户组的权限,其他用户的权限。每一项权限可以细分为可读(r)、可写(w)、可执行(x)。
需要说明的是,除了可读、可写与可执行这三个权限,还有三个特殊权限:SUID、GUID、与STICKY权限。
SUID其实是Set-User-ID的缩写,这个特殊的权限作用在于:当某个文件具备SUID权限时,任何人来执行该文件时都会以该文件所有者的身份来执行。
这个权限非常有用,因为常规情况下我们设置用户、同一用户组和其他用户的权限,即使其他用户有执行权限,但程序执行过程中往往因为UID权限级别不够导致执行失败,此时我们就需要通过SUID权限位来进行设置。这里我们以Linux系统中的passwd为例:
$ls -lah /usr/bin/passwd
-rwsr-xr-x 1 root root 59K 2月 6 2024 /usr/bin/passwd
这样其他用户使用passwd来修改密码时,同样可以以root用户的权限去修改密码,这样能确保passwd修改密码能够执行成功。
如果文件拥有者没有x执行权限,设置了SUID之后会显示为S;如果文件拥有者没有x执行权限,设置了SUID之后会显示为s;这个特殊权限标志位会替代原本的文件Owner对应的x权限标志位。
SGID其实是Set-Group-ID的缩写,这个特殊的权限位与SUID比较类似:
1.当作用于文件时,具备SGID权限位的文件在执行时可以以Group的身份去执行
2.当作用于文件夹时,具备SGID权限位的文件夹内的所有子文件都以该文件夹的Owner作为自己的Group Owner
与SUID类似,当文件/文件夹所属用户组具备x执行权限时,会以小写s显示,如果不具备x执行权限,会以大写S显示。该特俗权限标志位替代的是文件所属用户组对应的x权限标志位。如下所示:
-rwsrwsr-x 1 franzkafka franzkafka 0 1月 10 10:04 test
在Linux中,我们一般通过chmod来设定文件的权限。在具体设置时我们有两种设置方法:Symbolic Method与Numeric Method这两种。
Symbolic Method:
chmod whowhatwhich FILE
其中who表明权限作用的用户,可选值包括u(User,文件所有者),g(Group,文件所属用户组),o(Others,其他用户)以及a(All,所有用户);
what表明对权限设定的操作,其中-表明去除权限,+表明增加权限,=设定权限(同时去除其他权限);
which表明具体的权限,这里我们使用r(读权限)、w(写权限)、x(执行权限),以及s(SUID权限)、g(GUID权限)和t(STICKY权限)。
如我们需要设置SUID权限,通过Symbolic Method进行设置:
chmod u+s /usr/bin/passwd
Numeric Method:
Numeric Method以0~7的数值来表示文件的权限,各个权限对应的数值不同,常规权限中r通过数值4表示,w通过数值2表示,x通过数值1表示,特殊权限中SUID权限通过数值4表示,GUID权限通过数值2表示,STICKY权限通过数值1表示。
如我们需要设置SUID权限,通过Numeric Method进行设置:
chmod 4775 /usr/bin/passwd #4表示SUID权限位
在设置SUID与GUID后,我们可以在程序内通过getuid与getgid系统调用来拿到调用方的UID或者GID,从而对调用方进行严格的权限管控。
The post 记一次su命令无法提权为root的问题 first appeared on FranzKafka Blog.