通过PackageManager的学习,我们知道,android的UID和linux的UID根本是两回事,Linux的UID是用于针对多用户操作系统中用于区分用户的。而Android中的UID是用于系统进行权限管理的,相信大家在shell环境中进行ps命令查询的时候,屏幕都会输出如下的信息,那么,对于输出信息中的USER一栏中具体的system,radio,u0_a1(CanlendarProvider),u0_a27(deskClock)等等这就是我们今天的主人公UID,奇怪的就是之前我们理解的uid都是有正整数来表示,为毛这里是字串的形式,uid是整数这点毋庸置疑,会出现字串的情况应该是有一个一一对应的关系。

为了探索这个对应关系,今天我们就以此为例,探索下这些UID的具体由来。

USER      PID   PPID  VSIZE  RSS   WCHAN              PC  NAMEu0_a42    1971  597   1443692 35452 SyS_epoll_ 7f7dca9ba4 S com.android.printspooleru0_a24    2003  597   1440292 33136 SyS_epoll_ 7f7dca9ba4 S com.qualcomm.qti.accesscacheu0_a50    2110  597   1440316 32912 SyS_epoll_ 7f7dca9ba4 S com.android.smspushsystem    2127  597   1470876 37476 SyS_epoll_ 7f7dca9ba4 S com.android.settingsradio     2140  597   1442476 43824 SyS_epoll_ 7f7dca9ba4 S com.qualcomm.qcrilmsgtunnelsystem    2212  597   1444100 35500 SyS_epoll_ 7f7dca9ba4 S com.qualcomm.telephonysystem    2286  597   1442632 34892 SyS_epoll_ 7f7dca9ba4 S com.qti.diagservicessystem    2301  597   1440236 34528 SyS_epoll_ 7f7dca9ba4 S com.qualcomm.qti.qsu0_a1     2318  597   1443108 39640 SyS_epoll_ 7f7dca9ba4 S com.android.providers.calendaru0_a8     2335  597   1442188 34216 SyS_epoll_ 7f7dca9ba4 S com.android.managedprovisioningu0_a9     2351  597   1440216 33492 SyS_epoll_ 7f7dca9ba4 S com.android.onetimeinitializeru0_a20    2368  597   1440176 32664 SyS_epoll_ 7f7dca9ba4 S com.qualcomm.qti.calendarlocalaccountu0_a26    2381  597   1440680 33512 SyS_epoll_ 7f7dca9ba4 S com.qti.csku0_a27    2394  597   1448988 40792 SyS_epoll_ 7f7dca9ba4 S com.android.deskclock

首先,通过对于android系统的了解,由于android进程是由zygote进程孵化而来,因此通过zygote的fork流程,我们可以断定,这个字符串并非在这里生成的。如下简要列出zygote孵化的重要部分:

android探索之UID u0_axxx的由来_第1张图片

最终在fork的子进程中通过系统调用setresgid和setresuid对当前的进程uid和gid进行了设置,但是这里仍然是数字。无法确认整数和字符的对应关系。所以并非是zygote对其进行了映射转换。

接着我们看第二个方向,由于这些信息终是由ps命令而输出,而这里的ps命令又与原生linux中的ps命令不同,android中源码中,具体的实现代码在/system/core/toolbox/ps.c中,其对应的函数为ps_line方法。

