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