1. 程式人生 > >[日更-2019.5.18] Android 系統內的守護程序(一)--core類中的服務 : adbd

[日更-2019.5.18] Android 系統內的守護程序(一)--core類中的服務 : adbd

宣告

  • 其實很好奇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中的啟動配置為:

# adbd is controlled via property triggers in init.<platform>.usb.rc
service adbd /sbin/adbd --root_seclabel=u:r:su:s0
    class core
    socket adbd stream 660 system system
    disabled
    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

static void drop_privileges(int server_port) {
    std::unique_ptr<minijail, void (*)(minijail*)> jail(minijail_new(),
                                                        &minijail_destroy);

    // Add extra groups:
    // AID_ADB to access the USB driver
    // AID_LOG to read system logs (adb logcat)
    // AID_INPUT to diagnose input issues (getevent)
    // AID_INET to diagnose network issues (ping)
    // AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
    // AID_SDCARD_R to allow reading from the SD card
    // AID_SDCARD_RW to allow writing to the SD card
    // AID_NET_BW_STATS to read out qtaguid statistics
    // AID_READPROC for reading /proc entries across UID boundaries
    gid_t groups[] = {AID_ADB,      AID_LOG,       AID_INPUT,
                      AID_INET,     AID_NET_BT,    AID_NET_BT_ADMIN,
                      AID_SDCARD_R, AID_SDCARD_RW, AID_NET_BW_STATS,
                      AID_READPROC};
    minijail_set_supplementary_gids(jail.get(),
                                    sizeof(groups) / sizeof(groups[0]),
                                    groups);

    // Don't listen on a port (default 5037) if running in secure mode.
    // Don't run as root if running in secure mode.
    if (should_drop_privileges()) {
        drop_capabilities_bounding_set_if_needed();

        minijail_change_gid(jail.get(), AID_SHELL);
        minijail_change_uid(jail.get(), AID_SHELL);
        // minijail_enter() will abort if any priv-dropping step fails.
        minijail_enter(jail.get());

        D("Local port disabled");
    } else {
        // minijail_enter() will abort if any priv-dropping step fails.
        minijail_enter(jail.get());

        if (root_seclabel != nullptr) {
            if (selinux_android_setcon(root_seclabel) < 0) {
                LOG(FATAL) << "Could not set SELinux context";
            }
        }
        std::string error;
        std::string local_name =
            android::base::StringPrintf("tcp:%d", server_port);
        if (install_listener(local_name, "*smartsocket*", nullptr, 0,
                             &error)) {
            LOG(FATAL) << "Could not install *smartsocket* listener: "
                       << error;
        }
    }
}

    在user-debug版本的系統中(系統屬性為ro.debuggable=0),還可以通過adb root命令讓adbd恢復root許可權(通過修改系統屬性service.adb.root=1)。adb作用不用多說,檢視他的help即可:

C:\Users\Administrator\Desktop\platform-tools>adb.exe --help
Android Debug Bridge version 1.0.40
Version 4986621
Installed as C:\Users\Administrator\Desktop\platform-tools\adb.exe

global options:
 -a         listen on all network interfaces, not just localhost
 -d         use USB device (error if multiple devices connected)
 -e         use TCP/IP device (error if multiple TCP/IP devices available)
 -s SERIAL  use device with given serial (overrides $ANDROID_SERIAL)
 -t ID      use device with given transport id
 -H         name of adb server host [default=localhost]
 -P         port of adb server [default=5037]
 -L SOCKET  listen on given socket for adb server [default=tcp:localhost:5037]

general commands:
 devices [-l]             list connected devices (-l for long output)
 help                     show this help message
 version                  show version num

networking:
 connect HOST[:PORT]      connect to a device via TCP/IP [default port=5555]
 disconnect [HOST[:PORT]]
     disconnect from given TCP/IP device [default port=5555], or all
 forward --list           list all forward socket connections
 forward [--no-rebind] LOCAL REMOTE
     forward socket connection using:
       tcp:<port> (<local> may be "tcp:0" to pick any open port)
       localabstract:<unix domain socket name>
       localreserved:<unix domain socket name>
       localfilesystem:<unix domain socket name>
       dev:<character device name>
       jdwp:<process pid> (remote only)
 forward --remove LOCAL   remove specific forward socket connection
 forward --remove-all     remove all forward socket connections
 ppp TTY [PARAMETER...]   run PPP over USB
 reverse --list           list all reverse socket connections from device
 reverse [--no-rebind] REMOTE LOCAL
     reverse socket connection using:
       tcp:<port> (<remote> may be "tcp:0" to pick any open port)
       localabstract:<unix domain socket name>
       localreserved:<unix domain socket name>
       localfilesystem:<unix domain socket name>
 reverse --remove REMOTE  remove specific reverse socket connection
 reverse --remove-all     remove all reverse socket connections from device

file transfer:
 push [--sync] LOCAL... REMOTE
     copy local files/directories to device
     --sync: only push files that are newer on the host than the device
 pull [-a] REMOTE... LOCAL
     copy files/dirs from device
     -a: preserve file timestamp and mode
 sync [all|data|odm|oem|product|system|vendor]
     sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)
     -l: list but don't copy

