• 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 !ADB_HOST
18 
19 #define TRACE_TAG JDWP
20 
21 #include "sysdeps.h"
22 
23 #include <errno.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 <vector>
34 
35 #include <android-base/cmsg.h>
36 
37 #include "adb.h"
38 #include "adb_io.h"
39 #include "adb_unique_fd.h"
40 #include "adb_utils.h"
41 
42 /* here's how these things work.
43 
44    when adbd starts, it creates a unix server socket
45    named @jdwp-control (@ is a shortcut for "first byte is zero"
46    to use the private namespace instead of the file system)
47 
48    when a new JDWP daemon thread starts in a new VM process, it creates
49    a connection to @jdwp-control to announce its availability.
50 
51 
52      JDWP thread                             @jdwp-control
53          |                                         |
54          |------------------------------->         |
55          | hello I'm in process <pid>              |
56          |                                         |
57          |                                         |
58 
59     the connection is kept alive. it will be closed automatically if
60     the JDWP process terminates (this allows adbd to detect dead
61     processes).
62 
63     adbd thus maintains a list of "active" JDWP processes. it can send
64     its content to clients through the "device:debug-ports" service,
65     or even updates through the "device:track-debug-ports" service.
66 
67     when a debugger wants to connect, it simply runs the command
68     equivalent to  "adb forward tcp:<hostport> jdwp:<pid>"
69 
70     "jdwp:<pid>" is a new forward destination format used to target
71     a given JDWP process on the device. when sutch a request arrives,
72     adbd does the following:
73 
74       - first, it calls socketpair() to create a pair of equivalent
75         sockets.
76 
77       - it attaches the first socket in the pair to a local socket
78         which is itself attached to the transport's remote socket:
79 
80 
81       - it sends the file descriptor of the second socket directly
82         to the JDWP process with the help of sendmsg()
83 
84 
85      JDWP thread                             @jdwp-control
86          |                                         |
87          |                  <----------------------|
88          |           OK, try this file descriptor  |
89          |                                         |
90          |                                         |
91 
92    then, the JDWP thread uses this new socket descriptor as its
93    pass-through connection to the debugger (and receives the
94    JDWP-Handshake message, answers to it, etc...)
95 
96    this gives the following graphics:
97                     ____________________________________
98                    |                                    |
99                    |          ADB Server (host)         |
100                    |                                    |
101         Debugger <---> LocalSocket <----> RemoteSocket  |
102                    |                           ^^       |
103                    |___________________________||_______|
104                                                ||
105                                      Transport ||
106            (TCP for emulator - USB for device) ||
107                                                ||
108                     ___________________________||_______
109                    |                           ||       |
110                    |          ADBD  (device)   ||       |
111                    |                           VV       |
112          JDWP <======> LocalSocket <----> RemoteSocket  |
113                    |                                    |
114                    |____________________________________|
115 
116     due to the way adb works, this doesn't need a special socket
117     type or fancy handling of socket termination if either the debugger
118     or the JDWP process closes the connection.
119 
120     THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
121     TO HAVE A BETTER IDEA, LET ME KNOW - Digit
122 
123 **********************************************************************/
124 
125 /** JDWP PID List Support Code
126  ** for each JDWP process, we record its pid and its connected socket
127  **/
128 
129 static void jdwp_process_event(int socket, unsigned events, void* _proc);
130 static void jdwp_process_list_updated(void);
131 
132 struct JdwpProcess;
133 static auto& _jdwp_list = *new std::list<std::unique_ptr<JdwpProcess>>();
134 
135 struct JdwpProcess {
JdwpProcessJdwpProcess136     explicit JdwpProcess(int socket) {
137         this->socket = socket;
138         this->fde = fdevent_create(socket, jdwp_process_event, this);
139 
140         if (!this->fde) {
141             LOG(FATAL) << "could not create fdevent for new JDWP process";
142         }
143 
144         /* start by waiting for the PID */
145         fdevent_add(this->fde, FDE_READ);
146     }
147 
~JdwpProcessJdwpProcess148     ~JdwpProcess() {
149         if (this->socket >= 0) {
150             adb_shutdown(this->socket);
151             this->socket = -1;
152         }
153 
154         if (this->fde) {
155             fdevent_destroy(this->fde);
156             this->fde = nullptr;
157         }
158 
159         out_fds.clear();
160     }
161 
RemoveFromListJdwpProcess162     void RemoveFromList() {
163         if (this->pid >= 0) {
164             D("removing pid %d from jdwp process list", this->pid);
165         } else {
166             D("removing transient JdwpProcess from list");
167         }
168 
169         auto pred = [this](const auto& proc) { return proc.get() == this; };
170         _jdwp_list.remove_if(pred);
171     }
172 
173     int32_t pid = -1;
174     int socket = -1;
175     fdevent* fde = nullptr;
176 
177     std::vector<unique_fd> out_fds;
178 };
179 
jdwp_process_list(char * buffer,size_t bufferlen)180 static size_t jdwp_process_list(char* buffer, size_t bufferlen) {
181     std::string temp;
182 
183     for (auto& proc : _jdwp_list) {
184         /* skip transient connections */
185         if (proc->pid < 0) {
186             continue;
187         }
188 
189         std::string next = std::to_string(proc->pid) + "\n";
190         if (temp.length() + next.length() > bufferlen) {
191             D("truncating JDWP process list (max len = %zu)", bufferlen);
192             break;
193         }
194         temp.append(next);
195     }
196 
197     memcpy(buffer, temp.data(), temp.length());
198     return temp.length();
199 }
200 
jdwp_process_list_msg(char * buffer,size_t bufferlen)201 static size_t jdwp_process_list_msg(char* buffer, size_t bufferlen) {
202     // Message is length-prefixed with 4 hex digits in ASCII.
203     static constexpr size_t header_len = 4;
204     if (bufferlen < header_len) {
205         LOG(FATAL) << "invalid JDWP process list buffer size: " << bufferlen;
206     }
207 
208     char head[header_len + 1];
209     size_t len = jdwp_process_list(buffer + header_len, bufferlen - header_len);
210     snprintf(head, sizeof head, "%04zx", len);
211     memcpy(buffer, head, header_len);
212     return len + header_len;
213 }
214 
jdwp_process_event(int socket,unsigned events,void * _proc)215 static void jdwp_process_event(int socket, unsigned events, void* _proc) {
216     JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
217     CHECK_EQ(socket, proc->socket);
218 
219     if (events & FDE_READ) {
220         if (proc->pid < 0) {
221             ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, &proc->pid, sizeof(proc->pid), 0));
222             if (rc != sizeof(proc->pid)) {
223                 D("failed to read jdwp pid: rc = %zd, errno = %s", rc, strerror(errno));
224                 goto CloseProcess;
225             }
226 
227             /* all is well, keep reading to detect connection closure */
228             D("Adding pid %d to jdwp process list", proc->pid);
229             jdwp_process_list_updated();
230         } else {
231             // We already have the PID, if we can read from the socket, we've probably hit EOF.
232             D("terminating JDWP connection %d", proc->pid);
233             goto CloseProcess;
234         }
235     }
236 
237     if (events & FDE_WRITE) {
238         D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
239         CHECK(!proc->out_fds.empty());
240 
241         int fd = proc->out_fds.back().get();
242         if (android::base::SendFileDescriptors(socket, "", 1, fd) != 1) {
243             D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
244             goto CloseProcess;
245         }
246 
247         D("sent file descriptor %d to JDWP process %d", fd, proc->pid);
248 
249         proc->out_fds.pop_back();
250         if (proc->out_fds.empty()) {
251             fdevent_del(proc->fde, FDE_WRITE);
252         }
253     }
254 
255     return;
256 
257 CloseProcess:
258     proc->RemoveFromList();
259     jdwp_process_list_updated();
260 }
261 
create_jdwp_connection_fd(int pid)262 unique_fd create_jdwp_connection_fd(int pid) {
263     D("looking for pid %d in JDWP process list", pid);
264 
265     for (auto& proc : _jdwp_list) {
266         if (proc->pid == pid) {
267             int fds[2];
268 
269             if (adb_socketpair(fds) < 0) {
270                 D("%s: socket pair creation failed: %s", __FUNCTION__, strerror(errno));
271                 return unique_fd{};
272             }
273             D("socketpair: (%d,%d)", fds[0], fds[1]);
274 
275             proc->out_fds.emplace_back(fds[1]);
276             if (proc->out_fds.size() == 1) {
277                 fdevent_add(proc->fde, FDE_WRITE);
278             }
279 
280             return unique_fd{fds[0]};
281         }
282     }
283     D("search failed !!");
284     return unique_fd{};
285 }
286 
287 /**  VM DEBUG CONTROL SOCKET
288  **
289  **  we do implement a custom asocket to receive the data
290  **/
291 
292 /* name of the debug control Unix socket */
293 #define JDWP_CONTROL_NAME "\0jdwp-control"
294 #define JDWP_CONTROL_NAME_LEN (sizeof(JDWP_CONTROL_NAME) - 1)
295 
296 struct JdwpControl {
297     int listen_socket;
298     fdevent* fde;
299 };
300 
301 static JdwpControl _jdwp_control;
302 
303 static void jdwp_control_event(int s, unsigned events, void* user);
304 
jdwp_control_init(JdwpControl * control,const char * sockname,int socknamelen)305 static int jdwp_control_init(JdwpControl* control, const char* sockname, int socknamelen) {
306     sockaddr_un addr;
307     socklen_t addrlen;
308     int maxpath = sizeof(addr.sun_path);
309     int pathlen = socknamelen;
310 
311     if (pathlen >= maxpath) {
312         D("vm debug control socket name too long (%d extra chars)", pathlen + 1 - maxpath);
313         return -1;
314     }
315 
316     memset(&addr, 0, sizeof(addr));
317     addr.sun_family = AF_UNIX;
318     memcpy(addr.sun_path, sockname, socknamelen);
319 
320     unique_fd s(socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0));
321     if (s < 0) {
322         D("could not create vm debug control socket. %d: %s", errno, strerror(errno));
323         return -1;
324     }
325 
326     addrlen = pathlen + sizeof(addr.sun_family);
327 
328     if (bind(s, reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
329         D("could not bind vm debug control socket: %d: %s", errno, strerror(errno));
330         return -1;
331     }
332 
333     if (listen(s, 4) < 0) {
334         D("listen failed in jdwp control socket: %d: %s", errno, strerror(errno));
335         return -1;
336     }
337 
338     control->listen_socket = s.release();
339     control->fde = fdevent_create(control->listen_socket, jdwp_control_event, control);
340     if (control->fde == nullptr) {
341         D("could not create fdevent for jdwp control socket");
342         return -1;
343     }
344 
345     /* only wait for incoming connections */
346     fdevent_add(control->fde, FDE_READ);
347 
348     D("jdwp control socket started (%d)", control->listen_socket);
349     return 0;
350 }
351 
jdwp_control_event(int fd,unsigned events,void * _control)352 static void jdwp_control_event(int fd, unsigned events, void* _control) {
353     JdwpControl* control = (JdwpControl*)_control;
354 
355     CHECK_EQ(fd, control->listen_socket);
356     if (events & FDE_READ) {
357         int s = adb_socket_accept(control->listen_socket, nullptr, nullptr);
358         if (s < 0) {
359             if (errno == ECONNABORTED) {
360                 /* oops, the JDWP process died really quick */
361                 D("oops, the JDWP process died really quick");
362                 return;
363             } else {
364                 /* the socket is probably closed ? */
365                 D("weird accept() failed on jdwp control socket: %s", strerror(errno));
366                 return;
367             }
368         }
369 
370         auto proc = std::make_unique<JdwpProcess>(s);
371         if (!proc) {
372             LOG(FATAL) << "failed to allocate JdwpProcess";
373         }
374 
375         _jdwp_list.emplace_back(std::move(proc));
376     }
377 }
378 
379 /** "jdwp" local service implementation
380  ** this simply returns the list of known JDWP process pids
381  **/
382 
383 struct JdwpSocket : public asocket {
384     bool pass = false;
385 };
386 
jdwp_socket_close(asocket * s)387 static void jdwp_socket_close(asocket* s) {
388     D("LS(%d): closing jdwp socket", s->id);
389 
390     if (s->peer) {
391         D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
392         s->peer->peer = nullptr;
393         s->peer->close(s->peer);
394         s->peer = nullptr;
395     }
396 
397     remove_socket(s);
398     delete s;
399 }
400 
jdwp_socket_enqueue(asocket * s,apacket::payload_type)401 static int jdwp_socket_enqueue(asocket* s, apacket::payload_type) {
402     /* you can't write to this asocket */
403     D("LS(%d): JDWP socket received data?", s->id);
404     s->peer->close(s->peer);
405     return -1;
406 }
407 
jdwp_socket_ready(asocket * s)408 static void jdwp_socket_ready(asocket* s) {
409     JdwpSocket* jdwp = (JdwpSocket*)s;
410     asocket* peer = jdwp->peer;
411 
412     /* on the first call, send the list of pids,
413      * on the second one, close the connection
414      */
415     if (!jdwp->pass) {
416         apacket::payload_type data;
417         data.resize(s->get_max_payload());
418         size_t len = jdwp_process_list(&data[0], data.size());
419         data.resize(len);
420         peer->enqueue(peer, std::move(data));
421         jdwp->pass = true;
422     } else {
423         peer->close(peer);
424     }
425 }
426 
create_jdwp_service_socket(void)427 asocket* create_jdwp_service_socket(void) {
428     JdwpSocket* s = new JdwpSocket();
429 
430     if (!s) {
431         LOG(FATAL) << "failed to allocate JdwpSocket";
432     }
433 
434     install_local_socket(s);
435 
436     s->ready = jdwp_socket_ready;
437     s->enqueue = jdwp_socket_enqueue;
438     s->close = jdwp_socket_close;
439     s->pass = false;
440 
441     return s;
442 }
443 
444 /** "track-jdwp" local service implementation
445  ** this periodically sends the list of known JDWP process pids
446  ** to the client...
447  **/
448 
449 struct JdwpTracker : public asocket {
450     bool need_initial;
451 };
452 
453 static auto& _jdwp_trackers = *new std::vector<std::unique_ptr<JdwpTracker>>();
454 
jdwp_process_list_updated(void)455 static void jdwp_process_list_updated(void) {
456     std::string data;
457     data.resize(1024);
458     data.resize(jdwp_process_list_msg(&data[0], data.size()));
459 
460     for (auto& t : _jdwp_trackers) {
461         if (t->peer) {
462             // The tracker might not have been connected yet.
463             apacket::payload_type payload(data.begin(), data.end());
464             t->peer->enqueue(t->peer, std::move(payload));
465         }
466     }
467 }
468 
jdwp_tracker_close(asocket * s)469 static void jdwp_tracker_close(asocket* s) {
470     D("LS(%d): destroying jdwp tracker service", s->id);
471 
472     if (s->peer) {
473         D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
474         s->peer->peer = nullptr;
475         s->peer->close(s->peer);
476         s->peer = nullptr;
477     }
478 
479     remove_socket(s);
480 
481     auto pred = [s](const auto& tracker) { return tracker.get() == s; };
482     _jdwp_trackers.erase(std::remove_if(_jdwp_trackers.begin(), _jdwp_trackers.end(), pred),
483                          _jdwp_trackers.end());
484 }
485 
jdwp_tracker_ready(asocket * s)486 static void jdwp_tracker_ready(asocket* s) {
487     JdwpTracker* t = (JdwpTracker*)s;
488 
489     if (t->need_initial) {
490         apacket::payload_type data;
491         data.resize(s->get_max_payload());
492         data.resize(jdwp_process_list_msg(&data[0], data.size()));
493         t->need_initial = false;
494         s->peer->enqueue(s->peer, std::move(data));
495     }
496 }
497 
jdwp_tracker_enqueue(asocket * s,apacket::payload_type)498 static int jdwp_tracker_enqueue(asocket* s, apacket::payload_type) {
499     /* you can't write to this socket */
500     D("LS(%d): JDWP tracker received data?", s->id);
501     s->peer->close(s->peer);
502     return -1;
503 }
504 
create_jdwp_tracker_service_socket(void)505 asocket* create_jdwp_tracker_service_socket(void) {
506     auto t = std::make_unique<JdwpTracker>();
507     if (!t) {
508         LOG(FATAL) << "failed to allocate JdwpTracker";
509     }
510 
511     memset(t.get(), 0, sizeof(asocket));
512 
513     install_local_socket(t.get());
514     D("LS(%d): created new jdwp tracker service", t->id);
515 
516     t->ready = jdwp_tracker_ready;
517     t->enqueue = jdwp_tracker_enqueue;
518     t->close = jdwp_tracker_close;
519     t->need_initial = true;
520 
521     asocket* result = t.get();
522 
523     _jdwp_trackers.emplace_back(std::move(t));
524 
525     return result;
526 }
527 
init_jdwp(void)528 int init_jdwp(void) {
529     return jdwp_control_init(&_jdwp_control, JDWP_CONTROL_NAME, JDWP_CONTROL_NAME_LEN);
530 }
531 
532 #endif /* !ADB_HOST */
533