diff options
Diffstat (limited to 'adb/adb.c')
-rw-r--r-- | adb/adb.c | 80 |
1 files changed, 62 insertions, 18 deletions
@@ -39,6 +39,8 @@ #include <sys/capability.h> #include <linux/prctl.h> #include <sys/mount.h> +#include <getopt.h> +#include <selinux/selinux.h> #else #include "usb_vendors.h" #endif @@ -54,6 +56,7 @@ static int auth_enabled = 0; #if !ADB_HOST static const char *adb_device_banner = "device"; +static const char *root_seclabel = NULL; #endif void fatal(const char *fmt, ...) @@ -562,7 +565,7 @@ void handle_packet(apacket *p, atransport *t) break; case A_OPEN: /* OPEN(local-id, 0, "destination") */ - if (t->online) { + if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) { char *name = (char*) p->data; name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0; s = create_local_service_socket(name); @@ -578,28 +581,50 @@ void handle_packet(apacket *p, atransport *t) break; case A_OKAY: /* READY(local-id, remote-id, "") */ - if (t->online) { - if((s = find_local_socket(p->msg.arg1))) { + if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) { + if((s = find_local_socket(p->msg.arg1, 0))) { if(s->peer == 0) { + /* On first READY message, create the connection. */ s->peer = create_remote_socket(p->msg.arg0, t); s->peer->peer = s; + s->ready(s); + } else if (s->peer->id == p->msg.arg0) { + /* Other READY messages must use the same local-id */ + s->ready(s); + } else { + D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n", + p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial); } - s->ready(s); } } break; - case A_CLSE: /* CLOSE(local-id, remote-id, "") */ - if (t->online) { - if((s = find_local_socket(p->msg.arg1))) { - s->close(s); + case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */ + if (t->online && p->msg.arg1 != 0) { + if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) { + /* According to protocol.txt, p->msg.arg0 might be 0 to indicate + * a failed OPEN only. However, due to a bug in previous ADB + * versions, CLOSE(0, remote-id, "") was also used for normal + * CLOSE() operations. + * + * This is bad because it means a compromised adbd could + * send packets to close connections between the host and + * other devices. To avoid this, only allow this if the local + * socket has a peer on the same transport. + */ + if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) { + D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n", + p->msg.arg1, t->serial, s->peer->transport->serial); + } else { + s->close(s); + } } } break; - case A_WRTE: - if (t->online) { - if((s = find_local_socket(p->msg.arg1))) { + case A_WRTE: /* WRITE(local-id, remote-id, <data>) */ + if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) { + if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) { unsigned rid = p->msg.arg0; p->len = p->msg.data_length; @@ -1333,6 +1358,12 @@ int adb_main(int is_daemon, int server_port) D("Local port disabled\n"); } else { char local_name[30]; + if ((root_seclabel != NULL) && (is_selinux_enabled() > 0)) { + // b/12587913: fix setcon to allow const pointers + if (setcon((char *)root_seclabel) < 0) { + exit(1); + } + } build_local_name(local_name, sizeof(local_name), server_port); if(install_listener(local_name, "*smartsocket*", NULL, 0)) { exit(1); @@ -1619,10 +1650,6 @@ int handle_host_request(char *service, transport_type ttype, char* serial, int r return -1; } -#if !ADB_HOST -int recovery_mode = 0; -#endif - int main(int argc, char **argv) { #if ADB_HOST @@ -1634,9 +1661,26 @@ int main(int argc, char **argv) /* If adbd runs inside the emulator this will enable adb tracing via * adb-debug qemud service in the emulator. */ adb_qemu_trace_init(); - if((argc > 1) && (!strcmp(argv[1],"recovery"))) { - adb_device_banner = "recovery"; - recovery_mode = 1; + while(1) { + int c; + int option_index = 0; + static struct option opts[] = { + {"root_seclabel", required_argument, 0, 's' }, + {"device_banner", required_argument, 0, 'b' } + }; + c = getopt_long(argc, argv, "", opts, &option_index); + if (c == -1) + break; + switch (c) { + case 's': + root_seclabel = optarg; + break; + case 'b': + adb_device_banner = optarg; + break; + default: + break; + } } start_device_log(); |