• 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 <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 
45 using android::base::borrowed_fd;
46 using android::base::unique_fd;
47 
48 /* here's how these things work.
49 
50    when adbd starts, it creates a unix server socket
51    named @jdwp-control (@ is a shortcut for "first byte is zero"
52    to use the private namespace instead of the file system)
53 
54    when a new JDWP daemon thread starts in a new VM process, it creates
55    a connection to @jdwp-control to announce its availability.
56 
57 
58      JDWP thread                             @jdwp-control
59          |                                         |
60          |------------------------------->         |
61          | hello I'm in process <pid>              |
62          |                                         |
63          |                                         |
64 
65     the connection is kept alive. it will be closed automatically if
66     the JDWP process terminates (this allows adbd to detect dead
67     processes).
68 
69     adbd thus maintains a list of "active" JDWP processes. it can send
70     its content to clients through the "device:debug-ports" service,
71     or even updates through the "device:track-debug-ports" service.
72 
73     when a debugger wants to connect, it simply runs the command
74     equivalent to  "adb forward tcp:<hostport> jdwp:<pid>"
75 
76     "jdwp:<pid>" is a new forward destination format used to target
77     a given JDWP process on the device. when sutch a request arrives,
78     adbd does the following:
79 
80       - first, it calls socketpair() to create a pair of equivalent
81         sockets.
82 
83       - it attaches the first socket in the pair to a local socket
84         which is itself attached to the transport's remote socket:
85 
86 
87       - it sends the file descriptor of the second socket directly
88         to the JDWP process with the help of sendmsg()
89 
90 
91      JDWP thread                             @jdwp-control
92          |                                         |
93          |                  <----------------------|
94          |           OK, try this file descriptor  |
95          |                                         |
96          |                                         |
97 
98    then, the JDWP thread uses this new socket descriptor as its
99    pass-through connection to the debugger (and receives the
100    JDWP-Handshake message, answers to it, etc...)
101 
102    this gives the following graphics:
103                     ____________________________________
104                    |                                    |
105                    |          ADB Server (host)         |
106                    |                                    |
107         Debugger <---> LocalSocket <----> RemoteSocket  |
108                    |                           ^^       |
109                    |___________________________||_______|
110                                                ||
111                                      Transport ||
112            (TCP for emulator - USB for device) ||
113                                                ||
114                     ___________________________||_______
115                    |                           ||       |
116                    |          ADBD  (device)   ||       |
117                    |                           VV       |
118          JDWP <======> LocalSocket <----> RemoteSocket  |
119                    |                                    |
120                    |____________________________________|
121 
122     due to the way adb works, this doesn't need a special socket
123     type or fancy handling of socket termination if either the debugger
124     or the JDWP process closes the connection.
125 
126     THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
127     TO HAVE A BETTER IDEA, LET ME KNOW - Digit
128 
129 **********************************************************************/
130 
131 /** JDWP PID List Support Code
132  ** for each JDWP process, we record its pid and its connected socket
133  **/
134 
135 static void jdwp_process_event(int socket, unsigned events, void* _proc);
136 static void jdwp_process_list_updated(void);
137 
138 struct JdwpProcess;
139 static auto& _jdwp_list = *new std::list<std::unique_ptr<JdwpProcess>>();
140 
141 struct JdwpProcess {
JdwpProcessJdwpProcess142     JdwpProcess(unique_fd socket, pid_t pid) {
143         CHECK(pid != 0);
144 
145         this->socket = socket;
146         this->pid = pid;
147         this->fde = fdevent_create(socket.release(), jdwp_process_event, this);
148 
149         if (!this->fde) {
150             LOG(FATAL) << "could not create fdevent for new JDWP process";
151         }
152     }
153 
~JdwpProcessJdwpProcess154     ~JdwpProcess() {
155         if (this->socket >= 0) {
156             adb_shutdown(this->socket);
157             this->socket = -1;
158         }
159 
160         if (this->fde) {
161             fdevent_destroy(this->fde);
162             this->fde = nullptr;
163         }
164 
165         out_fds.clear();
166     }
167 
RemoveFromListJdwpProcess168     void RemoveFromList() {
169         auto pred = [this](const auto& proc) { return proc.get() == this; };
170         _jdwp_list.remove_if(pred);
171     }
172 
173     borrowed_fd socket = -1;
174     int32_t pid = -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         std::string next = std::to_string(proc->pid) + "\n";
185         if (temp.length() + next.length() > bufferlen) {
186             D("truncating JDWP process list (max len = %zu)", bufferlen);
187             break;
188         }
189         temp.append(next);
190     }
191 
192     memcpy(buffer, temp.data(), temp.length());
193     return temp.length();
194 }
195 
jdwp_process_list_msg(char * buffer,size_t bufferlen)196 static size_t jdwp_process_list_msg(char* buffer, size_t bufferlen) {
197     // Message is length-prefixed with 4 hex digits in ASCII.
198     static constexpr size_t header_len = 4;
199     if (bufferlen < header_len) {
200         LOG(FATAL) << "invalid JDWP process list buffer size: " << bufferlen;
201     }
202 
203     char head[header_len + 1];
204     size_t len = jdwp_process_list(buffer + header_len, bufferlen - header_len);
205     snprintf(head, sizeof head, "%04zx", len);
206     memcpy(buffer, head, header_len);
207     return len + header_len;
208 }
209 
jdwp_process_event(int socket,unsigned events,void * _proc)210 static void jdwp_process_event(int socket, unsigned events, void* _proc) {
211     JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(_proc);
212     CHECK_EQ(socket, proc->socket.get());
213 
214     if (events & FDE_READ) {
215         // We already have the PID, if we can read from the socket, we've probably hit EOF.
216         D("terminating JDWP connection %d", proc->pid);
217         goto CloseProcess;
218     }
219 
220     if (events & FDE_WRITE) {
221         D("trying to send fd to JDWP process (count = %zu)", proc->out_fds.size());
222         CHECK(!proc->out_fds.empty());
223 
224         int fd = proc->out_fds.back().get();
225         if (android::base::SendFileDescriptors(socket, "", 1, fd) != 1) {
226             D("sending new file descriptor to JDWP %d failed: %s", proc->pid, strerror(errno));
227             goto CloseProcess;
228         }
229 
230         D("sent file descriptor %d to JDWP process %d", fd, proc->pid);
231 
232         proc->out_fds.pop_back();
233         if (proc->out_fds.empty()) {
234             fdevent_del(proc->fde, FDE_WRITE);
235         }
236     }
237 
238     return;
239 
240 CloseProcess:
241     proc->RemoveFromList();
242     jdwp_process_list_updated();
243 }
244 
create_jdwp_connection_fd(int pid)245 unique_fd create_jdwp_connection_fd(int pid) {
246     D("looking for pid %d in JDWP process list", pid);
247 
248     for (auto& proc : _jdwp_list) {
249         if (proc->pid == pid) {
250             int fds[2];
251 
252             if (adb_socketpair(fds) < 0) {
253                 D("%s: socket pair creation failed: %s", __FUNCTION__, strerror(errno));
254                 return unique_fd{};
255             }
256             D("socketpair: (%d,%d)", fds[0], fds[1]);
257 
258             proc->out_fds.emplace_back(fds[1]);
259             if (proc->out_fds.size() == 1) {
260                 fdevent_add(proc->fde, FDE_WRITE);
261             }
262 
263             return unique_fd{fds[0]};
264         }
265     }
266     D("search failed !!");
267     return unique_fd{};
268 }
269 
270 /** "jdwp" local service implementation
271  ** this simply returns the list of known JDWP process pids
272  **/
273 
274 struct JdwpSocket : public asocket {
275     bool pass = false;
276 };
277 
jdwp_socket_close(asocket * s)278 static void jdwp_socket_close(asocket* s) {
279     D("LS(%d): closing jdwp socket", s->id);
280 
281     if (s->peer) {
282         D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
283         s->peer->peer = nullptr;
284         s->peer->close(s->peer);
285         s->peer = nullptr;
286     }
287 
288     remove_socket(s);
289     delete s;
290 }
291 
jdwp_socket_enqueue(asocket * s,apacket::payload_type)292 static int jdwp_socket_enqueue(asocket* s, apacket::payload_type) {
293     /* you can't write to this asocket */
294     D("LS(%d): JDWP socket received data?", s->id);
295     s->peer->close(s->peer);
296     return -1;
297 }
298 
jdwp_socket_ready(asocket * s)299 static void jdwp_socket_ready(asocket* s) {
300     JdwpSocket* jdwp = (JdwpSocket*)s;
301     asocket* peer = jdwp->peer;
302 
303     /* on the first call, send the list of pids,
304      * on the second one, close the connection
305      */
306     if (!jdwp->pass) {
307         apacket::payload_type data;
308         data.resize(s->get_max_payload());
309         size_t len = jdwp_process_list(&data[0], data.size());
310         data.resize(len);
311         peer->enqueue(peer, std::move(data));
312         jdwp->pass = true;
313     } else {
314         peer->close(peer);
315     }
316 }
317 
create_jdwp_service_socket(void)318 asocket* create_jdwp_service_socket(void) {
319     JdwpSocket* s = new JdwpSocket();
320 
321     if (!s) {
322         LOG(FATAL) << "failed to allocate JdwpSocket";
323     }
324 
325     install_local_socket(s);
326 
327     s->ready = jdwp_socket_ready;
328     s->enqueue = jdwp_socket_enqueue;
329     s->close = jdwp_socket_close;
330     s->pass = false;
331 
332     return s;
333 }
334 
335 /** "track-jdwp" local service implementation
336  ** this periodically sends the list of known JDWP process pids
337  ** to the client...
338  **/
339 
340 struct JdwpTracker : public asocket {
341     bool need_initial;
342 };
343 
344 static auto& _jdwp_trackers = *new std::vector<std::unique_ptr<JdwpTracker>>();
345 
jdwp_process_list_updated(void)346 static void jdwp_process_list_updated(void) {
347     std::string data;
348     data.resize(1024);
349     data.resize(jdwp_process_list_msg(&data[0], data.size()));
350 
351     for (auto& t : _jdwp_trackers) {
352         if (t->peer) {
353             // The tracker might not have been connected yet.
354             apacket::payload_type payload(data.begin(), data.end());
355             t->peer->enqueue(t->peer, std::move(payload));
356         }
357     }
358 }
359 
jdwp_tracker_close(asocket * s)360 static void jdwp_tracker_close(asocket* s) {
361     D("LS(%d): destroying jdwp tracker service", s->id);
362 
363     if (s->peer) {
364         D("LS(%d) peer->close()ing peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd);
365         s->peer->peer = nullptr;
366         s->peer->close(s->peer);
367         s->peer = nullptr;
368     }
369 
370     remove_socket(s);
371 
372     auto pred = [s](const auto& tracker) { return tracker.get() == s; };
373     _jdwp_trackers.erase(std::remove_if(_jdwp_trackers.begin(), _jdwp_trackers.end(), pred),
374                          _jdwp_trackers.end());
375 }
376 
jdwp_tracker_ready(asocket * s)377 static void jdwp_tracker_ready(asocket* s) {
378     JdwpTracker* t = (JdwpTracker*)s;
379 
380     if (t->need_initial) {
381         apacket::payload_type data;
382         data.resize(s->get_max_payload());
383         data.resize(jdwp_process_list_msg(&data[0], data.size()));
384         t->need_initial = false;
385         s->peer->enqueue(s->peer, std::move(data));
386     }
387 }
388 
jdwp_tracker_enqueue(asocket * s,apacket::payload_type)389 static int jdwp_tracker_enqueue(asocket* s, apacket::payload_type) {
390     /* you can't write to this socket */
391     D("LS(%d): JDWP tracker received data?", s->id);
392     s->peer->close(s->peer);
393     return -1;
394 }
395 
create_jdwp_tracker_service_socket(void)396 asocket* create_jdwp_tracker_service_socket(void) {
397     auto t = std::make_unique<JdwpTracker>();
398     if (!t) {
399         LOG(FATAL) << "failed to allocate JdwpTracker";
400     }
401 
402     memset(t.get(), 0, sizeof(asocket));
403 
404     install_local_socket(t.get());
405     D("LS(%d): created new jdwp tracker service", t->id);
406 
407     t->ready = jdwp_tracker_ready;
408     t->enqueue = jdwp_tracker_enqueue;
409     t->close = jdwp_tracker_close;
410     t->need_initial = true;
411 
412     asocket* result = t.get();
413 
414     _jdwp_trackers.emplace_back(std::move(t));
415 
416     return result;
417 }
418 
init_jdwp(void)419 int init_jdwp(void) {
420     std::thread([]() {
421         adb_thread_setname("jdwp control");
422         adbconnection_listen([](int fd, pid_t pid) {
423             LOG(INFO) << "jdwp connection from " << pid;
424             fdevent_run_on_main_thread([fd, pid] {
425                 unique_fd ufd(fd);
426                 auto proc = std::make_unique<JdwpProcess>(std::move(ufd), pid);
427                 if (!proc) {
428                     LOG(FATAL) << "failed to allocate JdwpProcess";
429                 }
430                 _jdwp_list.emplace_back(std::move(proc));
431                 jdwp_process_list_updated();
432             });
433         });
434     }).detach();
435     return 0;
436 }
437 
438 #endif /* !ADB_HOST */
439