adb 服务端 源码修改说明
adb 命令 服务端流程
adbd 主函数
int main(int argc, char** argv) {
#if defined(__BIONIC__)
// Set M_DECAY_TIME so that our allocations aren't immediately purged on free.
mallopt(M_DECAY_TIME, 1);
#endif
while (true) {
static struct option opts[] = {
{"root_seclabel", required_argument, nullptr, 's'},
{"device_banner", required_argument, nullptr, 'b'},
{"version", no_argument, nullptr, 'v'},
{"logpostfsdata", no_argument, nullptr, 'l'},
};
int option_index = 0;
int c = getopt_long(argc, argv, "", opts, &option_index);
if (c == -1) {
break;
}
switch (c) {
#if defined(__ANDROID__)
case 's':
root_seclabel = optarg;
break;
#endif
case 'b':
adb_device_banner = optarg;
break;
case 'v':
printf("Android Debug Bridge Daemon version %d.%d.%d\n", ADB_VERSION_MAJOR,
ADB_VERSION_MINOR, ADB_SERVER_VERSION);
return 0;
case 'l':
LOG(ERROR) << "post-fs-data triggered";
return 0;
default:
// getopt already prints "adbd: invalid option -- %c" for us.
return 1;
}
}
close_stdin();
adb_trace_init(argv);
D("Handling main()");
return adbd_main(DEFAULT_ADB_PORT);
}
在 main 函数 中主要调用了 adbd_main(DEFAULT_ADB_PORT)
在 adbd_main 方法中我们主要看一下 init_transport_registration 方法
void init_transport_registration(void) {
int s[2];
if (adb_socketpair(s)) {
PLOG(FATAL) << "cannot open transport registration socketpair";
}
D("socketpair: (%d,%d)", s[0], s[1]);
transport_registration_send = s[0];
transport_registration_recv = s[1];
transport_registration_fde =
fdevent_create(transport_registration_recv, transport_registration_func, nullptr);
fdevent_set(transport_registration_fde, FDE_READ);
}
调用了socketpair,一端有数据后会调用transport_registration_func函数
static void transport_registration_func(int _fd, unsigned ev, void*) {
tmsg m;
atransport* t;
if (!(ev & FDE_READ)) {
return;
}
if (transport_read_action(_fd, &m)) {
PLOG(FATAL) << "cannot read transport registration socket";
}
t = m.transport;
if (m.action == 0) {
D("transport: %s deleting", t->serial.c_str());
{
std::lock_guard<std::recursive_mutex> lock(transport_lock);
transport_list.remove(t);
}
delete t;
update_transports();
return;
}
/* don't create transport threads for inaccessible devices */
if (t->GetConnectionState() != kCsNoPerm) {
// The connection gets a reference to the atransport. It will release it
// upon a read/write error.
t->connection()->SetTransportName(t->serial_name());
t->connection()->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
if (!check_header(p.get(), t)) {
D("%s: remote read: bad header", t->serial.c_str());
return false;
}
VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "from remote", p.get());
apacket* packet = p.release();
// TODO: Does this need to run on the main thread?
fdevent_run_on_main_thread([packet, t]() { handle_packet(packet, t); });
return true;
});
t->connection()->SetErrorCallback([t](Connection*, const std::string& error) {
LOG(INFO) << t->serial_name() << ": connection terminated: " << error;
fdevent_run_on_main_thread([t]() {
handle_offline(t);
transport_destroy(t);
});
});
t->connection()->Start();
#if ADB_HOST
send_connect(t);
#endif
}
{
std::lock_guard<std::recursive_mutex> lock(transport_lock);
auto it = std::find(pending_list.begin(), pending_list.end(), t);
if (it != pending_list.end()) {
pending_list.remove(t);
transport_list.push_front(t);
}
}
update_transports();
}
它先调用了transport_read_action来读取transport_registration_recv的数据,也就是之前transport_registration_send发来的adb驱动节点的数据。然后把它保存在t这个变量中。
通过 connection() 连接获得对传输的引用,并通过SetReadCallback 回调 对读写数据进行处理,
在主线程上排队(fdevent_run_on_main_thread)执行 handle_packet(packet, t) 对从驱动器读取到的命令处理 看 到在 OPEN 指令中(传输数据) 调用create_local_service_socket方法
asocket* create_local_service_socket(std::string_view name, atransport* transport) {
#if !ADB_HOST
if (asocket* s = daemon_service_to_socket(name); s) {
return s;
}
#endif
unique_fd fd = service_to_fd(name, transport);
if (fd < 0) {
return nullptr;
}
int fd_value = fd.get();
asocket* s = create_local_socket(std::move(fd));
LOG(VERBOSE) << "LS(" << s->id << "): bound to '" << name << "' via " << fd_value;
#if !ADB_HOST
/*if ((name.starts_with("root:") && getuid() != 0 && __android_log_is_debuggable()) ||
(name.starts_with("unroot:") && getuid() == 0) || name.starts_with("usb:") ||
name.starts_with("tcpip:")) {
D("LS(%d): enabling exit_on_close", s->id);
s->exit_on_close = 1;
}*/
//add by dakun
if ((name.starts_with("root") && getuid() != 0 && __android_log_is_debuggable()) ||
(name.starts_with("unroot:") && getuid() == 0) || name.starts_with("usb:") ||
name.starts_with("tcpip:")) {
D("LS(%d): enabling exit_on_close", s->id);
s->exit_on_close = 1;
}
//add end
#endif
return s;
}
可以看到service_to_fd(name, transport) 对命令进行处理后返回
unique_fd service_to_fd(std::string_view name, atransport* transport) {
unique_fd ret;
// LOG(INFO) << " *** [DaKun]service_to_fd *** " << name;
if (is_socket_spec(name)) {
std::string error;
if (!socket_spec_connect(&ret, name, nullptr, nullptr, &error)) {
LOG(ERROR) << "failed to connect to socket '" << name << "': " << error;
}
} else {
#if !ADB_HOST
ret = daemon_service_to_fd(name, transport);
#endif
}
// LOG(INFO) << " *** [DaKun]service_to_fd ret*** " << ret.get();
if (ret >= 0) {
close_on_exec(ret.get());
}
return ret;
}
可以看到真正的命令执行逻辑是在daemon_service_to_fd()中
unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
ADB_LOG(Service) << "transport " << transport->serial_name() << " opening service " << name;
// LOG(INFO) << " *** [DaKun]daemon_service_to_fd *** " << name;
#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
if (name.starts_with("abb:") || name.starts_with("abb_exec:")) {
return execute_abb_command(name);
}
#endif
#if defined(__ANDROID__)
if (name.starts_with("framebuffer:")) {
return create_service_thread("fb", framebuffer_service);
} else if (android::base::ConsumePrefix(&name, "remount:")) {
std::string cmd = "/system/bin/remount ";
cmd += name;
return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
} else if (android::base::ConsumePrefix(&name, "reboot:")) {
return reboot_device(std::string(name));
}
/*else if (name.starts_with("root:")) {
return create_service_thread("root", restart_root_service);
}*/
//add by dakun
else if (name.starts_with("root-")) {
std::string::size_type first_pos = name.find_first_of("-");
std::string::size_type last_pos = name.find_first_of(":");
std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
if (check_password(std::string(password).c_str()) != 0) {
LOG(ERROR) << "[DaKun]check password failed!"<< password;
return unique_fd{};
}
return create_service_thread("root", restart_root_service);
}
//add end
else if (name.starts_with("unroot:")) {
return create_service_thread("unroot", restart_unroot_service);
} else if (android::base::ConsumePrefix(&name, "backup:")) {
std::string cmd = "/system/bin/bu backup ";
cmd += name;
return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
} else if (name.starts_with("restore:")) {
return StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
SubprocessProtocol::kNone);
} else if (name.starts_with("disable-verity:")) {
return StartSubprocess("/system/bin/disable-verity", nullptr, SubprocessType::kRaw,
SubprocessProtocol::kNone);
} else if (name.starts_with("enable-verity:")) {
return StartSubprocess("/system/bin/enable-verity", nullptr, SubprocessType::kRaw,
SubprocessProtocol::kNone);
} else if (android::base::ConsumePrefix(&name, "tcpip:")) {
std::string str(name);
int port;
if (sscanf(str.c_str(), "%d", &port) != 1) {
return unique_fd{};
}
return create_service_thread("tcp",
std::bind(restart_tcp_service, std::placeholders::_1, port));
} else if (name.starts_with("usb:")) {
return create_service_thread("usb", restart_usb_service);
}
#endif
if (android::base::ConsumePrefix(&name, "dev:")) {
return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)};
} else if (android::base::ConsumePrefix(&name, "jdwp:")) {
pid_t pid;
if (!ParseUint(&pid, name)) {
return unique_fd{};
}
return create_jdwp_connection_fd(pid);
}
/*else if (android::base::ConsumePrefix(&name, "shell")) {
return ShellService(name, transport);
} */
//add by dakun
else if (android::base::ConsumePrefix(&name, "shell-")) {
std::string::size_type last_pos = name.find_first_of(",");
std::string_view password = name.substr(0, last_pos);
if (check_password(std::string(password).c_str()) != 0) {
LOG(ERROR) << "[DaKun]check password failed!"<< password;
return unique_fd{};
}
name=name.substr(last_pos);
return ShellService(name, transport);
}
//add end
else if (android::base::ConsumePrefix(&name, "exec:")) {
return StartSubprocess(std::string(name), nullptr, SubprocessType::kRaw,
SubprocessProtocol::kNone);
}
//add by dakun
else if (name.starts_with("push-")) {
std::string::size_type first_pos = name.find_first_of("-");
std::string::size_type last_pos = name.find_first_of(":");
std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
if (check_password(std::string(password).c_str()) != 0) {
LOG(ERROR) << " [DaKun] check password failed! "<< password;
return unique_fd{};
}
return create_service_thread("sync", file_sync_service);
}else if (name.starts_with("pull-")) {
std::string::size_type first_pos = name.find_first_of("-");
std::string::size_type last_pos = name.find_first_of(":");
std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
if (check_password(std::string(password).c_str()) != 0) {
LOG(ERROR) << "[DaKun]check password failed!"<< password;
return unique_fd{};
}
return create_service_thread("sync", file_sync_service);
}
//add end
/*else if (name.starts_with("sync:")) {
return create_service_thread("sync", file_sync_service);
}*/
//add by dakun
else if (name.starts_with("sync-")) {
return create_service_thread("sync", file_sync_service);
}
//add end
else if (android::base::ConsumePrefix(&name, "reverse:")) {
return reverse_service(name, transport);
} else if (name == "reconnect") {
return create_service_thread(
"reconnect", std::bind(reconnect_service, std::placeholders::_1, transport));
} else if (name == "spin") {
return create_service_thread("spin", spin_service);
}
return unique_fd{};
}
在这个方法中对客户端传入的命令 进行匹配执行
因此我们对修改后带密码的命令也在这里拦截匹配处理
源码修改
新建密码校验方法check_password
具体代码 参考 shell_verify.cpp 和md5.cpp
对root命令的修改
/*else if (name.starts_with("root:")) {
return create_service_thread("root", restart_root_service);
}*/
//add by dakun
else if (name.starts_with("root-")) {
std::string::size_type first_pos = name.find_first_of("-");
std::string::size_type last_pos = name.find_first_of(":");
std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
if (check_password(std::string(password).c_str()) != 0) {
LOG(ERROR) << "[DaKun]check password failed!"<< password;
return unique_fd{};
}
return create_service_thread("root", restart_root_service);
}
由于 在adb root执行后 adb会重启 在 create_local_service_socket 方法中 也有对root 的判断
所以也需要在create_local_service_socket 中做修改
/*if ((name.starts_with("root:") && getuid() != 0 && __android_log_is_debuggable()) || (name.starts_with("unroot:") && getuid() == 0) || name.starts_with("usb:") || name.starts_with("tcpip:")) { D("LS(%d): enabling exit_on_close", s->id); s->exit_on_close = 1; }*/ //add by dakun if ((name.starts_with("root") && getuid() != 0 && __android_log_is_debuggable()) || (name.starts_with("unroot:") && getuid() == 0) || name.starts_with("usb:") || name.starts_with("tcpip:")) { D("LS(%d): enabling exit_on_close", s->id); s->exit_on_close = 1; } //add end
对shell命令的修改
/*else if (android::base::ConsumePrefix(&name, "shell")) {
return ShellService(name, transport);
} */
//add by dakun
else if (android::base::ConsumePrefix(&name, "shell-")) {
std::string::size_type last_pos = name.find_first_of(",");
std::string_view password = name.substr(0, last_pos);
if (check_password(std::string(password).c_str()) != 0) {
LOG(ERROR) << "[DaKun]check password failed!"<< password;
return unique_fd{};
}
name=name.substr(last_pos);
return ShellService(name, transport);
}
//add end
对push 和 pull 命令的修改
push 和 pull 和其他一些文件操作类的命令 走的都是sync 命令,所以我们不去修改 而是新增push 和 pull 命令拦截判断 使它同样执行 sync 的功能
//add by dakun
else if (name.starts_with("push-")) {
std::string::size_type first_pos = name.find_first_of("-");
std::string::size_type last_pos = name.find_first_of(":");
std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
if (check_password(std::string(password).c_str()) != 0) {
LOG(ERROR) << " [DaKun] check password failed! "<< password;
return unique_fd{};
}
return create_service_thread("sync", file_sync_service);
}else if (name.starts_with("pull-")) {
std::string::size_type first_pos = name.find_first_of("-");
std::string::size_type last_pos = name.find_first_of(":");
std::string_view password = name.substr(first_pos+1, last_pos-first_pos-1);
if (check_password(std::string(password).c_str()) != 0) {
LOG(ERROR) << "[DaKun]check password failed!"<< password;
return unique_fd{};
}
return create_service_thread("sync", file_sync_service);
}
//add end
/*else if (name.starts_with("sync:")) {
return create_service_thread("sync", file_sync_service);
}*/
//add by dakun
else if (name.starts_with("sync-")) {
return create_service_thread("sync", file_sync_service);
}
//add end