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/* implement the "debug-ports" and "track-debug-ports" device services */
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 <unistd.h>
28
29#include "adb.h"
30#include "adb_utils.h"
31
32/* here's how these things work.
33
34   when adbd starts, it creates a unix server socket
35   named @vm-debug-control (@ is a shortcut for "first byte is zero"
36   to use the private namespace instead of the file system)
37
38   when a new JDWP daemon thread starts in a new VM process, it creates
39   a connection to @vm-debug-control to announce its availability.
40
41
42     JDWP thread                             @vm-debug-control
43         |                                         |
44         |------------------------------->         |
45         | hello I'm in process <pid>              |
46         |                                         |
47         |                                         |
48
49    the connection is kept alive. it will be closed automatically if
50    the JDWP process terminates (this allows adbd to detect dead
51    processes).
52
53    adbd thus maintains a list of "active" JDWP processes. it can send
54    its content to clients through the "device:debug-ports" service,
55    or even updates through the "device:track-debug-ports" service.
56
57    when a debugger wants to connect, it simply runs the command
58    equivalent to  "adb forward tcp:<hostport> jdwp:<pid>"
59
60    "jdwp:<pid>" is a new forward destination format used to target
61    a given JDWP process on the device. when sutch a request arrives,
62    adbd does the following:
63
64      - first, it calls socketpair() to create a pair of equivalent
65        sockets.
66
67      - it attaches the first socket in the pair to a local socket
68        which is itself attached to the transport's remote socket:
69
70
71      - it sends the file descriptor of the second socket directly
72        to the JDWP process with the help of sendmsg()
73
74
75     JDWP thread                             @vm-debug-control
76         |                                         |
77         |                  <----------------------|
78         |           OK, try this file descriptor  |
79         |                                         |
80         |                                         |
81
82   then, the JDWP thread uses this new socket descriptor as its
83   pass-through connection to the debugger (and receives the
84   JDWP-Handshake message, answers to it, etc...)
85
86   this gives the following graphics:
87                    ____________________________________
88                   |                                    |
89                   |          ADB Server (host)         |
90                   |                                    |
91        Debugger <---> LocalSocket <----> RemoteSocket  |
92                   |                           ^^       |
93                   |___________________________||_______|
94                                               ||
95                                     Transport ||
96           (TCP for emulator - USB for device) ||
97                                               ||
98                    ___________________________||_______
99                   |                           ||       |
100                   |          ADBD  (device)   ||       |
101                   |                           VV       |
102         JDWP <======> LocalSocket <----> RemoteSocket  |
103                   |                                    |
104                   |____________________________________|
105
106    due to the way adb works, this doesn't need a special socket
107    type or fancy handling of socket termination if either the debugger
108    or the JDWP process closes the connection.
109
110    THIS IS THE SIMPLEST IMPLEMENTATION I COULD FIND, IF YOU HAPPEN
111    TO HAVE A BETTER IDEA, LET ME KNOW - Digit
112
113**********************************************************************/
114
115/** JDWP PID List Support Code
116 ** for each JDWP process, we record its pid and its connected socket
117 **/
118
119#define  MAX_OUT_FDS   4
120
121#if !ADB_HOST
122
123#include <sys/socket.h>
124#include <sys/un.h>
125
126struct JdwpProcess {
127    JdwpProcess*  next;
128    JdwpProcess*  prev;
129    int           pid;
130    int           socket;
131    fdevent*      fde;
132
133    char          in_buff[4];  /* input character to read PID */
134    int           in_len;      /* number from JDWP process    */
135
136    int           out_fds[MAX_OUT_FDS]; /* output array of file descriptors */
137    int           out_count;            /* to send to the JDWP process      */
138};
139
140static JdwpProcess  _jdwp_list;
141
142static int
143jdwp_process_list( char*  buffer, int  bufferlen )
144{
145    char*         end  = buffer + bufferlen;
146    char*         p    = buffer;
147    JdwpProcess*  proc = _jdwp_list.next;
148
149    for ( ; proc != &_jdwp_list; proc = proc->next ) {
150        int  len;
151
152        /* skip transient connections */
153        if (proc->pid < 0)
154            continue;
155
156        len = snprintf(p, end-p, "%d\n", proc->pid);
157        if (p + len >= end)
158            break;
159        p += len;
160    }
161    p[0] = 0;
162    return (p - buffer);
163}
164
165
166static int
167jdwp_process_list_msg( char*  buffer, int  bufferlen )
168{
169    char  head[5];
170    int   len = jdwp_process_list( buffer+4, bufferlen-4 );
171    snprintf(head, sizeof head, "%04x", len);
172    memcpy(buffer, head, 4);
173    return len + 4;
174}
175
176
177static void  jdwp_process_list_updated(void);
178
179static void
180jdwp_process_free( JdwpProcess*  proc )
181{
182    if (proc) {
183        int  n;
184
185        proc->prev->next = proc->next;
186        proc->next->prev = proc->prev;
187
188        if (proc->socket >= 0) {
189            adb_shutdown(proc->socket);
190            adb_close(proc->socket);
191            proc->socket = -1;
192        }
193
194        if (proc->fde != NULL) {
195            fdevent_destroy(proc->fde);
196            proc->fde = NULL;
197        }
198        proc->pid = -1;
199
200        for (n = 0; n < proc->out_count; n++) {
201            adb_close(proc->out_fds[n]);
202        }
203        proc->out_count = 0;
204
205        free(proc);
206
207        jdwp_process_list_updated();
208    }
209}
210
211
212static void  jdwp_process_event(int, unsigned, void*);  /* forward */
213
214
215static JdwpProcess*
216jdwp_process_alloc( int  socket )
217{
218    JdwpProcess* proc = reinterpret_cast<JdwpProcess*>(
219        calloc(1, sizeof(*proc)));
220
221    if (proc == NULL) {
222        D("not enough memory to create new JDWP process");
223        return NULL;
224    }
225
226    proc->socket = socket;
227    proc->pid    = -1;
228    proc->next   = proc;
229    proc->prev   = proc;
230
231    proc->fde = fdevent_create( socket, jdwp_process_event, proc );
232    if (proc->fde == NULL) {
233        D("could not create fdevent for new JDWP process" );
234        free(proc);
235        return NULL;
236    }
237
238    proc->fde->state |= FDE_DONT_CLOSE;
239    proc->in_len      = 0;
240    proc->out_count   = 0;
241
242    /* append to list */
243    proc->next = &_jdwp_list;
244    proc->prev = proc->next->prev;
245
246    proc->prev->next = proc;
247    proc->next->prev = proc;
248
249    /* start by waiting for the PID */
250    fdevent_add(proc->fde, FDE_READ);
251
252    return proc;
253}
254
255
256static void
257jdwp_process_event( int  socket, unsigned  events, void*  _proc )
258{
259    JdwpProcess*  proc = reinterpret_cast<JdwpProcess*>(_proc);
260
261    if (events & FDE_READ) {
262        if (proc->pid < 0) {
263            /* read the PID as a 4-hexchar string */
264            char*  p    = proc->in_buff + proc->in_len;
265            int    size = 4 - proc->in_len;
266            char   temp[5];
267            while (size > 0) {
268                int  len = recv( socket, p, size, 0 );
269                if (len < 0) {
270                    if (errno == EINTR)
271                        continue;
272                    if (errno == EAGAIN)
273                        return;
274                    /* this can fail here if the JDWP process crashes very fast */
275                    D("weird unknown JDWP process failure: %s",
276                      strerror(errno));
277
278                    goto CloseProcess;
279                }
280                if (len == 0) {  /* end of stream ? */
281                    D("weird end-of-stream from unknown JDWP process");
282                    goto CloseProcess;
283                }
284                p            += len;
285                proc->in_len += len;
286                size         -= len;
287            }
288            /* we have read 4 characters, now decode the pid */
289            memcpy(temp, proc->in_buff, 4);
290            temp[4] = 0;
291
292            if (sscanf( temp, "%04x", &proc->pid ) != 1) {
293                D("could not decode JDWP %p PID number: '%s'", proc, temp);
294                goto CloseProcess;
295            }
296
297            /* all is well, keep reading to detect connection closure */
298            D("Adding pid %d to jdwp process list", proc->pid);
299            jdwp_process_list_updated();
300        }
301        else
302        {
303            /* the pid was read, if we get there it's probably because the connection
304             * was closed (e.g. the JDWP process exited or crashed) */
305            char  buf[32];
306
307            for (;;) {
308                int  len = recv(socket, buf, sizeof(buf), 0);
309
310                if (len <= 0) {
311                    if (len < 0 && errno == EINTR)
312                        continue;
313                    if (len < 0 && errno == EAGAIN)
314                        return;
315                    else {
316                        D("terminating JDWP %d connection: %s", proc->pid,
317                          strerror(errno));
318                        break;
319                    }
320                }
321                else {
322                    D( "ignoring unexpected JDWP %d control socket activity (%d bytes)",
323                       proc->pid, len );
324                }
325            }
326
327        CloseProcess:
328            if (proc->pid >= 0) {
329                D( "remove pid %d to jdwp process list", proc->pid );
330            }
331            jdwp_process_free(proc);
332            return;
333        }
334    }
335
336    if (events & FDE_WRITE) {
337        D("trying to write to JDWP pid controli (count=%d first=%d) %d",
338          proc->pid, proc->out_count, proc->out_fds[0]);
339        if (proc->out_count > 0) {
340            int  fd = proc->out_fds[0];
341            int  n, ret;
342            struct cmsghdr*  cmsg;
343            struct msghdr    msg;
344            struct iovec     iov;
345            char             dummy = '!';
346            char             buffer[sizeof(struct cmsghdr) + sizeof(int)];
347
348            iov.iov_base       = &dummy;
349            iov.iov_len        = 1;
350            msg.msg_name       = NULL;
351            msg.msg_namelen    = 0;
352            msg.msg_iov        = &iov;
353            msg.msg_iovlen     = 1;
354            msg.msg_flags      = 0;
355            msg.msg_control    = buffer;
356            msg.msg_controllen = sizeof(buffer);
357
358            cmsg = CMSG_FIRSTHDR(&msg);
359            cmsg->cmsg_len   = msg.msg_controllen;
360            cmsg->cmsg_level = SOL_SOCKET;
361            cmsg->cmsg_type  = SCM_RIGHTS;
362            ((int*)CMSG_DATA(cmsg))[0] = fd;
363
364            if (!set_file_block_mode(proc->socket, true)) {
365                VLOG(JDWP) << "failed to set blocking mode for fd " << proc->socket;
366                goto CloseProcess;
367            }
368
369            for (;;) {
370                ret = sendmsg(proc->socket, &msg, 0);
371                if (ret >= 0) {
372                    adb_close(fd);
373                    break;
374                }
375                if (errno == EINTR)
376                    continue;
377                D("sending new file descriptor to JDWP %d failed: %s",
378                  proc->pid, strerror(errno));
379                goto CloseProcess;
380            }
381
382            D("sent file descriptor %d to JDWP process %d",
383              fd, proc->pid);
384
385            for (n = 1; n < proc->out_count; n++)
386                proc->out_fds[n-1] = proc->out_fds[n];
387
388            if (!set_file_block_mode(proc->socket, false)) {
389                VLOG(JDWP) << "failed to set non-blocking mode for fd " << proc->socket;
390                goto CloseProcess;
391            }
392
393            if (--proc->out_count == 0)
394                fdevent_del( proc->fde, FDE_WRITE );
395        }
396    }
397}
398
399
400int
401create_jdwp_connection_fd(int  pid)
402{
403    JdwpProcess*  proc = _jdwp_list.next;
404
405    D("looking for pid %d in JDWP process list", pid);
406    for ( ; proc != &_jdwp_list; proc = proc->next ) {
407        if (proc->pid == pid) {
408            goto FoundIt;
409        }
410    }
411    D("search failed !!");
412    return -1;
413
414FoundIt:
415    {
416        int  fds[2];
417
418        if (proc->out_count >= MAX_OUT_FDS) {
419            D("%s: too many pending JDWP connection for pid %d",
420              __FUNCTION__, pid);
421            return -1;
422        }
423
424        if (adb_socketpair(fds) < 0) {
425            D("%s: socket pair creation failed: %s",
426              __FUNCTION__, strerror(errno));
427            return -1;
428        }
429        D("socketpair: (%d,%d)", fds[0], fds[1]);
430
431        proc->out_fds[ proc->out_count ] = fds[1];
432        if (++proc->out_count == 1)
433            fdevent_add( proc->fde, FDE_WRITE );
434
435        return fds[0];
436    }
437}
438
439/**  VM DEBUG CONTROL SOCKET
440 **
441 **  we do implement a custom asocket to receive the data
442 **/
443
444/* name of the debug control Unix socket */
445#define  JDWP_CONTROL_NAME      "\0jdwp-control"
446#define  JDWP_CONTROL_NAME_LEN  (sizeof(JDWP_CONTROL_NAME)-1)
447
448struct JdwpControl {
449    int       listen_socket;
450    fdevent*  fde;
451};
452
453
454static void
455jdwp_control_event(int  s, unsigned events, void*  user);
456
457
458static int
459jdwp_control_init( JdwpControl*  control,
460                   const char*   sockname,
461                   int           socknamelen )
462{
463    sockaddr_un   addr;
464    socklen_t     addrlen;
465    int           s;
466    int           maxpath = sizeof(addr.sun_path);
467    int           pathlen = socknamelen;
468
469    if (pathlen >= maxpath) {
470        D( "vm debug control socket name too long (%d extra chars)",
471           pathlen+1-maxpath );
472        return -1;
473    }
474
475    memset(&addr, 0, sizeof(addr));
476    addr.sun_family = AF_UNIX;
477    memcpy(addr.sun_path, sockname, socknamelen);
478
479    s = socket( AF_UNIX, SOCK_STREAM, 0 );
480    if (s < 0) {
481        D( "could not create vm debug control socket. %d: %s",
482           errno, strerror(errno));
483        return -1;
484    }
485
486    addrlen = (pathlen + sizeof(addr.sun_family));
487
488    if (bind(s, reinterpret_cast<sockaddr*>(&addr), addrlen) < 0) {
489        D( "could not bind vm debug control socket: %d: %s",
490           errno, strerror(errno) );
491        adb_close(s);
492        return -1;
493    }
494
495    if ( listen(s, 4) < 0 ) {
496        D("listen failed in jdwp control socket: %d: %s",
497          errno, strerror(errno));
498        adb_close(s);
499        return -1;
500    }
501
502    control->listen_socket = s;
503
504    control->fde = fdevent_create(s, jdwp_control_event, control);
505    if (control->fde == NULL) {
506        D( "could not create fdevent for jdwp control socket" );
507        adb_close(s);
508        return -1;
509    }
510
511    /* only wait for incoming connections */
512    fdevent_add(control->fde, FDE_READ);
513    close_on_exec(s);
514
515    D("jdwp control socket started (%d)", control->listen_socket);
516    return 0;
517}
518
519
520static void
521jdwp_control_event( int  s, unsigned  events, void*  _control )
522{
523    JdwpControl*  control = (JdwpControl*) _control;
524
525    if (events & FDE_READ) {
526        sockaddr_storage   ss;
527        sockaddr*          addrp = reinterpret_cast<sockaddr*>(&ss);
528        socklen_t          addrlen = sizeof(ss);
529        int                s = -1;
530        JdwpProcess*       proc;
531
532        do {
533            s = adb_socket_accept(control->listen_socket, addrp, &addrlen);
534            if (s < 0) {
535                if (errno == EINTR)
536                    continue;
537                if (errno == ECONNABORTED) {
538                    /* oops, the JDWP process died really quick */
539                    D("oops, the JDWP process died really quick");
540                    return;
541                }
542                /* the socket is probably closed ? */
543                D( "weird accept() failed on jdwp control socket: %s",
544                   strerror(errno) );
545                return;
546            }
547        }
548        while (s < 0);
549
550        proc = jdwp_process_alloc( s );
551        if (proc == NULL)
552            return;
553    }
554}
555
556
557static JdwpControl   _jdwp_control;
558
559/** "jdwp" local service implementation
560 ** this simply returns the list of known JDWP process pids
561 **/
562
563struct JdwpSocket {
564    asocket  socket;
565    int      pass;
566};
567
568static void
569jdwp_socket_close( asocket*  s )
570{
571    asocket*  peer = s->peer;
572
573    remove_socket(s);
574
575    if (peer) {
576        peer->peer = NULL;
577        peer->close(peer);
578    }
579    free(s);
580}
581
582static int
583jdwp_socket_enqueue( asocket*  s, apacket*  p )
584{
585    /* you can't write to this asocket */
586    put_apacket(p);
587    s->peer->close(s->peer);
588    return -1;
589}
590
591
592static void
593jdwp_socket_ready( asocket*  s )
594{
595    JdwpSocket*  jdwp = (JdwpSocket*)s;
596    asocket*     peer = jdwp->socket.peer;
597
598   /* on the first call, send the list of pids,
599    * on the second one, close the connection
600    */
601    if (jdwp->pass == 0) {
602        apacket*  p = get_apacket();
603        p->len = jdwp_process_list((char*)p->data, s->get_max_payload());
604        peer->enqueue(peer, p);
605        jdwp->pass = 1;
606    }
607    else {
608        peer->close(peer);
609    }
610}
611
612asocket*
613create_jdwp_service_socket( void )
614{
615    JdwpSocket* s = reinterpret_cast<JdwpSocket*>(calloc(sizeof(*s), 1));
616
617    if (s == NULL)
618        return NULL;
619
620    install_local_socket(&s->socket);
621
622    s->socket.ready   = jdwp_socket_ready;
623    s->socket.enqueue = jdwp_socket_enqueue;
624    s->socket.close   = jdwp_socket_close;
625    s->pass           = 0;
626
627    return &s->socket;
628}
629
630/** "track-jdwp" local service implementation
631 ** this periodically sends the list of known JDWP process pids
632 ** to the client...
633 **/
634
635struct JdwpTracker {
636    asocket       socket;
637    JdwpTracker*  next;
638    JdwpTracker*  prev;
639    int           need_update;
640};
641
642static JdwpTracker   _jdwp_trackers_list;
643
644
645static void
646jdwp_process_list_updated(void)
647{
648    char             buffer[1024];
649    int              len;
650    JdwpTracker*  t = _jdwp_trackers_list.next;
651
652    len = jdwp_process_list_msg(buffer, sizeof(buffer));
653
654    for ( ; t != &_jdwp_trackers_list; t = t->next ) {
655        apacket*  p    = get_apacket();
656        asocket*  peer = t->socket.peer;
657        memcpy(p->data, buffer, len);
658        p->len = len;
659        peer->enqueue( peer, p );
660    }
661}
662
663static void
664jdwp_tracker_close( asocket*  s )
665{
666    JdwpTracker*  tracker = (JdwpTracker*) s;
667    asocket*      peer    = s->peer;
668
669    if (peer) {
670        peer->peer = NULL;
671        peer->close(peer);
672    }
673
674    remove_socket(s);
675
676    tracker->prev->next = tracker->next;
677    tracker->next->prev = tracker->prev;
678
679    free(s);
680}
681
682static void
683jdwp_tracker_ready( asocket*  s )
684{
685    JdwpTracker*  t = (JdwpTracker*) s;
686
687    if (t->need_update) {
688        apacket*  p = get_apacket();
689        t->need_update = 0;
690        p->len = jdwp_process_list_msg((char*)p->data, s->get_max_payload());
691        s->peer->enqueue(s->peer, p);
692    }
693}
694
695static int
696jdwp_tracker_enqueue( asocket*  s, apacket*  p )
697{
698    /* you can't write to this socket */
699    put_apacket(p);
700    s->peer->close(s->peer);
701    return -1;
702}
703
704
705asocket*
706create_jdwp_tracker_service_socket( void )
707{
708    JdwpTracker* t = reinterpret_cast<JdwpTracker*>(calloc(sizeof(*t), 1));
709
710    if (t == NULL)
711        return NULL;
712
713    t->next = &_jdwp_trackers_list;
714    t->prev = t->next->prev;
715
716    t->next->prev = t;
717    t->prev->next = t;
718
719    install_local_socket(&t->socket);
720
721    t->socket.ready   = jdwp_tracker_ready;
722    t->socket.enqueue = jdwp_tracker_enqueue;
723    t->socket.close   = jdwp_tracker_close;
724    t->need_update    = 1;
725
726    return &t->socket;
727}
728
729
730int
731init_jdwp(void)
732{
733    _jdwp_list.next = &_jdwp_list;
734    _jdwp_list.prev = &_jdwp_list;
735
736    _jdwp_trackers_list.next = &_jdwp_trackers_list;
737    _jdwp_trackers_list.prev = &_jdwp_trackers_list;
738
739    return jdwp_control_init( &_jdwp_control,
740                              JDWP_CONTROL_NAME,
741                              JDWP_CONTROL_NAME_LEN );
742}
743
744#endif /* !ADB_HOST */
745