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