Loading adb/adb.h +1 −1 Original line number Diff line number Diff line Loading @@ -153,7 +153,7 @@ asocket* daemon_service_to_socket(std::string_view name); #endif #if !ADB_HOST unique_fd execute_binder_command(std::string_view command); unique_fd execute_abb_command(std::string_view command); #endif #if !ADB_HOST Loading adb/daemon/abb.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -85,7 +85,19 @@ int main(int argc, char* const argv[]) { break; } unique_fd result = StartCommandInProcess(std::move(data), &execCmd); std::string_view name = data; auto protocol = SubprocessProtocol::kShell; if (name.starts_with("abb:")) { name.remove_prefix(strlen("abb:")); protocol = SubprocessProtocol::kShell; } else if (name.starts_with("abb_exec:")) { name.remove_prefix(strlen("abb_exec:")); protocol = SubprocessProtocol::kNone; } else { LOG(FATAL) << "Unknown command prefix for abb: " << data; } unique_fd result = StartCommandInProcess(std::string(name), &execCmd, protocol); if (android::base::SendFileDescriptors(fd, "", 1, result.get()) != 1) { PLOG(ERROR) << "Failed to send an inprocess fd for command: " << data; break; Loading adb/daemon/abb_service.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -86,6 +86,6 @@ unique_fd AbbProcess::startAbbProcess(unique_fd* error_fd) { } // namespace unique_fd execute_binder_command(std::string_view command) { unique_fd execute_abb_command(std::string_view command) { return abbp->sendCommand(command); } adb/daemon/services.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -244,9 +244,8 @@ asocket* daemon_service_to_socket(std::string_view name) { unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) { #if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__) if (name.starts_with("abb:")) { name.remove_prefix(strlen("abb:")); return execute_binder_command(name); if (name.starts_with("abb:") || name.starts_with("abb_exec:")) { return execute_abb_command(name); } #endif Loading adb/daemon/shell_service.cpp +46 −65 Original line number Diff line number Diff line Loading @@ -170,6 +170,8 @@ class Subprocess { // Opens the file at |pts_name|. int OpenPtyChildFd(const char* pts_name, unique_fd* error_sfd); bool ConnectProtocolEndpoints(std::string* _Nonnull error); static void ThreadHandler(void* userdata); void PassDataStreams(); void WaitForExit(); Loading Loading @@ -383,44 +385,11 @@ bool Subprocess::ForkAndExec(std::string* error) { } D("subprocess parent: exec completed"); if (protocol_ == SubprocessProtocol::kNone) { // No protocol: all streams pass through the stdinout FD and hook // directly into the local socket for raw data transfer. local_socket_sfd_.reset(stdinout_sfd_.release()); } else { // Shell protocol: create another socketpair to intercept data. if (!CreateSocketpair(&protocol_sfd_, &local_socket_sfd_)) { *error = android::base::StringPrintf( "failed to create socketpair to intercept data: %s", strerror(errno)); kill(pid_, SIGKILL); return false; } D("protocol FD = %d", protocol_sfd_.get()); input_ = std::make_unique<ShellProtocol>(protocol_sfd_); output_ = std::make_unique<ShellProtocol>(protocol_sfd_); if (!input_ || !output_) { *error = "failed to allocate shell protocol objects"; if (!ConnectProtocolEndpoints(error)) { kill(pid_, SIGKILL); return false; } // Don't let reads/writes to the subprocess block our thread. This isn't // likely but could happen under unusual circumstances, such as if we // write a ton of data to stdin but the subprocess never reads it and // the pipe fills up. for (int fd : {stdinout_sfd_.get(), stderr_sfd_.get()}) { if (fd >= 0) { if (!set_file_block_mode(fd, false)) { *error = android::base::StringPrintf( "failed to set non-blocking mode for fd %d", fd); kill(pid_, SIGKILL); return false; } } } } D("subprocess parent: completed"); return true; } Loading @@ -429,7 +398,6 @@ bool Subprocess::ExecInProcess(Command command, std::string* _Nonnull error) { unique_fd child_stdinout_sfd, child_stderr_sfd; CHECK(type_ == SubprocessType::kRaw); CHECK(protocol_ == SubprocessProtocol::kShell); __android_log_security_bswrite(SEC_TAG_ADB_SHELL_CMD, command_.c_str()); Loading @@ -448,10 +416,29 @@ bool Subprocess::ExecInProcess(Command command, std::string* _Nonnull error) { D("execinprocess: stdin/stdout FD = %d, stderr FD = %d", stdinout_sfd_.get(), stderr_sfd_.get()); if (!ConnectProtocolEndpoints(error)) { return false; } std::thread([inout_sfd = std::move(child_stdinout_sfd), err_sfd = std::move(child_stderr_sfd), command = std::move(command), args = command_]() { command(args, inout_sfd, inout_sfd, err_sfd); }) .detach(); D("execinprocess: completed"); return true; } bool Subprocess::ConnectProtocolEndpoints(std::string* _Nonnull error) { if (protocol_ == SubprocessProtocol::kNone) { // No protocol: all streams pass through the stdinout FD and hook // directly into the local socket for raw data transfer. local_socket_sfd_.reset(stdinout_sfd_.release()); } else { // Required for shell protocol: create another socketpair to intercept data. if (!CreateSocketpair(&protocol_sfd_, &local_socket_sfd_)) { *error = android::base::StringPrintf("failed to create socketpair to intercept data: %s", strerror(errno)); *error = android::base::StringPrintf( "failed to create socketpair to intercept data: %s", strerror(errno)); return false; } D("protocol FD = %d", protocol_sfd_.get()); Loading @@ -470,19 +457,14 @@ bool Subprocess::ExecInProcess(Command command, std::string* _Nonnull error) { for (int fd : {stdinout_sfd_.get(), stderr_sfd_.get()}) { if (fd >= 0) { if (!set_file_block_mode(fd, false)) { *error = android::base::StringPrintf("failed to set non-blocking mode for fd %d", fd); *error = android::base::StringPrintf( "failed to set non-blocking mode for fd %d", fd); return false; } } } } std::thread([inout_sfd = std::move(child_stdinout_sfd), err_sfd = std::move(child_stderr_sfd), command = std::move(command), args = command_]() { command(args, inout_sfd, inout_sfd, err_sfd); }) .detach(); D("execinprocess: completed"); return true; } Loading Loading @@ -863,12 +845,11 @@ unique_fd StartSubprocess(std::string name, const char* terminal_type, Subproces return local_socket; } unique_fd StartCommandInProcess(std::string name, Command command) { unique_fd StartCommandInProcess(std::string name, Command command, SubprocessProtocol protocol) { LOG(INFO) << "StartCommandInProcess(" << dump_hex(name.data(), name.size()) << ")"; constexpr auto terminal_type = ""; constexpr auto type = SubprocessType::kRaw; constexpr auto protocol = SubprocessProtocol::kShell; constexpr auto make_pty_raw = false; auto subprocess = std::make_unique<Subprocess>(std::move(name), terminal_type, type, protocol, Loading Loading
adb/adb.h +1 −1 Original line number Diff line number Diff line Loading @@ -153,7 +153,7 @@ asocket* daemon_service_to_socket(std::string_view name); #endif #if !ADB_HOST unique_fd execute_binder_command(std::string_view command); unique_fd execute_abb_command(std::string_view command); #endif #if !ADB_HOST Loading
adb/daemon/abb.cpp +13 −1 Original line number Diff line number Diff line Loading @@ -85,7 +85,19 @@ int main(int argc, char* const argv[]) { break; } unique_fd result = StartCommandInProcess(std::move(data), &execCmd); std::string_view name = data; auto protocol = SubprocessProtocol::kShell; if (name.starts_with("abb:")) { name.remove_prefix(strlen("abb:")); protocol = SubprocessProtocol::kShell; } else if (name.starts_with("abb_exec:")) { name.remove_prefix(strlen("abb_exec:")); protocol = SubprocessProtocol::kNone; } else { LOG(FATAL) << "Unknown command prefix for abb: " << data; } unique_fd result = StartCommandInProcess(std::string(name), &execCmd, protocol); if (android::base::SendFileDescriptors(fd, "", 1, result.get()) != 1) { PLOG(ERROR) << "Failed to send an inprocess fd for command: " << data; break; Loading
adb/daemon/abb_service.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -86,6 +86,6 @@ unique_fd AbbProcess::startAbbProcess(unique_fd* error_fd) { } // namespace unique_fd execute_binder_command(std::string_view command) { unique_fd execute_abb_command(std::string_view command) { return abbp->sendCommand(command); }
adb/daemon/services.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -244,9 +244,8 @@ asocket* daemon_service_to_socket(std::string_view name) { unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) { #if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__) if (name.starts_with("abb:")) { name.remove_prefix(strlen("abb:")); return execute_binder_command(name); if (name.starts_with("abb:") || name.starts_with("abb_exec:")) { return execute_abb_command(name); } #endif Loading
adb/daemon/shell_service.cpp +46 −65 Original line number Diff line number Diff line Loading @@ -170,6 +170,8 @@ class Subprocess { // Opens the file at |pts_name|. int OpenPtyChildFd(const char* pts_name, unique_fd* error_sfd); bool ConnectProtocolEndpoints(std::string* _Nonnull error); static void ThreadHandler(void* userdata); void PassDataStreams(); void WaitForExit(); Loading Loading @@ -383,44 +385,11 @@ bool Subprocess::ForkAndExec(std::string* error) { } D("subprocess parent: exec completed"); if (protocol_ == SubprocessProtocol::kNone) { // No protocol: all streams pass through the stdinout FD and hook // directly into the local socket for raw data transfer. local_socket_sfd_.reset(stdinout_sfd_.release()); } else { // Shell protocol: create another socketpair to intercept data. if (!CreateSocketpair(&protocol_sfd_, &local_socket_sfd_)) { *error = android::base::StringPrintf( "failed to create socketpair to intercept data: %s", strerror(errno)); kill(pid_, SIGKILL); return false; } D("protocol FD = %d", protocol_sfd_.get()); input_ = std::make_unique<ShellProtocol>(protocol_sfd_); output_ = std::make_unique<ShellProtocol>(protocol_sfd_); if (!input_ || !output_) { *error = "failed to allocate shell protocol objects"; if (!ConnectProtocolEndpoints(error)) { kill(pid_, SIGKILL); return false; } // Don't let reads/writes to the subprocess block our thread. This isn't // likely but could happen under unusual circumstances, such as if we // write a ton of data to stdin but the subprocess never reads it and // the pipe fills up. for (int fd : {stdinout_sfd_.get(), stderr_sfd_.get()}) { if (fd >= 0) { if (!set_file_block_mode(fd, false)) { *error = android::base::StringPrintf( "failed to set non-blocking mode for fd %d", fd); kill(pid_, SIGKILL); return false; } } } } D("subprocess parent: completed"); return true; } Loading @@ -429,7 +398,6 @@ bool Subprocess::ExecInProcess(Command command, std::string* _Nonnull error) { unique_fd child_stdinout_sfd, child_stderr_sfd; CHECK(type_ == SubprocessType::kRaw); CHECK(protocol_ == SubprocessProtocol::kShell); __android_log_security_bswrite(SEC_TAG_ADB_SHELL_CMD, command_.c_str()); Loading @@ -448,10 +416,29 @@ bool Subprocess::ExecInProcess(Command command, std::string* _Nonnull error) { D("execinprocess: stdin/stdout FD = %d, stderr FD = %d", stdinout_sfd_.get(), stderr_sfd_.get()); if (!ConnectProtocolEndpoints(error)) { return false; } std::thread([inout_sfd = std::move(child_stdinout_sfd), err_sfd = std::move(child_stderr_sfd), command = std::move(command), args = command_]() { command(args, inout_sfd, inout_sfd, err_sfd); }) .detach(); D("execinprocess: completed"); return true; } bool Subprocess::ConnectProtocolEndpoints(std::string* _Nonnull error) { if (protocol_ == SubprocessProtocol::kNone) { // No protocol: all streams pass through the stdinout FD and hook // directly into the local socket for raw data transfer. local_socket_sfd_.reset(stdinout_sfd_.release()); } else { // Required for shell protocol: create another socketpair to intercept data. if (!CreateSocketpair(&protocol_sfd_, &local_socket_sfd_)) { *error = android::base::StringPrintf("failed to create socketpair to intercept data: %s", strerror(errno)); *error = android::base::StringPrintf( "failed to create socketpair to intercept data: %s", strerror(errno)); return false; } D("protocol FD = %d", protocol_sfd_.get()); Loading @@ -470,19 +457,14 @@ bool Subprocess::ExecInProcess(Command command, std::string* _Nonnull error) { for (int fd : {stdinout_sfd_.get(), stderr_sfd_.get()}) { if (fd >= 0) { if (!set_file_block_mode(fd, false)) { *error = android::base::StringPrintf("failed to set non-blocking mode for fd %d", fd); *error = android::base::StringPrintf( "failed to set non-blocking mode for fd %d", fd); return false; } } } } std::thread([inout_sfd = std::move(child_stdinout_sfd), err_sfd = std::move(child_stderr_sfd), command = std::move(command), args = command_]() { command(args, inout_sfd, inout_sfd, err_sfd); }) .detach(); D("execinprocess: completed"); return true; } Loading Loading @@ -863,12 +845,11 @@ unique_fd StartSubprocess(std::string name, const char* terminal_type, Subproces return local_socket; } unique_fd StartCommandInProcess(std::string name, Command command) { unique_fd StartCommandInProcess(std::string name, Command command, SubprocessProtocol protocol) { LOG(INFO) << "StartCommandInProcess(" << dump_hex(name.data(), name.size()) << ")"; constexpr auto terminal_type = ""; constexpr auto type = SubprocessType::kRaw; constexpr auto protocol = SubprocessProtocol::kShell; constexpr auto make_pty_raw = false; auto subprocess = std::make_unique<Subprocess>(std::move(name), terminal_type, type, protocol, Loading