当前位置:   article > 正文

[日更-2019.5.18] Android 系统内的守护进程(一)--core类中的服务 : adbd

android coresyncservice

声明

  • 其实很好奇Android系统中的一些关键守护进程服务的作用;
  • 暂且大概分析下它们的作用,这样有助于理解整个系统的工作过程;
  • ADB本身也是个复杂的系统,最近在处理ADB相关的修改工作,后续相关adbd的会再添加进来;

0 写在前面的

  • 只要是操作系统,不用说的就是其中肯定会运行着一些很多守护进程(daemon)来完成很多杂乱的工作。通过系统中的init.rc文件也可以看出来,其中每个service中就包含着系统后台服务进程。
  • 而这些服务被分为:core类服务(adbd/servicemanager/healthd/lmkd/logd/vold)和main类服务;
  • main类服务又分为:网络类服务(netd/mdnsd/mtpd/rild)、图形及媒体类服务(surfaceflinger/bootanimation/mediaserver/dnnserver)、其他类服务(installd/keystore/debuggerd/sdcard/Zygote)

1 adbd的作用

        

    adbd是Android系统特有的ADB功能中运行在手机/平板端的守护进程,其在/init.usb.rc中的启动配置为:

  1. # adbd is controlled via property triggers in init.<platform>.usb.rc
  2. service adbd /sbin/adbd --root_seclabel=u:r:su:s0
  3. class core
  4. socket adbd stream 660 system system
  5. disabled
  6. seclabel u:r:adbd:s0

    调试者可以直接在PC上使用adb命令对设备进行调试,也可以通过ddms命令间接调试。在调试之前,要在系统开发者模式中打开“USB调试”的开关,其在底层其实是通过修改系统属性sys.usb.config的值为adb时打开的。

    在默认情况下,adbd是以uid root的权限启动的。不过它确实还会通过函数drop_privileges()主动把自己降到uid shell : shell,和几个GID权限,所在源码目录为:~/LineageOS/system/core/adb/daemon/main.cpp

  1. static void drop_privileges(int server_port) {
  2. std::unique_ptr<minijail, void (*)(minijail*)> jail(minijail_new(),
  3. &minijail_destroy);
  4. // Add extra groups:
  5. // AID_ADB to access the USB driver
  6. // AID_LOG to read system logs (adb logcat)
  7. // AID_INPUT to diagnose input issues (getevent)
  8. // AID_INET to diagnose network issues (ping)
  9. // AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
  10. // AID_SDCARD_R to allow reading from the SD card
  11. // AID_SDCARD_RW to allow writing to the SD card
  12. // AID_NET_BW_STATS to read out qtaguid statistics
  13. // AID_READPROC for reading /proc entries across UID boundaries
  14. gid_t groups[] = {AID_ADB, AID_LOG, AID_INPUT,
  15. AID_INET, AID_NET_BT, AID_NET_BT_ADMIN,
  16. AID_SDCARD_R, AID_SDCARD_RW, AID_NET_BW_STATS,
  17. AID_READPROC};
  18. minijail_set_supplementary_gids(jail.get(),
  19. sizeof(groups) / sizeof(groups[0]),
  20. groups);
  21. // Don't listen on a port (default 5037) if running in secure mode.
  22. // Don't run as root if running in secure mode.
  23. if (should_drop_privileges()) {
  24. drop_capabilities_bounding_set_if_needed();
  25. minijail_change_gid(jail.get(), AID_SHELL);
  26. minijail_change_uid(jail.get(), AID_SHELL);
  27. // minijail_enter() will abort if any priv-dropping step fails.
  28. minijail_enter(jail.get());
  29. D("Local port disabled");
  30. } else {
  31. // minijail_enter() will abort if any priv-dropping step fails.
  32. minijail_enter(jail.get());
  33. if (root_seclabel != nullptr) {
  34. if (selinux_android_setcon(root_seclabel) < 0) {
  35. LOG(FATAL) << "Could not set SELinux context";
  36. }
  37. }
  38. std::string error;
  39. std::string local_name =
  40. android::base::StringPrintf("tcp:%d", server_port);
  41. if (install_listener(local_name, "*smartsocket*", nullptr, 0,
  42. &error)) {
  43. LOG(FATAL) << "Could not install *smartsocket* listener: "
  44. << error;
  45. }
  46. }
  47. }

    在user-debug版本的系统中(系统属性为ro.debuggable=0),还可以通过adb root命令让adbd恢复root权限(通过修改系统属性service.adb.root=1)。adb作用不用多说,查看他的help即可:

  1. C:\Users\Administrator\Desktop\platform-tools>adb.exe --help
  2. Android Debug Bridge version 1.0.40
  3. Version 4986621
  4. Installed as C:\Users\Administrator\Desktop\platform-tools\adb.exe
  5. global options:
  6. -a listen on all network interfaces, not just localhost
  7. -d use USB device (error if multiple devices connected)
  8. -e use TCP/IP device (error if multiple TCP/IP devices available)
  9. -s SERIAL use device with given serial (overrides $ANDROID_SERIAL)
  10. -t ID use device with given transport id
  11. -H name of adb server host [default=localhost]
  12. -P port of adb server [default=5037]
  13. -L SOCKET listen on given socket for adb server [default=tcp:localhost:5037]
  14. general commands:
  15. devices [-l] list connected devices (-l for long output)
  16. help show this help message
  17. version show version num
  18. networking:
  19. connect HOST[:PORT] connect to a device via TCP/IP [default port=5555]
  20. disconnect [HOST[:PORT]]
  21. disconnect from given TCP/IP device [default port=5555], or all
  22. forward --list list all forward socket connections
  23. forward [--no-rebind] LOCAL REMOTE
  24. forward socket connection using:
  25. tcp:<port> (<local> may be "tcp:0" to pick any open port)
  26. localabstract:<unix domain socket name>
  27. localreserved:<unix domain socket name>
  28. localfilesystem:<unix domain socket name>
  29. dev:<character device name>
  30. jdwp:<process pid> (remote only)
  31. forward --remove LOCAL remove specific forward socket connection
  32. forward --remove-all remove all forward socket connections
  33. ppp TTY [PARAMETER...] run PPP over USB
  34. reverse --list list all reverse socket connections from device
  35. reverse [--no-rebind] REMOTE LOCAL
  36. reverse socket connection using:
  37. tcp:<port> (<remote> may be "tcp:0" to pick any open port)
  38. localabstract:<unix domain socket name>
  39. localreserved:<unix domain socket name>
  40. localfilesystem:<unix domain socket name>
  41. reverse --remove REMOTE remove specific reverse socket connection
  42. reverse --remove-all remove all reverse socket connections from device
  43. file transfer:
  44. push [--sync] LOCAL... REMOTE
  45. copy local files/directories to device
  46. --sync: only push files that are newer on the host than the device
  47. pull [-a] REMOTE... LOCAL
  48. copy files/dirs from device
  49. -a: preserve file timestamp and mode
  50. sync [all|data|odm|oem|product|system|vendor]
  51. sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)
  52. -l: list but don't copy
  53. shell:
  54. shell [-e ESCAPE] [-n] [-Tt] [-x] [COMMAND...]
  55. run remote shell command (interactive shell if no command given)
  56. -e: choose escape character, or "none"; default '~'
  57. -n: don't read from stdin
  58. -T: disable PTY allocation
  59. -t: force PTY allocation
  60. -x: disable remote exit codes and stdout/stderr separation
  61. emu COMMAND run emulator console command
  62. app installation:
  63. install [-lrtsdg] [--instant] PACKAGE
  64. install-multiple [-lrtsdpg] [--instant] PACKAGE...
  65. push package(s) to the device and install them
  66. -l: forward lock application
  67. -r: replace existing application
  68. -t: allow test packages
  69. -s: install application on sdcard
  70. -d: allow version code downgrade (debuggable packages only)
  71. -p: partial application install (install-multiple only)
  72. -g: grant all runtime permissions
  73. --instant: cause the app to be installed as an ephemeral install app
  74. uninstall [-k] PACKAGE
  75. remove this app package from the device
  76. '-k': keep the data and cache directories
  77. backup/restore:
  78. to show usage run "adb shell bu help"
  79. debugging:
  80. bugreport [PATH]
  81. write bugreport to given PATH [default=bugreport.zip];
  82. if PATH is a directory, the bug report is saved in that directory.
  83. devices that don't support zipped bug reports output to stdout.
  84. jdwp list pids of processes hosting a JDWP transport
  85. logcat show device log (logcat --help for more)
  86. security:
  87. disable-verity disable dm-verity checking on userdebug builds
  88. enable-verity re-enable dm-verity checking on userdebug builds
  89. keygen FILE
  90. generate adb public/private key; private key stored in FILE,
  91. public key stored in FILE.pub (existing files overwritten)
  92. scripting:
  93. wait-for[-TRANSPORT]-STATE
  94. wait for device to be in the given state
  95. State: device, recovery, sideload, or bootloader
  96. Transport: usb, local, or any [default=any]
  97. get-state print offline | bootloader | device
  98. get-serialno print <serial-number>
  99. get-devpath print <device-path>
  100. remount remount partitions read-write
  101. reboot [bootloader|recovery|sideload|sideload-auto-reboot]
  102. reboot the device; defaults to booting system image but
  103. supports bootloader and recovery too. sideload reboots
  104. into recovery and automatically starts sideload mode,
  105. sideload-auto-reboot is the same but reboots after sideloading.
  106. sideload OTAPACKAGE sideload the given full OTA package
  107. root restart adbd with root permissions
  108. unroot restart adbd without root permissions
  109. usb restart adb server listening on USB
  110. tcpip PORT restart adb server listening on TCP on PORT
  111. internal debugging:
  112. start-server ensure that there is a server running
  113. kill-server kill the server if it is running
  114. reconnect kick connection from host side to force reconnect
  115. reconnect device kick connection from device side to force reconnect
  116. reconnect offline reset offline/unauthorized devices to force reconnect
  117. environment variables:
  118. $ADB_TRACE
  119. comma-separated list of debug info to log:
  120. all,adb,sockets,packets,rwx,usb,sync,sysdeps,transport,jdwp
  121. $ADB_VENDOR_KEYS colon-separated list of keys (files or directories)
  122. $ANDROID_SERIAL serial number to connect to (see -s)
  123. $ANDROID_LOG_TAGS tags to be used by logcat (see logcat --help)

