diff options
author | Josh Gao <jmgao@google.com> | 2020-01-22 18:02:19 -0800 |
---|---|---|
committer | Josh Gao <jmgao@google.com> | 2020-01-29 00:03:20 +0000 |
commit | bd396c001fd3b13a7451876ec8c535bb597ea350 (patch) | |
tree | 0323ee2c9bc30732dacf42e985282086338723f2 | |
parent | 3f0dca119df45ef2a7fdfc26c070677953cfcce4 (diff) | |
download | platform_art-bd396c001fd3b13a7451876ec8c535bb597ea350.tar.gz platform_art-bd396c001fd3b13a7451876ec8c535bb597ea350.tar.bz2 platform_art-bd396c001fd3b13a7451876ec8c535bb597ea350.zip |
Move jdwp connection abstraction from ART apex to adbd apex.
Test: ./art/tools/run-jdwp-tests.sh
Change-Id: I3114b8403f3548700a45df5d7bb72ebe727adec1
-rw-r--r-- | Android.mk | 2 | ||||
-rw-r--r-- | adbconnection/Android.bp | 27 | ||||
-rw-r--r-- | adbconnection/adbconnection.cc | 115 | ||||
-rw-r--r-- | adbconnection/adbconnection.h | 6 | ||||
-rw-r--r-- | adbconnection/adbconnection_server.cc | 133 | ||||
-rw-r--r-- | adbconnection/include/adbconnection/server.h | 30 | ||||
-rw-r--r-- | adbconnection/libadbconnection_server.map.txt | 22 | ||||
-rw-r--r-- | build/apex/Android.bp | 1 | ||||
-rwxr-xr-x | build/apex/art_apex_test.py | 1 | ||||
-rw-r--r-- | build/apex/ld.config.txt | 25 |
10 files changed, 56 insertions, 306 deletions
diff --git a/Android.mk b/Android.mk index 6e41516c8a1..fc44da43aac 100644 --- a/Android.mk +++ b/Android.mk @@ -537,7 +537,6 @@ PRIVATE_ART_APEX_DEPENDENCY_FILES := \ PRIVATE_ART_APEX_DEPENDENCY_LIBS := \ lib/libadbconnectiond.so \ - lib/libadbconnection_server.so \ lib/libadbconnection.so \ lib/libandroidicu.so \ lib/libandroidio.so \ @@ -591,7 +590,6 @@ PRIVATE_ART_APEX_DEPENDENCY_LIBS := \ lib/libziparchive.so \ lib/libz.so \ lib64/libadbconnectiond.so \ - lib64/libadbconnection_server.so \ lib64/libadbconnection.so \ lib64/libandroidicu.so \ lib64/libandroidio.so \ diff --git a/adbconnection/Android.bp b/adbconnection/Android.bp index b2503e1b495..b03cd0d07b7 100644 --- a/adbconnection/Android.bp +++ b/adbconnection/Android.bp @@ -28,6 +28,7 @@ cc_defaults { shared_libs: [ "libbase", + "libadbconnection_client", ], target: { host: { @@ -59,32 +60,6 @@ art_cc_library { ], } -// We export a library to do the server-side socket handling that gets loaded -// by adbd from the art apex, so that we can update the socket handling -// independently from the adbd apex. -cc_library { - name: "libadbconnection_server", - srcs: ["adbconnection_server.cc"], - - export_include_dirs: ["include"], - - stl: "libc++_static", - shared_libs: ["liblog"], - whole_static_libs: ["libbase"], - - defaults: ["art_defaults"], - visibility: [ - "//system/core/adb", - ], - stubs: { - symbol_file: "libadbconnection_server.map.txt", - versions: ["1"], - }, - - host_supported: true, - recovery_available: true, -} - art_cc_library { name: "libadbconnectiond", defaults: [ diff --git a/adbconnection/adbconnection.cc b/adbconnection/adbconnection.cc index 0824eb459b6..2234ce4fa24 100644 --- a/adbconnection/adbconnection.cc +++ b/adbconnection/adbconnection.cc @@ -15,16 +15,17 @@ */ #include <array> +#include <iterator> #include "adbconnection.h" +#include "adbconnection/client.h" #include "android-base/endian.h" #include "android-base/stringprintf.h" #include "base/file_utils.h" #include "base/logging.h" #include "base/macros.h" #include "base/mutex.h" -#include "base/socket_peer_is_trusted.h" #include "jni/java_vm_ext.h" #include "jni/jni_env_ext.h" #include "mirror/throwable.h" @@ -66,7 +67,6 @@ static constexpr const char kJdwpHandshake[14] = { static constexpr int kEventfdLocked = 0; static constexpr int kEventfdUnlocked = 1; -static constexpr int kControlSockSendTimeout = 10; static constexpr size_t kPacketHeaderLen = 11; static constexpr off_t kPacketSizeOff = 0; @@ -125,7 +125,7 @@ AdbConnectionState::AdbConnectionState(const std::string& agent_name) controller_(this), ddm_callback_(this), sleep_event_fd_(-1), - control_sock_(-1), + control_ctx_(nullptr, adbconnection_client_destroy), local_agent_control_sock_(-1), remote_agent_control_sock_(-1), adb_connection_socket_(-1), @@ -447,57 +447,18 @@ void AdbConnectionState::SendAgentFds(bool require_handshake) { } android::base::unique_fd AdbConnectionState::ReadFdFromAdb() { - // We don't actually care about the data that is sent. We do need to receive something though. - char dummy = '!'; - union { - cmsghdr cm; - char buffer[CMSG_SPACE(sizeof(int))]; - } cm_un; - - iovec iov; - iov.iov_base = &dummy; - iov.iov_len = 1; - - msghdr msg; - msg.msg_name = nullptr; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_flags = 0; - msg.msg_control = cm_un.buffer; - msg.msg_controllen = sizeof(cm_un.buffer); - - cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = msg.msg_controllen; - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - (reinterpret_cast<int*>(CMSG_DATA(cmsg)))[0] = -1; - - int rc = TEMP_FAILURE_RETRY(recvmsg(control_sock_, &msg, 0)); - - if (rc <= 0) { - return android::base::unique_fd(-1); - } else { - VLOG(jdwp) << "Fds have been received from ADB!"; - } - - return android::base::unique_fd((reinterpret_cast<int*>(CMSG_DATA(cmsg)))[0]); + return android::base::unique_fd(adbconnection_client_receive_jdwp_fd(control_ctx_.get())); } bool AdbConnectionState::SetupAdbConnection() { - int sleep_ms = 500; - const int sleep_max_ms = 2*1000; + int sleep_ms = 500; + const int sleep_max_ms = 2 * 1000; - android::base::unique_fd sock(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0)); - if (sock < 0) { - PLOG(ERROR) << "Could not create ADB control socket"; - return false; - } - struct timeval timeout; - timeout.tv_sec = kControlSockSendTimeout; - timeout.tv_usec = 0; - setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); - int32_t pid = getpid(); + const AdbConnectionClientInfo infos[] = { + {.type = AdbConnectionClientInfoType::pid, .data.pid = static_cast<uint64_t>(getpid())}, + {.type = AdbConnectionClientInfoType::debuggable, .data.debuggable = true}, + }; + const AdbConnectionClientInfo* info_ptrs[] = {&infos[0], &infos[1]}; while (!shutting_down_) { // If adbd isn't running, because USB debugging was disabled or @@ -511,39 +472,20 @@ bool AdbConnectionState::SetupAdbConnection() { // of battery life, we should consider timing out and giving // up after a few minutes in case somebody ships an app with // the debuggable flag set. - int ret = connect(sock, &control_addr_.controlAddrPlain, control_addr_len_); - if (ret == 0) { - bool trusted = sock >= 0 && art::SocketPeerIsTrusted(sock); - if (!trusted) { - LOG(ERROR) << "adb socket is not trusted. Aborting connection."; - if (sock >= 0 && shutdown(sock, SHUT_RDWR)) { - PLOG(ERROR) << "trouble shutting down socket"; - } - return false; - } - /* now try to send our pid to the ADB daemon */ - ret = TEMP_FAILURE_RETRY(send(sock, &pid, sizeof(pid), 0)); - if (ret == sizeof(pid)) { - VLOG(jdwp) << "PID " << pid << " sent to adb"; - control_sock_ = std::move(sock); - return true; - } else { - PLOG(ERROR) << "Weird, can't send JDWP process pid to ADB. Aborting connection."; - return false; - } - } else { - if (VLOG_IS_ON(jdwp)) { - PLOG(ERROR) << "Can't connect to ADB control socket. Will retry."; - } + control_ctx_.reset(adbconnection_client_new(info_ptrs, std::size(infos))); + if (control_ctx_) { + return true; + } - usleep(sleep_ms * 1000); + // We failed to connect. + usleep(sleep_ms * 1000); - sleep_ms += (sleep_ms >> 1); - if (sleep_ms > sleep_max_ms) { - sleep_ms = sleep_max_ms; - } + sleep_ms += (sleep_ms >> 1); + if (sleep_ms > sleep_max_ms) { + sleep_ms = sleep_max_ms; } } + return false; } @@ -554,12 +496,12 @@ void AdbConnectionState::RunPollLoop(art::Thread* self) { self->SetState(art::kWaitingInMainDebuggerLoop); // shutting_down_ set by StopDebuggerThreads while (!shutting_down_) { - // First get the control_sock_ from adb if we don't have one. We only need to do this once. - if (control_sock_ == -1 && !SetupAdbConnection()) { + // First, connect to adbd if we haven't already. + if (!control_ctx_ && !SetupAdbConnection()) { LOG(ERROR) << "Failed to setup adb connection."; return; } - while (!shutting_down_ && control_sock_ != -1) { + while (!shutting_down_ && control_ctx_) { bool should_listen_on_connection = !agent_has_socket_ && !sent_agent_fds_; struct pollfd pollfds[4] = { { sleep_event_fd_, POLLIN, 0 }, @@ -567,7 +509,8 @@ void AdbConnectionState::RunPollLoop(art::Thread* self) { { (agent_loaded_ ? local_agent_control_sock_ : -1), POLLIN, 0 }, // Check for the control_sock_ actually going away. Only do this if we don't have an active // connection. - { (adb_connection_socket_ == -1 ? control_sock_ : -1), POLLIN | POLLRDHUP, 0 }, + { (adb_connection_socket_ == -1 ? adbconnection_client_pollfd(control_ctx_.get()) : -1), + POLLIN | POLLRDHUP, 0 }, // if we have not loaded the agent either the adb_connection_socket_ is -1 meaning we don't // have a real connection yet or the socket through adb needs to be listened to for incoming // data that the agent or this plugin can handle. @@ -617,10 +560,10 @@ void AdbConnectionState::RunPollLoop(art::Thread* self) { { // Hold onto this lock so that concurrent ddm publishes don't try to use an illegal fd. ScopedEventFdLock sefdl(adb_write_event_fd_); - android::base::unique_fd new_fd(ReadFdFromAdb()); + android::base::unique_fd new_fd(adbconnection_client_receive_jdwp_fd(control_ctx_.get())); if (new_fd == -1) { // Something went wrong. We need to retry getting the control socket. - control_sock_.reset(); + control_ctx_.reset(); break; } else if (adb_connection_socket_ != -1) { // We already have a connection. @@ -645,7 +588,7 @@ void AdbConnectionState::RunPollLoop(art::Thread* self) { // Reset the connection since we don't have an active socket through the adb server. DCHECK(!agent_has_socket_) << "We shouldn't be doing anything if there is already a " << "connection active"; - control_sock_.reset(); + control_ctx_.reset(); break; } else if (FlagsSet(adb_socket_poll.revents, POLLIN)) { DCHECK(!agent_has_socket_); diff --git a/adbconnection/adbconnection.h b/adbconnection/adbconnection.h index c51f981f40e..f9b0928298e 100644 --- a/adbconnection/adbconnection.h +++ b/adbconnection/adbconnection.h @@ -18,10 +18,12 @@ #define ART_ADBCONNECTION_ADBCONNECTION_H_ #include <stdint.h> +#include <memory> #include <vector> #include <limits> #include "android-base/unique_fd.h" +#include "adbconnection/client.h" #include "base/mutex.h" #include "base/array_ref.h" @@ -127,8 +129,8 @@ class AdbConnectionState { // Eventfd used to allow the StopDebuggerThreads function to wake up sleeping threads android::base::unique_fd sleep_event_fd_; - // Socket that we use to talk to adbd. - android::base::unique_fd control_sock_; + // Context which wraps the socket which we use to talk to adbd. + std::unique_ptr<AdbConnectionClientContext, void(*)(AdbConnectionClientContext*)> control_ctx_; // Socket that we use to talk to the agent (if it's loaded). android::base::unique_fd local_agent_control_sock_; diff --git a/adbconnection/adbconnection_server.cc b/adbconnection/adbconnection_server.cc deleted file mode 100644 index f69f4a71966..00000000000 --- a/adbconnection/adbconnection_server.cc +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "adbconnection/server.h" - -#include <sys/epoll.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> - -#include <algorithm> -#include <array> -#include <vector> - -#include <android-base/logging.h> -#include <android-base/unique_fd.h> - -using android::base::unique_fd; - -#define JDWP_CONTROL_NAME "\0jdwp-control" -#define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME) - 1) - -static_assert(JDWP_CONTROL_NAME_LEN <= - sizeof(reinterpret_cast<sockaddr_un*>(0)->sun_path)); - -// Listen for incoming jdwp clients forever. -void adbconnection_listen(void (*callback)(int fd, pid_t pid)) { - sockaddr_un addr = {}; - socklen_t addrlen = JDWP_CONTROL_NAME_LEN + sizeof(addr.sun_family); - - addr.sun_family = AF_UNIX; - memcpy(addr.sun_path, JDWP_CONTROL_NAME, JDWP_CONTROL_NAME_LEN); - - unique_fd s(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); - if (s < 0) { - PLOG(ERROR) << "failed to create JDWP control socket"; - return; - } - - if (bind(s.get(), reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) { - PLOG(ERROR) << "failed to bind JDWP control socket"; - return; - } - - if (listen(s.get(), 4) < 0) { - PLOG(ERROR) << "failed to listen on JDWP control socket"; - return; - } - - std::vector<unique_fd> pending_connections; - - unique_fd epfd(epoll_create1(EPOLL_CLOEXEC)); - std::array<epoll_event, 16> events; - - events[0].events = EPOLLIN; - events[0].data.fd = -1; - if (epoll_ctl(epfd.get(), EPOLL_CTL_ADD, s.get(), &events[0]) != 0) { - LOG(FATAL) << "failed to register event with epoll fd"; - } - - while (true) { - int epoll_rc = TEMP_FAILURE_RETRY(epoll_wait(epfd.get(), events.data(), events.size(), -1)); - if (epoll_rc == -1) { - PLOG(FATAL) << "epoll_wait failed"; - } - - for (int i = 0; i < epoll_rc; ++i) { - const epoll_event& event = events[i]; - if (event.data.fd == -1) { - unique_fd client(TEMP_FAILURE_RETRY( - accept4(s.get(), nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC))); - - if (client == -1) { - PLOG(WARNING) << "failed to accept client on JDWP control socket"; - continue; - } - - epoll_event register_event; - register_event.events = EPOLLIN; - register_event.data.fd = client.get(); - - if (epoll_ctl(epfd.get(), EPOLL_CTL_ADD, client.get(), - ®ister_event) != 0) { - PLOG(FATAL) << "failed to register JDWP client with epoll"; - } - - pending_connections.emplace_back(std::move(client)); - } else { - // n^2, but the backlog should be short. - auto it = std::find_if( - pending_connections.begin(), pending_connections.end(), - [&](const unique_fd& fd) { return fd.get() == event.data.fd; }); - - if (it == pending_connections.end()) { - LOG(FATAL) << "failed to find JDWP client (" << event.data.fd - << ") in pending connections"; - } - - // Massively oversized buffer: we're expecting an int32_t from the other end. - char buf[32]; - int rc = TEMP_FAILURE_RETRY(recv(it->get(), buf, sizeof(buf), MSG_DONTWAIT)); - if (rc != 4) { - LOG(ERROR) - << "received data of incorrect size from JDWP client: read " << rc - << ", expected 4"; - } else { - int32_t pid; - memcpy(&pid, buf, sizeof(pid)); - callback(it->release(), static_cast<pid_t>(pid)); - } - - if (epoll_ctl(epfd.get(), EPOLL_CTL_DEL, event.data.fd, nullptr) != 0) { - LOG(FATAL) << "failed to delete fd from JDWP epoll fd"; - } - - pending_connections.erase(it); - } - } - } -} diff --git a/adbconnection/include/adbconnection/server.h b/adbconnection/include/adbconnection/server.h deleted file mode 100644 index 8d1d69a771a..00000000000 --- a/adbconnection/include/adbconnection/server.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef ART_ADBCONNECTION_INCLUDE_ADBCONNECTION_SERVER_H_ -#define ART_ADBCONNECTION_INCLUDE_ADBCONNECTION_SERVER_H_ - -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <sys/types.h> - -#include <android-base/unique_fd.h> - -extern "C" { - -void adbconnection_listen(void (*callback)(int fd, pid_t pid)); - -} - -#endif // ART_ADBCONNECTION_INCLUDE_ADBCONNECTION_SERVER_H_ diff --git a/adbconnection/libadbconnection_server.map.txt b/adbconnection/libadbconnection_server.map.txt deleted file mode 100644 index b6315810315..00000000000 --- a/adbconnection/libadbconnection_server.map.txt +++ /dev/null @@ -1,22 +0,0 @@ -# -# Copyright (C) 2019 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LIBADBCONNECTION_SERVER_1 { - global: - adbconnection_listen; - local: - *; -}; diff --git a/build/apex/Android.bp b/build/apex/Android.bp index 70e4988d741..738a8700cbc 100644 --- a/build/apex/Android.bp +++ b/build/apex/Android.bp @@ -27,7 +27,6 @@ art_runtime_base_binaries_prefer32 = [ // the ART APEX. art_runtime_base_native_shared_libs = [ // External API (having APEX stubs). - "libadbconnection_server", "libdexfile_external", "libnativebridge", "libnativehelper", diff --git a/build/apex/art_apex_test.py b/build/apex/art_apex_test.py index 4062676b254..f2ec6e43780 100755 --- a/build/apex/art_apex_test.py +++ b/build/apex/art_apex_test.py @@ -492,7 +492,6 @@ class ReleaseChecker: self._checker.check_native_library('libnativebridge') self._checker.check_native_library('libnativehelper') self._checker.check_native_library('libnativeloader') - self._checker.check_native_library('libadbconnection_server') # Check internal libraries for ART. self._checker.check_native_library('libadbconnection') diff --git a/build/apex/ld.config.txt b/build/apex/ld.config.txt index b2eefcfc091..4121e9f8bcd 100644 --- a/build/apex/ld.config.txt +++ b/build/apex/ld.config.txt @@ -8,15 +8,16 @@ dir.art = /apex/com.android.art/bin/ [art] -additional.namespaces = platform,conscrypt,art,neuralnetworks +additional.namespaces = platform,conscrypt,art,neuralnetworks,adbd # The default namespace here only links to other namespaces, in particular "art" # where the real library loading takes place. Any outgoing links from "art" also # need to be present here. namespace.default.isolated = true -namespace.default.links = art,platform +namespace.default.links = art,platform,adbd namespace.default.link.art.allow_all_shared_libs = true namespace.default.link.platform.allow_all_shared_libs = true +namespace.default.link.adbd.shared_libs = libadbconnection_client.so ############################################################################### # "art" APEX namespace @@ -47,13 +48,14 @@ namespace.art.permitted.paths += /apex/com.android.art/javalib # the APEX namespaces, because searching of the libs are NOT done in # /system/lib, but in /apex/<module>/lib directory. namespace.art.permitted.paths += /system/${LIB} -namespace.art.links = platform,neuralnetworks +namespace.art.links = platform,neuralnetworks,adbd # Need allow_all_shared_libs because libart.so can dlopen oat files in # /system/framework and /data. # TODO(b/130340935): Use a dynamically created linker namespace similar to # classloader-namespace for oat files, and tighten this up. namespace.art.link.platform.allow_all_shared_libs = true namespace.art.link.neuralnetworks.shared_libs = libneuralnetworks.so +namespace.art.link.adbd.shared_libs = libadbconnection_client.so ############################################################################### # "platform" namespace @@ -155,3 +157,20 @@ namespace.neuralnetworks.link.platform.shared_libs += libnativewindow.so namespace.neuralnetworks.link.platform.shared_libs += libneuralnetworks_packageinfo.so namespace.neuralnetworks.link.platform.shared_libs += libsync.so namespace.neuralnetworks.link.platform.shared_libs += libvndksupport.so + +############################################################################### +# "adbd" APEX namespace +# +# This namespace is for libraries within the adbd APEX. +############################################################################### + +namespace.adbd.isolated = true +namespace.adbd.visible = true + +namespace.adbd.search.paths = /apex/com.android.adbd/${LIB} +namespace.adbd.asan.search.paths = /apex/com.android.adbd/${LIB} +namespace.adbd.links = platform +namespace.adbd.link.platform.shared_libs = libc.so +namespace.adbd.link.platform.shared_libs += libm.so +namespace.adbd.link.platform.shared_libs += libdl.so +namespace.adbd.link.platform.shared_libs += liblog.so |