在之前博客中我们分析了很多adbd的代码,也分析了adb root的代码流程,这篇博客我们说下adb root的一个bug。
我们先来回顾下adbd处理adb root的代码:
void restart_root_service(int fd, void *cookie) { if (getuid() == 0) { WriteFdExactly(fd, "adbd is already running as root\n"); adb_close(fd); } else { char value[PROPERTY_VALUE_MAX]; property_get("ro.debuggable", value, ""); if (strcmp(value, "1") != 0) { WriteFdExactly(fd, "adbd cannot run as root in production builds\n"); adb_close(fd); return; } property_set("service.adb.root", "1"); WriteFdExactly(fd, "restarting adbd as root\n"); adb_close(fd); } }
初看没啥问题,我们再来结合init.rc来看。
on property:service.adb.root=1 write /sys/class/android_usb/android0/enable 0 restart adbd write /sys/class/android_usb/android0/enable 1
adb root后adbd会往service.adb.root写1,然后init会根据这个属性,把上面init.rc中的两个节点先写0,再写1。什么意思呢,就是usb驱动,使能开关先关掉,再开。而这中间还要重启adbd。
正常的话,我们之前也分析过了,adbd重启后,发现property:service.adb.root=1,于是就不会给adbd降级为shell,还是为root。
但是如何有问题的话,首先adbd写这个属性,先把usb驱动的使能开关关了,试问这个时候adbd往adb驱动写的数据只有到一半怎么办?这个时候很有可能和pc的通信就有问题。
结合实际,在我们的手机上没有问题,但是类似"restarting adbd as root“的字眼经常在pc的cmd命令上显示不出来,就是因为usb使能关太早了,导致adbd还没发送完数据。
最近调试adb root就直接驱动那边出问题。
归根到底就是一个时序的问题,解决方案可以在驱动关闭usb使能的时候,延时一段时间,就可以解决了。
但是归根到底还是google的一个bug,可以在adbd中等数据完全通信完了再去写service.adb.root为1,这样这个问题也就完全解决了,而不用去做规避。