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