2 ADB的安全认证

    由于ADB这个接口具有功能非常强大的调试和跟踪功能,尽管它是以shell这个uid的身份运行,但由于shell这个uid是好几个组(log、graphic等)的成员,这也使得它具有很强的能力。使用ADB可以访问到用户的个人数据,也能把任意APP、Native层可执行文件上传到设备中。因此,在Android 4.3 以后的Android系统中引入了公钥认证机制(前提是ro.adb.secure=1时),把ADB的安全性进一步提升。

    AUTH消息将作为对OPEN消息的响应,发送到电脑端,要求在其执行任何命令之前,先完成认证。AUTH消息的参数总是一个TOKEN,它是由移动设备中的随机数发生器(/dev/urandom)生成的一个大小为20个字节的随机数数组。移动设备端将等待电脑端用自己的私钥(该私钥应该己经生成,并存放在$HOME/.android/adbkey这个文件中)对这个TOKEN 进行签名,然后回复一个AUTH SIGNATURE消息,把用私钥签名过的随机数数组放在这个消息里返回给移动设备端。如果移动设备知道相应的公钥,那么验证就能继续,而且如过验证通过了,该会话就会切换到online状态上去。

    因为所有这一切都依赖于公钥,这就产生了一个先有鸡还是先有蛋的问题:怎么让移动端事先就知道这个公钥,并将其用于验证呢?解决方案是允许电脑端响应一个AUTHRSAPUBLICKEY消息。因为此时这个公钥是不可信的,ADB将把这个公钥通过/dev/socket/adbd这个UDS传递给system_server(特别是由com.android.server.usb.UsbDeviceManager启动的UsbDebuggingManager ),然后,system_server将会弹出一个对话框(com.android.server.usb.UsbDebuggingActivity),要求用户确认该公钥的指纹(MD5 Hash)。如果用户选择信任该公钥,这个公钥就会被添加到adb的key store(位于/data/misc/adb/adb_key)中去。作为厂商的话可以重新编译adbd,删掉这一功能(相关代码位于adb_auth_client.c中的adb_auth_confirm_key()函数中),所在源码目录:~/LineageOS/system/core/adb/adb_auth_client.cpp

  1. void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
  2. {
  3. char msg[MAX_PAYLOAD_V1];
  4. int ret;
  5. if (!usb_transport) {
  6. usb_transport = t;
  7. t->AddDisconnect(&usb_disconnect);
  8. }
  9. if (framework_fd < 0) {
  10. D("Client not connected");
  11. needs_retry = true;
  12. return;
  13. }
  14. if (key[len - 1] != '\0') {
  15. D("Key must be a null-terminated string");
  16. return;
  17. }
  18. ret = snprintf(msg, sizeof(msg), "PK%s", key);
  19. if (ret >= (signed)sizeof(msg)) {
  20. D("Key too long. ret=%d", ret);
  21. return;
  22. }
  23. D("Sending '%s'", msg);
  24. ret = unix_write(framework_fd, msg, ret);
  25. if (ret < 0) {
  26. D("Failed to write PK, errno=%d", errno);
  27. return;
  28. }
  29. }

    输入dumpsys usb命令,你就能看到当前的USB调试状态以及当前使用的adb_keys,如下图所示:

        

转载于:https://my.oschina.net/XiaoMaPedro/blog/3061030

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/336269
推荐阅读
相关标签
  

闽ICP备14008679号