static int ps_line(int pid, int tid, char *namefilter){    // 略去无关代码    pw = getpwuid(stats.st_uid);    if(pw == 0 || (display_flags & SHOW_NUMERIC_UID)) {        sprintf(user,"%d",(int)stats.st_uid);    } else {        strcpy(user,pw->pw_name);    }    // 略去无关代码}

这个方法体很长,我们只关注重点部分,getpwuid即是我们要获取UID的方法了。这里需要注意,这个方法是在libc(android实现的轻量级c库boinic)中,路径bionic/libc/bionic/stubs.c

passwd* getpwuid(uid_t uid) { // NOLINT: implementing bad function.  passwd_state_t* state = g_passwd_tls_buffer.get();  if (state == NULL) {    return NULL;  }  passwd* pw = android_id_to_passwd(state, uid);  if (pw != NULL) {    return pw;  }  return app_id_to_passwd(uid, state);}

这里首先通过传入的uid通过android_id_to_passwd方法去查找,如果有查到,便直接返回了。这里我插一下,这个uid啊,是由userid+appid得来的, 而userid即为我们android的用户id,appid即PKMS在apk安装的时候给每个应用分配的,想要了解PKMS是怎样给安装的应用程序分配uid的同学请戳如下文章深入了解:

Android M PackageManagerService 启动过程分析

Android M PackageManager对于应用程序apk的安装流程分析

我们跟进android_id_to_passwd方法。

static passwd* android_id_to_passwd(passwd_state_t* state, unsigned id) {  for (size_t n = 0; n < android_id_count; ++n) {    if (android_ids[n].aid == id) {      return android_iinfo_to_passwd(state, android_ids + n);    }  }  return NULL;}

android_id_passwd的情况是通过查询一个android_ids的数组,其中定义了各个特殊uid和字符串的对应关系,如system root shell等系统级别的,定义在文件/system/core/include/private/android_filesystem_config.h当中的,看一下,是不是似曾相识?

#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 range 2900-2999 is reserved for OEM, and must never be * used here */#define AID_OEM_RESERVED_START 2900#define AID_OEM_RESERVED_END   2999/* 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_QCOM_DIAG     3009  /* can read/write /dev/diag */#define AID_SENSORS       3011 /* access to /dev/socket/sensor_ctl_socket & QCCI/QCSI */#define AID_RFS           3012  /* Remote Filesystem for peripheral processors */#define AID_RFS_SHARED    3013  /* Shared files for Remote Filesystem for peripheral processors  */#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 */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, },    { "shared_relro",  AID_SHARED_RELRO, },    { "shell",         AID_SHELL, },    { "cache",         AID_CACHE, },    { "diag",          AID_DIAG, },    { "qcom_diag",     AID_QCOM_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, },    { "net_bw_acct",   AID_NET_BW_ACCT, },    { "net_bt_stack",  AID_NET_BT_STACK, },    { "sensors",       AID_SENSORS, },    { "rfs",           AID_RFS, },    { "rfs_shared",    AID_RFS_SHARED, },    { "everybody",     AID_EVERYBODY, },    { "misc",          AID_MISC, },    { "nobody",        AID_NOBODY, },};

这里就很清楚了,那些系统级别的uid对应的字符串都是在这里定义的,比如我们开篇提到的system,radio等等,而普通的应用呢则不是在这里匹配得到,方法自然会返回null,那么就会进入后面的流程 app_id_to_passwd。

#define AID_USER 100000    /* offset for uid ranges for each user */ #define AID_ISOLATED_START 99000  /* start of uids for fully isolated sandboxed processes */ #define AID_APP 10000 // Translate a uid into the corresponding name.// 0 to AID_APP-1                   -> "system", "radio", etc.// AID_APP to AID_ISOLATED_START-1  -> u0_a1234// AID_ISOLATED_START to AID_USER-1 -> u0_i1234// AID_USER+                        -> u1_radio, u1_a1234, u2_i1234, etc.// returns a passwd structure (sets errno to ENOENT on failure).static passwd* app_id_to_passwd(uid_t uid, passwd_state_t* state) {  if (uid < AID_APP) {    errno = ENOENT;    return NULL;  }  print_app_name_from_uid(uid, state->name_buffer_, sizeof(state->name_buffer_));  const uid_t appid = uid % AID_USER;  if (appid < AID_APP) {      snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");  } else {      snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/data");  }  snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");  passwd* pw = &state->passwd_;  pw->pw_name  = state->name_buffer_;  pw->pw_dir   = state->dir_buffer_;  pw->pw_shell = state->sh_buffer_;  pw->pw_uid   = uid;  pw->pw_gid   = uid;  return pw;}static void print_app_name_from_uid(const uid_t uid, char* buffer, const int bufferlen) {  const uid_t appid = uid % AID_USER;  const uid_t userid = uid / AID_USER;  if (appid >= AID_ISOLATED_START) {    snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START);  } else if (appid < AID_APP) {    for (size_t n = 0; n < android_id_count; n++) {      if (android_ids[n].aid == appid) {        snprintf(buffer, bufferlen, "u%u_%s", userid, android_ids[n].name);        return;      }    }  } else {    snprintf(buffer, bufferlen, "u%u_a%u", userid, appid - AID_APP);  }}

看到这个方法后,我们不禁恍然大悟啊,通过上面的宏定义以及计算方法,我们不难得出:

  • app的uid/100000的结果为userid,填到ux的x处。
  • app的uid减去10000为appid,填到axx的xx处。
  • 例如某个app的uid是10022,经过计算,userid为10022/100000=0,appid为10022-10000=22,则那么最终通过ps打印得到uid字串就是u0_a22

那么这个useid在系统中哪里可以查到呢?当然是在pkms中啦 ,比如在packages.list中就会有哦。

com.gd.mobicore.pa 10047 0 /data/data/com.gd.mobicore.pa platform 3003com.qualcomm.qti.auth.sampleextauthservice 10049 0 /data/data/com.qualcomm.qti.auth.sampleextauthservice platform nonecom.cootek.smartinputv5.language.indonesian 10062 0 /data/data/com.cootek.smartinputv5.language.indonesian default nonecom.qrd.omadownload 10036 0 /data/data/com.qrd.omadownload platform 3003com.cootek.smartinputv5.language.vietnam 10072 0 /data/data/com.cootek.smartinputv5.language.vietnam default nonecom.android.providers.telephony 1001 0 /data/data/com.android.providers.telephony platform 2001,1005,3002,1023,1015,3003,3001,3009,3006com.cootek.smartinputv5.language.cangjie 10059 0 /data/data/com.cootek.smartinputv5.language.cangjie default nonecom.android.providers.calendar 10001 0 /data/data/com.android.providers.calendar default 3003com.android.providers.media 10006 0 /data/data/com.android.providers.media default 2001,1023,1015,3003,1024,3007com.qti.service.colorservice 1000 0 /data/data/com.qti.service.colorservice platform 2001,3002,1023,1015,3003,3001,1021,3004,3005,1000,2002,3009,1010com.qualcomm.shutdownlistner 10053 0 /data/data/com.qualcomm.shutdownlistner platform nonecom.android.wallpapercropper 10016 0 /data/data/com.android.wallpapercropper platform nonecom.quicinc.cne.CNEService 1000 0 /data/data/com.quicinc.cne.CNEService platform 2001,3002,1023,1015,3003,3001,1021,3004,3005,1000,2002,3009,1010com.android.protips 10043 0 /data/data/com.android.protips default nonecom.qualcomm.qti.phonefeature 1001 0 /data/data/com.qualcomm.qti.phonefeature platform 2001,1005,3002,1023,1015,3003,3001,3009,3006com.cootek.smartinputv5.language.marathi 10063 0 /data/data/com.cootek.smartinputv5.language.marathi default noneorg.simalliance.openmobileapi.service 1000 0 /data/data/org.simalliance.openmobileapi.service platform 2001,3002,1023,1015,3003,3001,1021,3004,3005,1000,2002,3009,1010com.android.documentsui 10028 0 /data/data/com.android.documentsui platform nonecom.android.externalstorage 10007 0 /data/data/com.android.externalstorage platform 1023,1015com.cootek.smartinputv5.language.spanishlatin 10066 0 /data/data/com.cootek.smartinputv5.language.spanishlatin default nonecom.qualcomm.uimremoteclient 1001 0 /data/data/com.qualcomm.uimremoteclient platform 2001,1005,3002,1023,1015,3003,3001,3009,3006com.android.htmlviewer 10030 0 /data/data/com.android.htmlviewer default nonecom.qualcomm.ftm 10029 0 /data/data/com.qualcomm.ftm platform nonecom.qualcomm.sta 1000 0 /data/data/com.qualcomm.sta platform 2001,3002,1023,1015,3003,3001,1021,3004,3005,1000,2002,3009,1010com.qualcomm.svi 1000 0 /data/data/com.qualcomm.svi platform 2001,3002,1023,1015,3003,3001,1021,3004,3005,1000,2002,3009,1010com.android.deskclock 10027 0 /data/data/com.android.deskclock platform none

上面的第二列即是每个app对应的uid了,我们可以看到,canlendarprovider的uid为10001,而deskclock的是10027,那么经过计算,我们得到的USER分别为u0_a1, u0_a27。

可能有些人会问:博主,看你打印都是u0_axx,那有些u10_axx中是u10是怎么回事,我看到过的哦。

    /**     * @hide Range of uids allocated for a user.     */    public static final int PER_USER_RANGE = 100000;    public static final int getUid(int userId, int appId) {        if (MU_ENABLED) {            return userId * PER_USER_RANGE + (appId % PER_USER_RANGE);        } else {            return appId;        }    }

很简单,u10_axx就是多用户下的进程了,我们打开多用户开关,切换到访客模式或者通过新建user的方式,完成后进行ps一下,输出如下:

// ps输出 访客模式u0_a34    13056 597   1440200 32780 SyS_epoll_ 7f7dca9ba4 S com.qualcomm.qti.lunarinfosystem    13069 597   1440288 33880 SyS_epoll_ 7f7dca9ba4 S com.qualcomm.timeserviceu10_a42   32319 597   1443772 35444 SyS_epoll_ 7f7dca9ba4 S com.android.printspooleru10_a8    32341 597   1442188 33064 SyS_epoll_ 7f7dca9ba4 S com.android.managedprovisioningu10_system 32355 597   1470876 36316 SyS_epoll_ 7f7dca9ba4 S com.android.settingsu10_radio 32388 597   1440252 32800 SyS_epoll_ 7f7dca9ba4 S com.qualcomm.qcrilmsgtunnelu10_a44   32406 597   1440248 35280 SyS_epoll_ 7f7dca9ba4 S com.android.provisionu10_a14   32419 597   1453712 44656 SyS_epoll_ 7f7dca9ba4 S com.android.systemuiu10_system 32434 597   1448136 37004 SyS_epoll_ 7f7dca9ba4 S com.qualcomm.location.XTsystem    32492 1     14332  3832  hrtimer_na 7f964c9594 S /system/bin/ATFWD-daemon// 新建user 11u11_system 3022  591   1440164 33184 SyS_epoll_ 7f96147ba4 S com.qualcomm.qti.notificationserviceu11_a37   3035  591   1447512 35676 SyS_epoll_ 7f96147ba4 S com.oma.drmu11_radio 3050  591   1451772 39164 SyS_epoll_ 7f96147ba4 S com.android.phoneu11_a45   3063  594   878888 36016 SyS_epoll_ 00f7427c64 S com.qti.smq.qualcommFeedbacku11_system 3077  591   1441432 34276 SyS_epoll_ 7f96147ba4 S com.qualcomm.qti.GBAHttpAuthentication.authu11_a46   3096  591   1440756 33672 SyS_epoll_ 7f96147ba4 S com.qualcomm.qti.telephonyserviceu11_system 3114  591   1441200 34632 SyS_epoll_ 7f96147ba4 S com.qualcomm.qualcommsettingsu11_radio 3128  591   1442344 34000 SyS_epoll_ 7f96147ba4 S com.qualcomm.qti.rcsbootstraputilu11_system 3143  591   1441420 34084 SyS_epoll_ 7f96147ba4 S com.qualcomm.telephony

是不是很神奇?

android探索之UID u0_axxx的由来_第2张图片

更多相关文章

  1. Android手机访问Django测试服务器方法
  2. Android 如何将定制的Launcher成为系统中唯一的Launcher
  3. android Map 使用方法
  4. 安卓系统新手入门教程
  5. Android 9 网络适配 (系统造成App内图片无法加载解决方案)

随机推荐

  1. 回望十年Android
  2. Android(安卓)ImageView 图片等比缩放问
  3. Android(安卓)UI Action Bar之ActionBarS
  4. Android(安卓)开源项目 eoe 社区 Android
  5. 亚马逊面向开发人员推出Android应用商店
  6. Android的三个阶段
  7. 条码扫描二维码扫描——ZXing android 源
  8. android 不是内部或外部命令
  9. Android面试及开发忠告
  10. android