• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #if !defined(__ANDROID_RECOVERY__)
18 #define TRACE_TAG JDWP
19 
20 #include "sysdeps.h"
21 
22 #include <errno.h>
23 #include <inttypes.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 #include <unistd.h>
30 
31 #include <list>
32 #include <memory>
33 #include <thread>
34 #include <vector>
35 
36 #include <adbconnection/process_info.h>
37 #include <adbconnection/server.h>
38 #include <android-base/cmsg.h>
39 #include <android-base/unique_fd.h>
40 
41 #include "adb.h"
42 #include "adb_io.h"
43 #include "adb_unique_fd.h"
44 #include "adb_utils.h"
45 #include "app_processes.pb.h"
46 
47 using android::base::borrowed_fd;
48 using android::base::unique_fd;
49 
50 /* here's how these things work.
51 
52    when adbd starts, it creates a unix server socket
53    named @jdwp-control (@ is a shortcut for "first byte is zero"
54    to use the private namespace instead of the file system)
55 
56    when a new JDWP daemon thread starts in a new VM process, it creates
57    a connection to @jdwp-control to announce its availability.
58 
59 
60      JDWP thread                             @jdwp-control
61          |                                         |
62          |------------------------------->         |
63          | hello I'm in process <pid>              |
64          |                                         |
65          |                                         |
66 
67     the connection is kept alive. it will be closed automatically if
68     the JDWP process terminates (this allows adbd to detect dead
69     processes).
70 
71     adbd thus maintains a list of "active" JDWP processes. it can send
72     its content to clients through the "device:debug-ports" service,
73     or even updates through the "device:track-debug-ports" service.
74 
75     when a debugger wants to connect, it simply runs the command
76     equivalent to  "adb forward tcp:<hostport> jdwp:<pid>"
77 
78     "jdwp:<pid>" is a new forward destination format used to target
79     a given JDWP process on the device. when sutch a request arrives,
80     adbd does the following:
81 
82       - first, it calls socketpair() to create a pair of equivalent
83         sockets.
84 
85       - it attaches the first socket in the pair to a local socket
86         which is itself attached to the transport's remote socket:
87 
88 
89       - it sends the file descriptor of the second socket directly
90         to the JDWP process with the help of sendmsg()
91 
92 
93      JDWP thread                             @jdwp-control
94          |                                         |
95          |                  <----------------------|
96          |           OK, try this file descriptor  |
97          |                                         |
98          |                                         |
99 
100    then, the JDWP thread uses this new socket descriptor as its
101    pass-through connection to the debugger (and receives the
102    JDWP-Handshake message, answers to it, etc...)
103 
104    this gives the following graphics:
105                     ____________________________________
106                    |                                    |
107                    |          ADB Server (host)         |
108                    |                                    |
109         Debugger <---> LocalSocket <----> RemoteSocket  |
110                    |                           ^^       |
111                    |___________________________||_______|
112                                                ||
113                                      Transport ||
114            (TCP for emulator - USB for device) ||
115                                                ||
116                     ___________________________||_______
117                    |                           ||       |
118                    |          ADBD  (device)   ||       |
119                    |                           VV       |
120          JDWP <======> LocalSocket <----> RemoteSocket  |
121                    |                                    |
122                    |____________________________________|
123 
124     due to the way adb works, this doesn't need a special socket
125     type or fancy handling of socket termination if either the debugger
126     or the JDWP process closes the connection.
127 
128     THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
129     TO HAVE A BETTER IDEA, LET ME KNOW - Digit
130 
131 **********************************************************************/
132 
133 /** JDWP PID List Support Code
134  ** for each JDWP process, we record its pid and its connected socket
135  **/
136 
137 enum class TrackerKind {
138     kJdwp,
139     kApp,
140 };
141 
142 static void jdwp_process_event(int socket, unsigned events, void* _proc);
143 static void jdwp_process_list_updated(void);
144 static void app_process_list_updated(void);
145 
146 struct JdwpProcess;
147 static auto& _jdwp_list = *new std::list<std::unique_ptr<JdwpProcess>>();
148 
149 struct JdwpProcess {
JdwpProcessJdwpProcess150     JdwpProcess(unique_fd socket, ProcessInfo process) {
151         CHECK(process.pid != 0);
152 
153         this->socket = socket;
154         this->process = process;
155         this->fde = fdevent_create(socket.release(), jdwp_process_event, this);
156 
157         if (!this->fde) {
158             LOG(FATAL) << "could not create fdevent for new JDWP process";
159         }
160     }
161 
~JdwpProcessJdwpProcess162     ~JdwpProcess() {
163         if (this->socket >= 0) {
164             adb_shutdown(this->socket);
165             this->socket = -1;
166         }
167 
168         if (this->fde) {
169             fdevent_destroy(this->fde);
170             this->fde = nullptr;
171         }
172 
173         out_fds.clear();
174     }
175 
RemoveFromListJdwpProcess176     void RemoveFromList() {
177         auto pred = [this](const auto& proc) { return proc.get() == this; };
178         _jdwp_list.remove_if(pred);
179     }
180 
181     borrowed_fd socket = -1;
182     ProcessInfo process;
183     fdevent* fde = nullptr;
184 
185     std::vector<unique_fd> out_fds;
186 };
187 
188 // Populate the list of processes for "track-jdwp" service.
jdwp_process_list(char * buffer,size_t bufferlen)189 static size_t jdwp_process_list(char* buffer, size_t bufferlen) {
190     std::string temp;
191 
192     for (auto& proc : _jdwp_list) {
193         if (!proc->process.debuggable) continue;
194         std::string next = std::to_string(proc->process.pid) + "\n";
195         if (temp.length() + next.length() > bufferlen) {
196             D("truncating JDWP process list (max len = %zu)", bufferlen);
197             break;
198         }
199         temp.append(next);
200     }
201 
202     memcpy(buffer, temp.data(), temp.length());
203     return temp.length();
204 }
205 
206 // Populate the list of processes for "track-app" service.
207 // The list is a protobuf message in the binary format for efficiency.
app_process_list(char * buffer,size_t bufferlen)208 static size_t app_process_list(char* buffer, size_t bufferlen) {
209     adb::proto::AppProcesses output;  // result that's guaranteed to fit in the given buffer
210     adb::proto::AppProcesses temp;    // temporary result that may be longer than the given buffer
211     std::string serialized_message;
212 
213     for (auto& proc : _jdwp_list) {
214         if (!proc->process.debuggable && !proc->process.profileable) continue;
215         auto* entry = temp.add_process();
216         entry->set_pid(proc->process.pid);
217         entry->set_debuggable(proc->process.debuggable);
218         entry->set_profileable(proc->process.profileable);
219         entry->set_architecture(proc->process.arch_name, proc->process.arch_name_length);
220         temp.SerializeToString(&serialized_message);
221         if (serialized_message.size() > bufferlen) {
222             D("truncating app process list (max len = %zu)", bufferlen);
223             break;
224         }
225         output = temp;
226     }
227     output.SerializeToString(&serialized_message);
228     memcpy(buffer, serialized_message.data(), serialized_message.length());
229     return serialized_message.length();
230 }
231 
232 // Populate the list of processes for either "track-jdwp" or "track-app" services,
233 // depending on the given kind.
process_list(TrackerKind kind,char * buffer,size_t bufferlen)234 static size_t process_list(TrackerKind kind, char* buffer, size_t bufferlen) {
235     switch (kind) {
236         case TrackerKind::kJdwp:
237             return jdwp_process_list(buffer, bufferlen);
238         case TrackerKind::kApp:
239             return app_process_list(buffer, bufferlen);
240     }
241 }
242 
process_list_msg(TrackerKind kind,char * buffer,size_t bufferlen)243 static size_t process_list_msg(TrackerKind kind, char* buffer, size_t bufferlen) {
244     // Message is length-prefixed with 4 hex digits in ASCII.
245     static constexpr size_t header_len = 4;
246     if (bufferlen < header_len) {
247         LOG(FATAL) << "invalid JDWP process list buffer size: " << bufferlen;
248     }
249 
250     char head[header_len + 1];
251     size_t len = process_list(kind, buffer + header_len, bufferlen - header_len);
252     snprintf(head, sizeof head, "%04zx", len);
253     memcpy(buffer, head, header_len);
254     return len + header_len;
255 }
256 
jdwp_process_event(int socket,unsigned events,void * _proc)257 static void jdwp_process_event(int socket, unsigned events, void* _proc) {
258     JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
259     CHECK_EQ(socket, proc->socket.get());
260 
261     if (events & FDE_READ) {
262         // We already have the PID, if we can read from the socket, we've probably hit EOF.
263         D("terminating JDWP connection %" PRId64, proc->process.pid);
264         goto CloseProcess;
265     }
266 
267     if (events & FDE_WRITE) {
268         D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
269         CHECK(!proc->out_fds.empty());
270 
271         int fd = proc->out_fds.back().get();
272         if (android::base::SendFileDescriptors(socket, "", 1, fd) != 1) {
273             D("sending new file descriptor to JDWP %" PRId64 " failed: %s", proc->process.pid,
274               strerror(errno));
275             goto CloseProcess;
276         }
277 
278         D("sent file descriptor %d to JDWP process %" PRId64, fd, proc->process.pid);
279 
280         proc->out_fds.pop_back();
281         if (proc->out_fds.empty()) {
282             fdevent_del(proc->fde, FDE_WRITE);
283         }
284     }
285 
286     return;
287 
288 CloseProcess:
289     bool debuggable = proc->process.debuggable;
290     bool profileable = proc->process.profileable;
291     proc->RemoveFromList();
292     if (debuggable) jdwp_process_list_updated();
293     if (debuggable || profileable) app_process_list_updated();
294 }
295 
create_jdwp_connection_fd(int pid)296 unique_fd create_jdwp_connection_fd(int pid) {
297     D("looking for pid %d in JDWP process list", pid);
298 
299     for (auto& proc : _jdwp_list) {
300         // Don't allow JDWP connection to a non-debuggable process.
301         if (!proc->process.debuggable) continue;
302         if (proc->process.pid == static_cast<uint64_t>(pid)) {
303             int fds[2];
304 
305             if (adb_socketpair(fds) < 0) {
306                 D("%s: socket pair creation failed: %s", __FUNCTION__, strerror(errno));
307                 return unique_fd{};
308             }
309             D("socketpair: (%d,%d)", fds[0], fds[1]);
310 
311             proc->out_fds.emplace_back(fds[1]);
312             if (proc->out_fds.size() == 1) {
313                 fdevent_add(proc->fde, FDE_WRITE);
314             }
315 
316             return unique_fd{fds[0]};
317         }
318     }
319     D("search failed !!");
320     return unique_fd{};
321 }
322 
323 /** "jdwp" local service implementation
324  ** this simply returns the list of known JDWP process pids
325  **/
326 
327 struct JdwpSocket : public asocket {
328     bool pass = false;
329 };
330 
jdwp_socket_close(asocket * s)331 static void jdwp_socket_close(asocket* s) {
332     D("LS(%d): closing jdwp socket", s->id);
333 
334     if (s->peer) {
335         D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
336         s->peer->peer = nullptr;
337         s->peer->close(s->peer);
338         s->peer = nullptr;
339     }
340 
341     remove_socket(s);
342     delete s;
343 }
344 
jdwp_socket_enqueue(asocket * s,apacket::payload_type)345 static int jdwp_socket_enqueue(asocket* s, apacket::payload_type) {
346     /* you can't write to this asocket */
347     D("LS(%d): JDWP socket received data?", s->id);
348     s->peer->close(s->peer);
349     return -1;
350 }
351 
jdwp_socket_ready(asocket * s)352 static void jdwp_socket_ready(asocket* s) {
353     JdwpSocket* jdwp = (JdwpSocket*)s;
354     asocket* peer = jdwp->peer;
355 
356     /* on the first call, send the list of pids,
357      * on the second one, close the connection
358      */
359     if (!jdwp->pass) {
360         apacket::payload_type data;
361         data.resize(s->get_max_payload());
362         size_t len = jdwp_process_list(&data[0], data.size());
363         data.resize(len);
364         peer->enqueue(peer, std::move(data));
365         jdwp->pass = true;
366     } else {
367         peer->close(peer);
368     }
369 }
370 
create_jdwp_service_socket(void)371 asocket* create_jdwp_service_socket(void) {
372     JdwpSocket* s = new JdwpSocket();
373 
374     if (!s) {
375         LOG(FATAL) << "failed to allocate JdwpSocket";
376     }
377 
378     install_local_socket(s);
379 
380     s->ready = jdwp_socket_ready;
381     s->enqueue = jdwp_socket_enqueue;
382     s->close = jdwp_socket_close;
383     s->pass = false;
384 
385     return s;
386 }
387 
388 /** "track-jdwp" local service implementation
389  ** this periodically sends the list of known JDWP process pids
390  ** to the client...
391  **/
392 
393 struct JdwpTracker : public asocket {
394     TrackerKind kind;
395     bool need_initial;
396 
JdwpTrackerJdwpTracker397     explicit JdwpTracker(TrackerKind k, bool initial) : kind(k), need_initial(initial) {}
398 };
399 
400 static auto& _jdwp_trackers = *new std::vector<std::unique_ptr<JdwpTracker>>();
401 
process_list_updated(TrackerKind kind)402 static void process_list_updated(TrackerKind kind) {
403     std::string data;
404     const int kMaxLength = kind == TrackerKind::kJdwp ? 1024 : 2048;
405     data.resize(kMaxLength);
406     data.resize(process_list_msg(kind, &data[0], data.size()));
407 
408     for (auto& t : _jdwp_trackers) {
409         if (t->kind == kind && t->peer) {
410             // The tracker might not have been connected yet.
411             apacket::payload_type payload(data.begin(), data.end());
412             t->peer->enqueue(t->peer, std::move(payload));
413         }
414     }
415 }
416 
jdwp_process_list_updated(void)417 static void jdwp_process_list_updated(void) {
418     process_list_updated(TrackerKind::kJdwp);
419 }
420 
app_process_list_updated(void)421 static void app_process_list_updated(void) {
422     process_list_updated(TrackerKind::kApp);
423 }
424 
jdwp_tracker_close(asocket * s)425 static void jdwp_tracker_close(asocket* s) {
426     D("LS(%d): destroying jdwp tracker service", s->id);
427 
428     if (s->peer) {
429         D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
430         s->peer->peer = nullptr;
431         s->peer->close(s->peer);
432         s->peer = nullptr;
433     }
434 
435     remove_socket(s);
436 
437     auto pred = [s](const auto& tracker) { return tracker.get() == s; };
438     _jdwp_trackers.erase(std::remove_if(_jdwp_trackers.begin(), _jdwp_trackers.end(), pred),
439                          _jdwp_trackers.end());
440 }
441 
jdwp_tracker_ready(asocket * s)442 static void jdwp_tracker_ready(asocket* s) {
443     JdwpTracker* t = (JdwpTracker*)s;
444 
445     if (t->need_initial) {
446         apacket::payload_type data;
447         data.resize(s->get_max_payload());
448         data.resize(process_list_msg(t->kind, &data[0], data.size()));
449         t->need_initial = false;
450         s->peer->enqueue(s->peer, std::move(data));
451     }
452 }
453 
jdwp_tracker_enqueue(asocket * s,apacket::payload_type)454 static int jdwp_tracker_enqueue(asocket* s, apacket::payload_type) {
455     /* you can't write to this socket */
456     D("LS(%d): JDWP tracker received data?", s->id);
457     s->peer->close(s->peer);
458     return -1;
459 }
460 
create_process_tracker_service_socket(TrackerKind kind)461 static asocket* create_process_tracker_service_socket(TrackerKind kind) {
462     std::unique_ptr<JdwpTracker> t = std::make_unique<JdwpTracker>(kind, true);
463     if (!t) {
464         LOG(FATAL) << "failed to allocate JdwpTracker";
465     }
466 
467     /* Object layout (with an inheritance hierarchy) varies across arch (e.g
468      * armv7a/Android TV vs aarch64), so no assumptions can be made about
469      * accessing fields based on offsets (e.g memset(t.get(), 0, sizeof(asocket))
470      * might clobber an unintended memory location).
471      */
472 
473     install_local_socket(t.get());
474     D("LS(%d): created new jdwp tracker service", t->id);
475 
476     t->ready = jdwp_tracker_ready;
477     t->enqueue = jdwp_tracker_enqueue;
478     t->close = jdwp_tracker_close;
479 
480     asocket* result = t.get();
481 
482     _jdwp_trackers.emplace_back(std::move(t));
483 
484     return result;
485 }
486 
create_jdwp_tracker_service_socket()487 asocket* create_jdwp_tracker_service_socket() {
488     return create_process_tracker_service_socket(TrackerKind::kJdwp);
489 }
490 
create_app_tracker_service_socket()491 asocket* create_app_tracker_service_socket() {
492     return create_process_tracker_service_socket(TrackerKind::kApp);
493 }
494 
init_jdwp(void)495 int init_jdwp(void) {
496     std::thread([]() {
497         adb_thread_setname("jdwp control");
498         adbconnection_listen([](int fd, ProcessInfo process) {
499             LOG(INFO) << "jdwp connection from " << process.pid;
500             fdevent_run_on_looper([fd, process] {
501                 unique_fd ufd(fd);
502                 auto proc = std::make_unique<JdwpProcess>(std::move(ufd), process);
503                 if (!proc) {
504                     LOG(FATAL) << "failed to allocate JdwpProcess";
505                 }
506                 _jdwp_list.emplace_back(std::move(proc));
507                 if (process.debuggable) jdwp_process_list_updated();
508                 if (process.debuggable || process.profileable) app_process_list_updated();
509             });
510         });
511     }).detach();
512     return 0;
513 }
514 
515 #else  // !defined(__ANDROID_RECOVERY)
516 #include "adb.h"
517 
create_jdwp_service_socket(void)518 asocket* create_jdwp_service_socket(void) {
519     return nullptr;
520 }
521 
create_jdwp_connection_fd(int pid)522 unique_fd create_jdwp_connection_fd(int pid) {
523     return {};
524 }
525 
create_app_tracker_service_socket()526 asocket* create_app_tracker_service_socket() {
527     return nullptr;
528 }
529 
create_jdwp_tracker_service_socket()530 asocket* create_jdwp_tracker_service_socket() {
531     return nullptr;
532 }
533 
init_jdwp()534 int init_jdwp() {
535     return 0;
536 }
537 
538 #endif /* defined(__ANDROID_RECOVERY__) */
539