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