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