adb进入手机,执行ps,如下图所示,在USER一栏除了有system,root以外,还有类似media_rw,u0_a78这种名字,那么这些字符串到底代表了什么?
android是在linux基础上构建的,而用户和组是linux中很重要的概念。linux系统允许多用户同时操作,用户和组主要是为了多用户同时工作来服务的。同时,linux还定义了对文件和目录进行操作的权限,操作的动作包括读、写、执行。
linux对某一文件或者目录的权限的管理分为:文件拥有者,文件所属于的组,其他用户。例如:
drwxr-xr-x 2 user user 4096 Jan 9 10:11 documents
文件documents,拥有者user的权限为读写可执行(rwx),组user的权限为读可执行(r-x),其他用户的权限为读可执行(r-x)。
注:linux一个用户可以属于多个组;而某个文件一般只属于一个组。但是如果支持posix acl扩展,利用setfacl getfacl等命令也能使得某个文件属于多个组。在我理解,acl扩展主要是为了弥补linux拥有者:组:其他用户这种模式的“粗犷”。
举个例子,如果用户user2也想去写documents这个文件,我们可以想到几种方法来实现:
1.将user2加入到组user中
2.给documents的其他用户增加写权限
从上面两个解决方法,都能感觉有些太过粗糙,对other定义的太过宽泛,而acl就是为了解决这个问题而产生的,简单地来说acl就是可以设置特定用户或者用户组对于一个文件的操作权限。
对android而言,是“单”用户的(从代码看貌似现在也支持多用户了),AOSP将linux用户这个概念做了修改。给每一个安装运行的app赋予不同的UID。下面结合代码看看这些system,root等字符串到底是什么(代码基于android 5.1)。
在system/core/include/private/android_filesystem_config.h中,有定义了数字的AID,从注释可以看出各个数字所对应的含义:
#define AID_ROOT 0 /* traditional unix root user */
#define AID_SYSTEM 1000 /* system server */
#define AID_RADIO 1001 /* telephony subsystem, RIL */
#define AID_BLUETOOTH 1002 /* bluetooth subsystem */
#define AID_GRAPHICS 1003 /* graphics devices */
#define AID_INPUT 1004 /* input devices */
#define AID_AUDIO 1005 /* audio devices */
#define AID_CAMERA 1006 /* camera devices */
#define AID_LOG 1007 /* log devices */
#define AID_COMPASS 1008 /* compass device */
#define AID_MOUNT 1009 /* mountd socket */
#define AID_WIFI 1010 /* wifi subsystem */
#define AID_ADB 1011 /* android debug bridge (adbd) */
#define AID_INSTALL 1012 /* group for installing packages */
#define AID_MEDIA 1013 /* mediaserver process */
#define AID_DHCP 1014 /* dhcp client */
#define AID_SDCARD_RW 1015 /* external storage write access */
#define AID_VPN 1016 /* system */
#define AID_KEYSTORE 1017 /* keystore subsystem */
#define AID_USB 1018 /* USB devices */
#define AID_DRM 1019 /* DRM server */
#define AID_MDNSR 1020 /* MulticastDNSResponder (service discovery) */
#define AID_GPS 1021 /* GPS daemon */
#define AID_UNUSED1 1022 /* deprecated, DO NOT USE */
#define AID_MEDIA_RW 1023 /* internal media storage write access */
#define AID_MTP 1024 /* MTP USB driver access */
#define AID_UNUSED2 1025 /* deprecated, DO NOT USE */
#define AID_DRMRPC 1026 /* group for drm rpc */
#define AID_NFC 1027 /* nfc subsystem */
#define AID_SDCARD_R 1028 /* external storage read access */
#define AID_CLAT 1029 /* clat part of nat464 */
#define AID_LOOP_RADIO 1030 /* loop radio devices */
#define AID_MEDIA_DRM 1031 /* MediaDrm plugins */
#define AID_PACKAGE_INFO 1032 /* access to installed package details */
#define AID_SDCARD_PICS 1033 /* external storage photos access */
#define AID_SDCARD_AV 1034 /* external storage audio/video access */
#define AID_SDCARD_ALL 1035 /* access all users external storage */
#define AID_LOGD 1036 /* log daemon */
#define AID_SHARED_RELRO 1037 /* creator of shared GNU RELRO files */
#define AID_SHELL 2000 /* adb and debug shell user */
#define AID_CACHE 2001 /* cache access */
#define AID_DIAG 2002 /* access to diagnostic resources */
/* The 3000 series are intended for use as supplemental group id's only.
* They indicate special Android capabilities that the kernel is aware of. */
#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */
#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */
#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
#define AID_NET_RAW 3004 /* can create raw INET sockets */
#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */
#define AID_NET_BW_STATS 3006 /* read bandwidth statistics */
#define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */
#define AID_NET_BT_STACK 3008 /* bluetooth: access config files */
#define AID_EVERYBODY 9997 /* shared between all apps in the same profile */
#define AID_MISC 9998 /* access to misc storage */
#define AID_NOBODY 9999
#define AID_APP 10000 /* first app user */
#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */
#define AID_USER 100000 /* offset for uid ranges for each user */
#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
#define AID_SHARED_GID_END 59999 /* start of gids for apps in each user to share */
其中APP的AID是从10000开始,而AID_USER为100000。从注释上看,Android现在也支持多用户了,AID_USER(100000)是每个用户的offset;而AID_APP表示用户安装的app的赋值的起始数值,而system,root这些AID系统已经固定。大概的意思是,第n个用户所安装的第m个apk的uid为n*AID_USER+10000+m (其中n从0开始,m每个apk都不同)。例如用户1所安装的第123个apk所对应的AID为0*100000+10000+123为10123,而用户2所安装的第123个apk所对应的AID为1*100000+10000+123为110123(每个用户最多可能装99000-10000=89000个app^_^)。
static const struct android_id_info android_ids[] = {
{ "root", AID_ROOT, },
{ "system", AID_SYSTEM, },
{ "radio", AID_RADIO, },
{ "bluetooth", AID_BLUETOOTH, },
{ "graphics", AID_GRAPHICS, },
{ "input", AID_INPUT, },
{ "audio", AID_AUDIO, },
{ "camera", AID_CAMERA, },
{ "log", AID_LOG, },
{ "compass", AID_COMPASS, },
{ "mount", AID_MOUNT, },
{ "wifi", AID_WIFI, },
{ "adb", AID_ADB, },
{ "install", AID_INSTALL, },
{ "media", AID_MEDIA, },
{ "dhcp", AID_DHCP, },
{ "sdcard_rw", AID_SDCARD_RW, },
{ "", AID_VPN, },
{ "keystore", AID_KEYSTORE, },
{ "usb", AID_USB, },
{ "drm", AID_DRM, },
{ "mdnsr", AID_MDNSR, },
{ "gps", AID_GPS, },
// AID_UNUSED1
{ "media_rw", AID_MEDIA_RW, },
{ "mtp", AID_MTP, },
// AID_UNUSED2
{ "drmrpc", AID_DRMRPC, },
{ "nfc", AID_NFC, },
{ "sdcard_r", AID_SDCARD_R, },
{ "clat", AID_CLAT, },
{ "loop_radio", AID_LOOP_RADIO, },
{ "mediadrm", AID_MEDIA_DRM, },
{ "package_info", AID_PACKAGE_INFO, },
{ "sdcard_pics", AID_SDCARD_PICS, },
{ "sdcard_av", AID_SDCARD_AV, },
{ "sdcard_all", AID_SDCARD_ALL, },
{ "logd", AID_LOGD, },
{ "shared_relro", AID_SHARED_RELRO, },
{ "shell", AID_SHELL, },
{ "cache", AID_CACHE, },
{ "diag", AID_DIAG, },
{ "net_bt_admin", AID_NET_BT_ADMIN, },
{ "net_bt", AID_NET_BT, },
{ "inet", AID_INET, },
{ "net_raw", AID_NET_RAW, },
{ "net_admin", AID_NET_ADMIN, },
{ "net_bw_stats", AID_NET_BW_STATS, },
{ "everybody", AID_EVERYBODY, },
{ "misc", AID_MISC, },
{ "nobody", AID_NOBODY, },
};
那么ps中第一列的用户id字符串和AID数字到底是如何转换的?在bionic/libc/bionic/stubs.cpp中,app_id_from_name函数就是从字符串到数字AID的转换,从注释就可以看出具体的转换方法和含义。
字符串已u*_开始,其中*为0,1,2….,为不同的用户,后面a代表app,i代表isolated,system,root等可以参考上面的数组android_ids[]。
// Translate a user/group name to the corresponding user/group id.
// u0_a1234 -> 0 * AID_USER + AID_APP + 1234
// u2_i1000 -> 2 * AID_USER + AID_ISOLATED_START + 1000
// u1_system -> 1 * AID_USER + android_ids['system']
// returns 0 and sets errno to ENOENT in case of error
static unsigned app_id_from_name(const char* name) {
if (name[0] != 'u' || !isdigit(name[1])) {
errno = ENOENT;
return 0;
}
char* end;
unsigned long userid = strtoul(name+1, &end, 10);
if (end[0] != '_' || end[1] == 0) {
errno = ENOENT;
return 0;
}
unsigned long appid = 0;
if (end[1] == 'a' && isdigit(end[2])) {
// end will point to \0 if the strtoul below succeeds.
appid = strtoul(end+2, &end, 10) + AID_APP;
} else if (end[1] == 'i' && isdigit(end[2])) {
// end will point to \0 if the strtoul below succeeds.
appid = strtoul(end+2, &end, 10) + AID_ISOLATED_START;
} else {
for (size_t n = 0; n < android_id_count; n++) {
if (!strcmp(android_ids[n].name, end + 1)) {
appid = android_ids[n].aid;
// Move the end pointer to the null terminator.
end += strlen(android_ids[n].name) + 1;
}
}
}
// Check that the entire string was consumed by one of the 3 cases above.
if (end[0] != 0) {
errno = ENOENT;
return 0;
}
// Check that user id won't overflow.
if (userid > 1000) {
errno = ENOENT;
return 0;
}
// Check that app id is within range.
if (appid >= AID_USER) {
errno = ENOENT;
return 0;
}
return (unsigned)(appid + userid*AID_USER);
}