• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 #include <stdlib.h>
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <errno.h>
22 
23 #include "sysdeps.h"
24 
25 #define  TRACE_TAG  TRACE_SERVICES
26 #include "adb.h"
27 #include "file_sync_service.h"
28 
29 #if ADB_HOST
30 #  ifndef HAVE_WINSOCK
31 #    include <netinet/in.h>
32 #    include <netdb.h>
33 #    include <sys/ioctl.h>
34 #  endif
35 #else
36 #  include <cutils/android_reboot.h>
37 #endif
38 
39 typedef struct stinfo stinfo;
40 
41 struct stinfo {
42     void (*func)(int fd, void *cookie);
43     int fd;
44     void *cookie;
45 };
46 
47 
service_bootstrap_func(void * x)48 void *service_bootstrap_func(void *x)
49 {
50     stinfo *sti = x;
51     sti->func(sti->fd, sti->cookie);
52     free(sti);
53     return 0;
54 }
55 
56 #if ADB_HOST
57 ADB_MUTEX_DEFINE( dns_lock );
58 
dns_service(int fd,void * cookie)59 static void dns_service(int fd, void *cookie)
60 {
61     char *hostname = cookie;
62     struct hostent *hp;
63     unsigned zero = 0;
64 
65     adb_mutex_lock(&dns_lock);
66     hp = gethostbyname(hostname);
67     free(cookie);
68     if(hp == 0) {
69         writex(fd, &zero, 4);
70     } else {
71         writex(fd, hp->h_addr, 4);
72     }
73     adb_mutex_unlock(&dns_lock);
74     adb_close(fd);
75 }
76 #else
77 extern int recovery_mode;
78 
recover_service(int s,void * cookie)79 static void recover_service(int s, void *cookie)
80 {
81     unsigned char buf[4096];
82     unsigned count = (unsigned) cookie;
83     int fd;
84 
85     fd = adb_creat("/tmp/update", 0644);
86     if(fd < 0) {
87         adb_close(s);
88         return;
89     }
90 
91     while(count > 0) {
92         unsigned xfer = (count > 4096) ? 4096 : count;
93         if(readx(s, buf, xfer)) break;
94         if(writex(fd, buf, xfer)) break;
95         count -= xfer;
96     }
97 
98     if(count == 0) {
99         writex(s, "OKAY", 4);
100     } else {
101         writex(s, "FAIL", 4);
102     }
103     adb_close(fd);
104     adb_close(s);
105 
106     fd = adb_creat("/tmp/update.begin", 0644);
107     adb_close(fd);
108 }
109 
restart_root_service(int fd,void * cookie)110 void restart_root_service(int fd, void *cookie)
111 {
112     char buf[100];
113     char value[PROPERTY_VALUE_MAX];
114 
115     if (getuid() == 0) {
116         snprintf(buf, sizeof(buf), "adbd is already running as root\n");
117         writex(fd, buf, strlen(buf));
118         adb_close(fd);
119     } else {
120         property_get("ro.debuggable", value, "");
121         if (strcmp(value, "1") != 0) {
122             snprintf(buf, sizeof(buf), "adbd cannot run as root in production builds\n");
123             writex(fd, buf, strlen(buf));
124             adb_close(fd);
125             return;
126         }
127 
128         property_set("service.adb.root", "1");
129         snprintf(buf, sizeof(buf), "restarting adbd as root\n");
130         writex(fd, buf, strlen(buf));
131         adb_close(fd);
132     }
133 }
134 
restart_tcp_service(int fd,void * cookie)135 void restart_tcp_service(int fd, void *cookie)
136 {
137     char buf[100];
138     char value[PROPERTY_VALUE_MAX];
139     int port = (int)cookie;
140 
141     if (port <= 0) {
142         snprintf(buf, sizeof(buf), "invalid port\n");
143         writex(fd, buf, strlen(buf));
144         adb_close(fd);
145         return;
146     }
147 
148     snprintf(value, sizeof(value), "%d", port);
149     property_set("service.adb.tcp.port", value);
150     snprintf(buf, sizeof(buf), "restarting in TCP mode port: %d\n", port);
151     writex(fd, buf, strlen(buf));
152     adb_close(fd);
153 }
154 
restart_usb_service(int fd,void * cookie)155 void restart_usb_service(int fd, void *cookie)
156 {
157     char buf[100];
158 
159     property_set("service.adb.tcp.port", "0");
160     snprintf(buf, sizeof(buf), "restarting in USB mode\n");
161     writex(fd, buf, strlen(buf));
162     adb_close(fd);
163 }
164 
reboot_service(int fd,void * arg)165 void reboot_service(int fd, void *arg)
166 {
167     char buf[100];
168     int pid, ret;
169 
170     sync();
171 
172     /* Attempt to unmount the SD card first.
173      * No need to bother checking for errors.
174      */
175     pid = fork();
176     if (pid == 0) {
177         /* ask vdc to unmount it */
178         execl("/system/bin/vdc", "/system/bin/vdc", "volume", "unmount",
179                 getenv("EXTERNAL_STORAGE"), "force", NULL);
180     } else if (pid > 0) {
181         /* wait until vdc succeeds or fails */
182         waitpid(pid, &ret, 0);
183     }
184 
185     ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg);
186     if (ret < 0) {
187         snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno));
188         writex(fd, buf, strlen(buf));
189     }
190     free(arg);
191     adb_close(fd);
192 }
193 
194 #endif
195 
196 #if 0
197 static void echo_service(int fd, void *cookie)
198 {
199     char buf[4096];
200     int r;
201     char *p;
202     int c;
203 
204     for(;;) {
205         r = read(fd, buf, 4096);
206         if(r == 0) goto done;
207         if(r < 0) {
208             if(errno == EINTR) continue;
209             else goto done;
210         }
211 
212         c = r;
213         p = buf;
214         while(c > 0) {
215             r = write(fd, p, c);
216             if(r > 0) {
217                 c -= r;
218                 p += r;
219                 continue;
220             }
221             if((r < 0) && (errno == EINTR)) continue;
222             goto done;
223         }
224     }
225 done:
226     close(fd);
227 }
228 #endif
229 
create_service_thread(void (* func)(int,void *),void * cookie)230 static int create_service_thread(void (*func)(int, void *), void *cookie)
231 {
232     stinfo *sti;
233     adb_thread_t t;
234     int s[2];
235 
236     if(adb_socketpair(s)) {
237         printf("cannot create service socket pair\n");
238         return -1;
239     }
240 
241     sti = malloc(sizeof(stinfo));
242     if(sti == 0) fatal("cannot allocate stinfo");
243     sti->func = func;
244     sti->cookie = cookie;
245     sti->fd = s[1];
246 
247     if(adb_thread_create( &t, service_bootstrap_func, sti)){
248         free(sti);
249         adb_close(s[0]);
250         adb_close(s[1]);
251         printf("cannot create service thread\n");
252         return -1;
253     }
254 
255     D("service thread started, %d:%d\n",s[0], s[1]);
256     return s[0];
257 }
258 
259 #if !ADB_HOST
create_subprocess(const char * cmd,const char * arg0,const char * arg1,pid_t * pid)260 static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
261 {
262 #ifdef HAVE_WIN32_PROC
263     D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
264     fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
265     return -1;
266 #else /* !HAVE_WIN32_PROC */
267     char *devname;
268     int ptm;
269 
270     ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
271     if(ptm < 0){
272         printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
273         return -1;
274     }
275     fcntl(ptm, F_SETFD, FD_CLOEXEC);
276 
277     if(grantpt(ptm) || unlockpt(ptm) ||
278        ((devname = (char*) ptsname(ptm)) == 0)){
279         printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
280         adb_close(ptm);
281         return -1;
282     }
283 
284     *pid = fork();
285     if(*pid < 0) {
286         printf("- fork failed: %s -\n", strerror(errno));
287         adb_close(ptm);
288         return -1;
289     }
290 
291     if(*pid == 0){
292         int pts;
293 
294         setsid();
295 
296         pts = unix_open(devname, O_RDWR);
297         if(pts < 0) {
298             fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
299             exit(-1);
300         }
301 
302         dup2(pts, 0);
303         dup2(pts, 1);
304         dup2(pts, 2);
305 
306         adb_close(pts);
307         adb_close(ptm);
308 
309         // set OOM adjustment to zero
310         char text[64];
311         snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
312         int fd = adb_open(text, O_WRONLY);
313         if (fd >= 0) {
314             adb_write(fd, "0", 1);
315             adb_close(fd);
316         } else {
317            D("adb: unable to open %s\n", text);
318         }
319         execl(cmd, cmd, arg0, arg1, NULL);
320         fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
321                 cmd, strerror(errno), errno);
322         exit(-1);
323     } else {
324         // Don't set child's OOM adjustment to zero.
325         // Let the child do it itself, as sometimes the parent starts
326         // running before the child has a /proc/pid/oom_adj.
327         // """adb: unable to open /proc/644/oom_adj""" seen in some logs.
328         return ptm;
329     }
330 #endif /* !HAVE_WIN32_PROC */
331 }
332 #endif  /* !ABD_HOST */
333 
334 #if ADB_HOST
335 #define SHELL_COMMAND "/bin/sh"
336 #else
337 #define SHELL_COMMAND "/system/bin/sh"
338 #endif
339 
340 #if !ADB_HOST
subproc_waiter_service(int fd,void * cookie)341 static void subproc_waiter_service(int fd, void *cookie)
342 {
343     pid_t pid = (pid_t)cookie;
344 
345     D("entered. fd=%d of pid=%d\n", fd, pid);
346     for (;;) {
347         int status;
348         pid_t p = waitpid(pid, &status, 0);
349         if (p == pid) {
350             D("fd=%d, post waitpid(pid=%d) status=%04x\n", fd, p, status);
351             if (WIFSIGNALED(status)) {
352                 D("*** Killed by signal %d\n", WTERMSIG(status));
353                 break;
354             } else if (!WIFEXITED(status)) {
355                 D("*** Didn't exit!!. status %d\n", status);
356                 break;
357             } else if (WEXITSTATUS(status) >= 0) {
358                 D("*** Exit code %d\n", WEXITSTATUS(status));
359                 break;
360             }
361          }
362     }
363     D("shell exited fd=%d of pid=%d err=%d\n", fd, pid, errno);
364     if (SHELL_EXIT_NOTIFY_FD >=0) {
365       int res;
366       res = writex(SHELL_EXIT_NOTIFY_FD, &fd, sizeof(fd));
367       D("notified shell exit via fd=%d for pid=%d res=%d errno=%d\n",
368         SHELL_EXIT_NOTIFY_FD, pid, res, errno);
369     }
370 }
371 
create_subproc_thread(const char * name)372 static int create_subproc_thread(const char *name)
373 {
374     stinfo *sti;
375     adb_thread_t t;
376     int ret_fd;
377     pid_t pid;
378     if(name) {
379         ret_fd = create_subprocess(SHELL_COMMAND, "-c", name, &pid);
380     } else {
381         ret_fd = create_subprocess(SHELL_COMMAND, "-", 0, &pid);
382     }
383     D("create_subprocess() ret_fd=%d pid=%d\n", ret_fd, pid);
384 
385     sti = malloc(sizeof(stinfo));
386     if(sti == 0) fatal("cannot allocate stinfo");
387     sti->func = subproc_waiter_service;
388     sti->cookie = (void*)pid;
389     sti->fd = ret_fd;
390 
391     if(adb_thread_create( &t, service_bootstrap_func, sti)){
392         free(sti);
393         adb_close(ret_fd);
394         printf("cannot create service thread\n");
395         return -1;
396     }
397 
398     D("service thread started, fd=%d pid=%d\n",ret_fd, pid);
399     return ret_fd;
400 }
401 #endif
402 
service_to_fd(const char * name)403 int service_to_fd(const char *name)
404 {
405     int ret = -1;
406 
407     if(!strncmp(name, "tcp:", 4)) {
408         int port = atoi(name + 4);
409         name = strchr(name + 4, ':');
410         if(name == 0) {
411             ret = socket_loopback_client(port, SOCK_STREAM);
412             if (ret >= 0)
413                 disable_tcp_nagle(ret);
414         } else {
415 #if ADB_HOST
416             adb_mutex_lock(&dns_lock);
417             ret = socket_network_client(name + 1, port, SOCK_STREAM);
418             adb_mutex_unlock(&dns_lock);
419 #else
420             return -1;
421 #endif
422         }
423 #ifndef HAVE_WINSOCK   /* winsock doesn't implement unix domain sockets */
424     } else if(!strncmp(name, "local:", 6)) {
425         ret = socket_local_client(name + 6,
426                 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
427     } else if(!strncmp(name, "localreserved:", 14)) {
428         ret = socket_local_client(name + 14,
429                 ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
430     } else if(!strncmp(name, "localabstract:", 14)) {
431         ret = socket_local_client(name + 14,
432                 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
433     } else if(!strncmp(name, "localfilesystem:", 16)) {
434         ret = socket_local_client(name + 16,
435                 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
436 #endif
437 #if ADB_HOST
438     } else if(!strncmp("dns:", name, 4)){
439         char *n = strdup(name + 4);
440         if(n == 0) return -1;
441         ret = create_service_thread(dns_service, n);
442 #else /* !ADB_HOST */
443     } else if(!strncmp("dev:", name, 4)) {
444         ret = unix_open(name + 4, O_RDWR);
445     } else if(!strncmp(name, "framebuffer:", 12)) {
446         ret = create_service_thread(framebuffer_service, 0);
447     } else if(recovery_mode && !strncmp(name, "recover:", 8)) {
448         ret = create_service_thread(recover_service, (void*) atoi(name + 8));
449     } else if (!strncmp(name, "jdwp:", 5)) {
450         ret = create_jdwp_connection_fd(atoi(name+5));
451     } else if (!strncmp(name, "log:", 4)) {
452         ret = create_service_thread(log_service, get_log_file_path(name + 4));
453     } else if(!HOST && !strncmp(name, "shell:", 6)) {
454         if(name[6]) {
455             ret = create_subproc_thread(name + 6);
456         } else {
457             ret = create_subproc_thread(0);
458         }
459     } else if(!strncmp(name, "sync:", 5)) {
460         ret = create_service_thread(file_sync_service, NULL);
461     } else if(!strncmp(name, "remount:", 8)) {
462         ret = create_service_thread(remount_service, NULL);
463     } else if(!strncmp(name, "reboot:", 7)) {
464         void* arg = strdup(name + 7);
465         if(arg == 0) return -1;
466         ret = create_service_thread(reboot_service, arg);
467     } else if(!strncmp(name, "root:", 5)) {
468         ret = create_service_thread(restart_root_service, NULL);
469     } else if(!strncmp(name, "backup:", 7)) {
470         char* arg = strdup(name+7);
471         if (arg == NULL) return -1;
472         ret = backup_service(BACKUP, arg);
473     } else if(!strncmp(name, "restore:", 8)) {
474         ret = backup_service(RESTORE, NULL);
475     } else if(!strncmp(name, "tcpip:", 6)) {
476         int port;
477         if (sscanf(name + 6, "%d", &port) == 0) {
478             port = 0;
479         }
480         ret = create_service_thread(restart_tcp_service, (void *)port);
481     } else if(!strncmp(name, "usb:", 4)) {
482         ret = create_service_thread(restart_usb_service, NULL);
483 #endif
484 #if 0
485     } else if(!strncmp(name, "echo:", 5)){
486         ret = create_service_thread(echo_service, 0);
487 #endif
488     }
489     if (ret >= 0) {
490         close_on_exec(ret);
491     }
492     return ret;
493 }
494 
495 #if ADB_HOST
496 struct state_info {
497     transport_type transport;
498     char* serial;
499     int state;
500 };
501 
wait_for_state(int fd,void * cookie)502 static void wait_for_state(int fd, void* cookie)
503 {
504     struct state_info* sinfo = cookie;
505     char* err = "unknown error";
506 
507     D("wait_for_state %d\n", sinfo->state);
508 
509     atransport *t = acquire_one_transport(sinfo->state, sinfo->transport, sinfo->serial, &err);
510     if(t != 0) {
511         writex(fd, "OKAY", 4);
512     } else {
513         sendfailmsg(fd, err);
514     }
515 
516     if (sinfo->serial)
517         free(sinfo->serial);
518     free(sinfo);
519     adb_close(fd);
520     D("wait_for_state is done\n");
521 }
522 #endif
523 
524 #if ADB_HOST
host_service_to_socket(const char * name,const char * serial)525 asocket*  host_service_to_socket(const char*  name, const char *serial)
526 {
527     if (!strcmp(name,"track-devices")) {
528         return create_device_tracker();
529     } else if (!strncmp(name, "wait-for-", strlen("wait-for-"))) {
530         struct state_info* sinfo = malloc(sizeof(struct state_info));
531 
532         if (serial)
533             sinfo->serial = strdup(serial);
534         else
535             sinfo->serial = NULL;
536 
537         name += strlen("wait-for-");
538 
539         if (!strncmp(name, "local", strlen("local"))) {
540             sinfo->transport = kTransportLocal;
541             sinfo->state = CS_DEVICE;
542         } else if (!strncmp(name, "usb", strlen("usb"))) {
543             sinfo->transport = kTransportUsb;
544             sinfo->state = CS_DEVICE;
545         } else if (!strncmp(name, "any", strlen("any"))) {
546             sinfo->transport = kTransportAny;
547             sinfo->state = CS_DEVICE;
548         } else {
549             free(sinfo);
550             return NULL;
551         }
552 
553         int fd = create_service_thread(wait_for_state, sinfo);
554         return create_local_socket(fd);
555     }
556     return NULL;
557 }
558 #endif /* ADB_HOST */
559