shell:
 shell [-e ESCAPE] [-n] [-Tt] [-x] [COMMAND...]
     run remote shell command (interactive shell if no command given)
     -e: choose escape character, or "none"; default '~'
     -n: don't read from stdin
     -T: disable PTY allocation
     -t: force PTY allocation
     -x: disable remote exit codes and stdout/stderr separation
 emu COMMAND              run emulator console command

app installation:
 install [-lrtsdg] [--instant] PACKAGE
 install-multiple [-lrtsdpg] [--instant] PACKAGE...
     push package(s) to the device and install them
     -l: forward lock application
     -r: replace existing application
     -t: allow test packages
     -s: install application on sdcard
     -d: allow version code downgrade (debuggable packages only)
     -p: partial application install (install-multiple only)
     -g: grant all runtime permissions
     --instant: cause the app to be installed as an ephemeral install app
 uninstall [-k] PACKAGE
     remove this app package from the device
     '-k': keep the data and cache directories

backup/restore:
   to show usage run "adb shell bu help"

debugging:
 bugreport [PATH]
     write bugreport to given PATH [default=bugreport.zip];
     if PATH is a directory, the bug report is saved in that directory.
     devices that don't support zipped bug reports output to stdout.
 jdwp                     list pids of processes hosting a JDWP transport
 logcat                   show device log (logcat --help for more)

security:
 disable-verity           disable dm-verity checking on userdebug builds
 enable-verity            re-enable dm-verity checking on userdebug builds
 keygen FILE
     generate adb public/private key; private key stored in FILE,
     public key stored in FILE.pub (existing files overwritten)

scripting:
 wait-for[-TRANSPORT]-STATE
     wait for device to be in the given state
     State: device, recovery, sideload, or bootloader
     Transport: usb, local, or any [default=any]
 get-state                print offline | bootloader | device
 get-serialno             print <serial-number>
 get-devpath              print <device-path>
 remount                  remount partitions read-write
 reboot [bootloader|recovery|sideload|sideload-auto-reboot]
     reboot the device; defaults to booting system image but
     supports bootloader and recovery too. sideload reboots
     into recovery and automatically starts sideload mode,
     sideload-auto-reboot is the same but reboots after sideloading.
 sideload OTAPACKAGE      sideload the given full OTA package
 root                     restart adbd with root permissions
 unroot                   restart adbd without root permissions
 usb                      restart adb server listening on USB
 tcpip PORT               restart adb server listening on TCP on PORT

internal debugging:
 start-server             ensure that there is a server running
 kill-server              kill the server if it is running
 reconnect                kick connection from host side to force reconnect
 reconnect device         kick connection from device side to force reconnect
 reconnect offline        reset offline/unauthorized devices to force reconnect

environment variables:
 $ADB_TRACE
     comma-separated list of debug info to log:
     all,adb,sockets,packets,rwx,usb,sync,sysdeps,transport,jdwp
 $ADB_VENDOR_KEYS         colon-separated list of keys (files or directories)
 $ANDROID_SERIAL          serial number to connect to (see -s)
 $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

void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
{
    char msg[MAX_PAYLOAD_V1];
    int ret;

    if (!usb_transport) {
        usb_transport = t;
        t->AddDisconnect(&usb_disconnect);
    }

    if (framework_fd < 0) {
        D("Client not connected");
        needs_retry = true;
        return;
    }

    if (key[len - 1] != '\0') {
        D("Key must be a null-terminated string");
        return;
    }

    ret = snprintf(msg, sizeof(msg), "PK%s", key);
    if (ret >= (signed)sizeof(msg)) {
        D("Key too long. ret=%d", ret);
        return;
    }
    D("Sending '%s'", msg);

    ret = unix_write(framework_fd, msg, ret);
    if (ret < 0) {
        D("Failed to write PK, errno=%d", errno);
        return;
    }
}

    輸入dumpsys usb命令,你就能看到當前的USB除錯狀態以及當前使用的adb_keys,如下圖所示:

        

相關推薦

[-2019.5.18] Android 系統守護程序--core服務 : adbd

宣告 其實很好奇Android系統中的一些關鍵守護程序服務的作用; 暫且大概分析下它們的作用,這樣有助於理解整個系統的工作過程;

[-2019.5.20] Android 系統守護程序--core服務 : lmkd

宣告 其實很好奇Android系統中的一些關鍵守護程序服務的作用; 暫且大概分析下它們的作用,這樣有助於理解整個系統的工作過程;

[-2019.5.21] Android 系統的分割槽和檔案系統--Android分割槽的大概框架

宣告 其實我在剛開始接觸Android時給手機刷機,很好奇Android的刷機包裡面怎麼這麼多img檔案?而且每個img要刷入對

操作系統 存管理

目的 工作 事先 -m 要求 load enter views 利用 1. 內存管理方法 內存管理主要包含虛地址、地址變換、內存分配和回收、內存

【安卓本卓】Android系統原始碼篇之原始碼獲取、原始碼目錄結構及原始碼閱讀工具簡介

