adb进入手机,执行ps,如下图所示,在USER一栏除了有system,root以外,还有类似media_rw,u0_a78这种名字,那么这些字符串到底代表了什么?
linux用户和组android是在linux基础上构建的,而用户和组是linux中很重要的概念。linux系统允许多用户同时操作,用户和组主要是为了多用户同时工作来服务的。同时,linux还定义了对文件和目录进行操作的权限,操作的动作包括读、写、执行。
- 1.读权限:
对文件来说,顾名思义,允许读取文件的内容;对目录,读权限允许列出目录中的内容。 - 2.写权限:
对文件来说,就是可写入内容;对目录,允许修改目录的内容,比如删除、添加文件。 - 3.可执行:
对文件来说,就是可执行或者脚本;对目录有执行权限,可以允许你cd到该目录中,记得以前看过内核文件系统的路径解析代码,如果目录没可执行权限,则返回错误。
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 UID
对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 /* vpn 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, }, { "vpn", 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 errorstatic 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); }