前言 古人常說,“熟讀唐詩三百首,不會作詩也會吟”,說明了大量閱讀詩歌名篇對學習作詩有非常大的幫助。做開發也一樣,Android原始碼是全世界最優秀的Android工程師編寫的程式碼,也是Android開發中絕對的權威所在。Android系統開源,且佔據了當今手機系統世界的絕大部分江山,各大手機廠商要做手機系

Android-UI佈局---RecyclerView學習在介面卡自定義長按和點選事件

該系列文章  如果想全方面學習,建議參考這個大牛的文章,寫的真可以。 地址:http://blog.csdn.net/lmj623565791/article/details/45059587 因為RecyclerView沒有點選、長按事件,需要自己寫 實現的方式比較多,

[-2019.5.8、9] Android 系統的安全性分析(二)--Dalvik/ART層面上的安全措施

宣告 最近工作上涉及到對Android系統安全性的改造,在改造之前先分析整理下目前Android系統自身的安全性; 參考了一些文

[-2019.5.10、11、12] Android 系統的安全性分析(三)--Linux層面上的安全措施

宣告 最近工作上涉及到對Android系統安全性的改造,在改造之前先分析整理下目前Android系統自身的安全性; 參考了一些文

[-2019.5.15、16] Android 系統的安全性分析(四)--儲存安全措施

宣告 最近工作上涉及到對Android系統安全性的改造,在改造之前先分析整理下目前Android系統自身的安全性; 參考了一些文

[-2019.5.22、23] Android 系統的分割槽和檔案系統--Android 檔案系統的檔案

宣告 Android系統中有很多分割槽,每個分割槽內的檔案系統一般都不同的,使用ADB進入系統/目錄下可發現掛載這很多的目錄,不

[-2019.5.24、25、26] Android系統的Binder通訊機制分析--servicemanager

宣告 其實對於Android系統Binder通訊的機制早就有分析的想法,記得去年6、7月份Mr.Deng離職期間約定一起對其進行

[-2019.5.5] 搭建SS伺服器

1 前提 在vultr註冊站好,建立伺服器。 2 安裝shadowsocks Debian/Ubuntu apt-get in

Android存優化DVM和ART原理初探

java虛擬機 劃分 cimage beef 靜態 由於 jar blank 查找 要學習Android的內存優化,首先要了解Java虛擬機,此前我用了多篇文章來介紹Java虛擬機的知識,就是為了這個系列做鋪墊。在Android開發中我們接觸的是與Java虛擬機類似的Dal

Android存優化Dalvik虛擬機和ART虛擬機對比

參考 -a 會有 font google 都是 http -s 轉換成 1.概述  Android4.4以上開始使用ART虛擬機,在此之前我們一直使用的Dalvik虛擬機,那麽為什麽Google突然換了Android運行的虛擬機呢?答案只有一個:ART虛擬機更優秀。 2.D

【安卓本卓】Android系統原始碼篇之Source Insight

Source Insight(以下簡稱SI) 一、SI簡介        SI是一款面向專案開發的程式編輯器和程式碼瀏覽器,它提供了一個檢視將分散在各個地方的程式碼匯合在一起形成一個虛擬的整體,供開發者方便地閱讀和編輯,如下圖所示。它已經持續維護了10多年了,旨在提

Android 多個應用之間聲音競爭之Android 系統處理音訊焦點AudioFocus

問題發現 最近在專案中發現我們的自己的apk和第三方的媒體apk會出現串音問題。即兩者之間的聲音會重疊在一起。 解決問題 1. 使用多媒體按鍵去控制第三方應用的聲音播放(無效果) 通過觸發媒體的按鈕來操作播放器狀態:KeyEvent.KEYCODE_MEDIA

android 框架之WIFI系統系統架構全面總結

知識就本來就是滾雪球,越滾才越大! 在瞭解WIFI模組的系統架構之前。我心中就有一個疑問,那麼android的系統架構是怎樣的呢。其實現在網路中有很多關於android系統架構的描述和解釋,在這裡我不做詳細的研究了,只是貼張圖重新溫故一下。具體細節還要檢視android原始

Android自定義控制元件 下拉重新整理,上拉分頁載入多(支援ListView, GridView, ScrollView)

        首先說明,這幾篇文章是對一些前輩的成果進行學習後的心得總結。也借這種方式對他們表示謝意。         最近專案中好幾個模組都用到listview和gridview的下拉重新整理,上拉載入更多等功能,而且涉及到圖片的批量下載。水平有限,首先是想到找一些比較

Android 5.0(L) ToolBar(替代ActionBar) 實戰

Android 5.0 SDK 在悄然釋出了,由於更新了Appcombat V7庫,將Google在IO 2014時提到的Material Design的UI介面元素帶了進來。從此,開發者可以建立基於Material Design介面設計的APP了。 誠然,在更新了新版

android 快速開發抽象的使用:使業務邏輯清晰

抽象類的使用:使業務邏輯更清晰 一、abstract修飾符         abstract修飾符可以用於類、方法、屬性、事件和索引指示器(indexer),表示其為抽象成員,抽象方法是沒有方法體的方法。         abstract 不可以和static、virtu