diff options
Diffstat (limited to 'cmds')
-rw-r--r-- | cmds/atrace/atrace.cpp | 16 | ||||
-rw-r--r-- | cmds/bugreport/Android.mk | 4 | ||||
-rw-r--r-- | cmds/bugreport/bugreport.c | 56 | ||||
-rw-r--r-- | cmds/bugreport/bugreport.cpp | 91 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.c | 27 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.h | 8 | ||||
-rw-r--r-- | cmds/dumpstate/utils.c | 249 | ||||
-rw-r--r-- | cmds/installd/Android.mk | 18 | ||||
-rw-r--r-- | cmds/installd/commands.cpp (renamed from cmds/installd/commands.c) | 686 | ||||
-rw-r--r-- | cmds/installd/installd.cpp (renamed from cmds/installd/installd.c) | 228 | ||||
-rw-r--r-- | cmds/installd/installd.h | 74 | ||||
-rw-r--r-- | cmds/installd/tests/Android.mk | 6 | ||||
-rw-r--r-- | cmds/installd/tests/installd_utils_test.cpp | 97 | ||||
-rw-r--r-- | cmds/installd/utils.cpp (renamed from cmds/installd/utils.c) | 239 | ||||
-rw-r--r-- | cmds/servicemanager/bctest.c | 1 | ||||
-rw-r--r-- | cmds/servicemanager/binder.c | 5 | ||||
-rw-r--r-- | cmds/servicemanager/service_manager.c | 45 |
17 files changed, 1045 insertions, 805 deletions
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index a3d210a..515d761 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -23,6 +23,7 @@ #include <stdbool.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/sendfile.h> #include <time.h> #include <zlib.h> @@ -34,6 +35,7 @@ #include <cutils/properties.h> #include <utils/String8.h> +#include <utils/Timers.h> #include <utils/Trace.h> using namespace android; @@ -191,6 +193,9 @@ static const char* k_tracingOnPath = static const char* k_tracePath = "/sys/kernel/debug/tracing/trace"; +static const char* k_traceMarkerPath = + "/sys/kernel/debug/tracing/trace_marker"; + // Check whether a file exists. static bool fileExists(const char* filename) { return access(filename, F_OK) != -1; @@ -253,6 +258,14 @@ static bool appendStr(const char* filename, const char* str) return _writeStr(filename, str, O_APPEND|O_WRONLY); } +static void writeClockSyncMarker() +{ + char buffer[128]; + float now_in_seconds = systemTime(CLOCK_MONOTONIC) / 1000000000.0f; + snprintf(buffer, 128, "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds); + writeStr(k_traceMarkerPath, buffer); +} + // Enable or disable a kernel option by writing a "1" or a "0" into a /sys // file. static bool setKernelOptionEnable(const char* filename, bool enable) @@ -630,6 +643,7 @@ static bool startTrace() // Disable tracing in the kernel. static void stopTrace() { + writeClockSyncMarker(); setTracingEnabled(false); } @@ -648,7 +662,7 @@ static void dumpTrace() uint8_t *in, *out; int result, flush; - bzero(&zs, sizeof(zs)); + memset(&zs, 0, sizeof(zs)); result = deflateInit(&zs, Z_DEFAULT_COMPRESSION); if (result != Z_OK) { fprintf(stderr, "error initializing zlib: %d\n", result); diff --git a/cmds/bugreport/Android.mk b/cmds/bugreport/Android.mk index f476f5e..ced5d30 100644 --- a/cmds/bugreport/Android.mk +++ b/cmds/bugreport/Android.mk @@ -1,10 +1,12 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES:= bugreport.c +LOCAL_SRC_FILES:= bugreport.cpp LOCAL_MODULE:= bugreport +LOCAL_CFLAGS := -Wall + LOCAL_SHARED_LIBRARIES := libcutils include $(BUILD_EXECUTABLE) diff --git a/cmds/bugreport/bugreport.c b/cmds/bugreport/bugreport.c deleted file mode 100644 index 11e9057..0000000 --- a/cmds/bugreport/bugreport.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include <cutils/properties.h> -#include <cutils/sockets.h> - -int main(int argc, char *argv[]) { - char buffer[65536]; - int i, s; - - /* start the dumpstate service */ - property_set("ctl.start", "dumpstate"); - - /* socket will not be available until service starts */ - for (i = 0; i < 20; i++) { - s = socket_local_client("dumpstate", - ANDROID_SOCKET_NAMESPACE_RESERVED, - SOCK_STREAM); - if (s >= 0) - break; - /* try again in 1 second */ - sleep(1); - } - - if (s < 0) { - fprintf(stderr, "Failed to connect to dumpstate service\n"); - exit(1); - } - - while (1) { - int length = read(s, buffer, sizeof(buffer)); - if (length <= 0) - break; - fwrite(buffer, 1, length, stdout); - } - - close(s); - return 0; -} diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp new file mode 100644 index 0000000..b606406 --- /dev/null +++ b/cmds/bugreport/bugreport.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <stdio.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> + +#include <cutils/properties.h> +#include <cutils/sockets.h> + +// This program will trigger the dumpstate service to start a call to +// dumpstate, then connect to the dumpstate local client to read the +// output. All of the dumpstate output is written to stdout, including +// any errors encountered while reading/writing the output. +int main() { + // Start the dumpstate service. + property_set("ctl.start", "dumpstate"); + + // Socket will not be available until service starts. + int s; + for (int i = 0; i < 20; i++) { + s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, + SOCK_STREAM); + if (s >= 0) + break; + // Try again in 1 second. + sleep(1); + } + + if (s == -1) { + printf("Failed to connect to dumpstate service: %s\n", strerror(errno)); + return 1; + } + + // Set a timeout so that if nothing is read in 3 minutes, we'll stop + // reading and quit. No timeout in dumpstate is longer than 60 seconds, + // so this gives lots of leeway in case of unforeseen time outs. + struct timeval tv; + tv.tv_sec = 3 * 60; + tv.tv_usec = 0; + if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) { + printf("WARNING: Cannot set socket timeout: %s\n", strerror(errno)); + } + + while (1) { + char buffer[65536]; + ssize_t bytes_read = TEMP_FAILURE_RETRY(read(s, buffer, sizeof(buffer))); + if (bytes_read == 0) { + break; + } else if (bytes_read == -1) { + // EAGAIN really means time out, so change the errno. + if (errno == EAGAIN) { + errno = ETIMEDOUT; + } + printf("\nBugreport read terminated abnormally (%s).\n", strerror(errno)); + break; + } + + ssize_t bytes_to_send = bytes_read; + ssize_t bytes_written; + do { + bytes_written = TEMP_FAILURE_RETRY(write(STDOUT_FILENO, + buffer + bytes_read - bytes_to_send, + bytes_to_send)); + if (bytes_written == -1) { + printf("Failed to write data to stdout: read %zd, trying to send %zd (%s)\n", + bytes_read, bytes_to_send, strerror(errno)); + return 1; + } + bytes_to_send -= bytes_written; + } while (bytes_written != 0 && bytes_to_send > 0); + } + + TEMP_FAILURE_RETRY(close(s)); + return 0; +} diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c index dc1ada0..a33dcf3 100644 --- a/cmds/dumpstate/dumpstate.c +++ b/cmds/dumpstate/dumpstate.c @@ -64,7 +64,8 @@ static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) { time_t thirty_minutes_ago = time(NULL) - 60*30; for (size_t i = 0; i < NUM_TOMBSTONES; i++) { snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i); - int fd = open(data[i].name, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); + int fd = TEMP_FAILURE_RETRY(open(data[i].name, + O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)); struct stat st; if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && (time_t) st.st_mtime >= thirty_minutes_ago) { @@ -184,7 +185,8 @@ static void dumpstate() { if (!anr_traces_path[0]) { printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n"); } else { - int fd = open(anr_traces_path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); + int fd = TEMP_FAILURE_RETRY(open(anr_traces_path, + O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)); if (fd < 0) { printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno)); } else { @@ -236,13 +238,15 @@ static void dumpstate() { dump_file("LAST KMSG", "/proc/last_kmsg"); } - dump_file("LAST PANIC CONSOLE", "/data/dontpanic/apanic_console"); - dump_file("LAST PANIC THREADS", "/data/dontpanic/apanic_threads"); + /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */ + run_command("LAST LOGCAT", 10, "logcat", "-L", "-v", "threadtime", + "-b", "all", "-d", "*:v", NULL); for_each_userid(do_dump_settings, NULL); /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */ - run_command("NETWORK INTERFACES", 10, SU_PATH, "root", "netcfg", NULL); + + run_command("NETWORK INTERFACES", 10, "ip", "link", NULL); run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL); run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL); @@ -387,7 +391,6 @@ static void usage() { fprintf(stderr, "usage: dumpstate [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-z]] [-s] [-q]\n" " -o: write to file (instead of stdout)\n" " -d: append date to filename (requires -o)\n" - " -z: gzip output (requires -o)\n" " -p: capture screenshot to filename.png (requires -o)\n" " -s: write output to control socket (for init)\n" " -b: play sound file instead of vibrate, at beginning of job\n" @@ -410,7 +413,6 @@ static void vibrate(FILE* vibrator, int ms) { int main(int argc, char *argv[]) { struct sigaction sigact; int do_add_date = 0; - int do_compress = 0; int do_vibrate = 1; char* use_outfile = 0; int use_socket = 0; @@ -435,7 +437,7 @@ int main(int argc, char *argv[]) { /* set as high priority, and protect from OOM killer */ setpriority(PRIO_PROCESS, 0, -20); - FILE *oom_adj = fopen("/proc/self/oom_adj", "w"); + FILE *oom_adj = fopen("/proc/self/oom_adj", "we"); if (oom_adj) { fputs("-17", oom_adj); fclose(oom_adj); @@ -450,7 +452,6 @@ int main(int argc, char *argv[]) { case 's': use_socket = 1; break; case 'v': break; // compatibility no-op case 'q': do_vibrate = 0; break; - case 'z': do_compress = 6; break; case 'p': do_fb = 1; break; case 'B': do_broadcast = 1; break; case '?': printf("\n"); @@ -469,15 +470,14 @@ int main(int argc, char *argv[]) { /* open the vibrator before dropping root */ FILE *vibrator = 0; if (do_vibrate) { - vibrator = fopen("/sys/class/timed_output/vibrator/enable", "w"); + vibrator = fopen("/sys/class/timed_output/vibrator/enable", "we"); if (vibrator) { - fcntl(fileno(vibrator), F_SETFD, FD_CLOEXEC); vibrate(vibrator, 150); } } /* read /proc/cmdline before dropping root */ - FILE *cmdline = fopen("/proc/cmdline", "r"); + FILE *cmdline = fopen("/proc/cmdline", "re"); if (cmdline != NULL) { fgets(cmdline_buf, sizeof(cmdline_buf), cmdline); fclose(cmdline); @@ -545,10 +545,9 @@ int main(int argc, char *argv[]) { strlcat(screenshot_path, ".png", sizeof(screenshot_path)); } strlcat(path, ".txt", sizeof(path)); - if (do_compress) strlcat(path, ".gz", sizeof(path)); strlcpy(tmp_path, path, sizeof(tmp_path)); strlcat(tmp_path, ".tmp", sizeof(tmp_path)); - gzip_pid = redirect_to_file(stdout, tmp_path, do_compress); + redirect_to_file(stdout, tmp_path); } dumpstate(); diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 53bfff6..d17a677 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -31,7 +31,9 @@ typedef void (for_each_userid_func)(int); /* prints the contents of a file */ int dump_file(const char *title, const char *path); -/* prints the contents of the fd */ +/* prints the contents of the fd + * fd must have been opened with the flag O_NONBLOCK. + */ int dump_file_from_fd(const char *title, const char *path, int fd); /* forks a command and waits for it to finish -- terminate args with NULL */ @@ -43,8 +45,8 @@ void print_properties(); /* redirect output to a service control socket */ void redirect_to_socket(FILE *redirect, const char *service); -/* redirect output to a file, optionally gzipping; returns gzip pid */ -pid_t redirect_to_file(FILE *redirect, char *path, int gzip_level); +/* redirect output to a file */ +void redirect_to_file(FILE *redirect, char *path); /* dump Dalvik and native stack traces, return the trace file location (NULL if none) */ const char *dump_traces(); diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c index 3e0b24b..cf14c8b 100644 --- a/cmds/dumpstate/utils.c +++ b/cmds/dumpstate/utils.c @@ -53,6 +53,12 @@ static const char* native_processes_to_dump[] = { NULL, }; +static uint64_t nanotime() { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (uint64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec; +} + void for_each_userid(void (*func)(int), const char *header) { DIR *d; struct dirent *de; @@ -98,7 +104,7 @@ static void __for_each_pid(void (*helper)(int, const char *, void *), const char sprintf(cmdpath,"/proc/%d/cmdline", pid); memset(cmdline, 0, sizeof(cmdline)); - if ((fd = open(cmdpath, O_RDONLY)) < 0) { + if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) < 0) { strcpy(cmdline, "N/A"); } else { read(fd, cmdline, sizeof(cmdline) - 1); @@ -149,7 +155,7 @@ static void for_each_tid_helper(int pid, const char *cmdline, void *arg) { sprintf(commpath,"/proc/%d/comm", tid); memset(comm, 0, sizeof(comm)); - if ((fd = open(commpath, O_RDONLY)) < 0) { + if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) { strcpy(comm, "N/A"); } else { char *c; @@ -180,7 +186,7 @@ void show_wchan(int pid, int tid, const char *name) { memset(buffer, 0, sizeof(buffer)); sprintf(path, "/proc/%d/wchan", tid); - if ((fd = open(path, O_RDONLY)) < 0) { + if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) { printf("Failed to open '%s' (%s)\n", path, strerror(errno)); return; } @@ -250,22 +256,7 @@ void do_showmap(int pid, const char *name) { run_command(title, 10, SU_PATH, "root", "showmap", arg, NULL); } -/* prints the contents of a file */ -int dump_file(const char *title, const char *path) { - int fd = open(path, O_RDONLY); - if (fd < 0) { - int err = errno; - if (title) printf("------ %s (%s) ------\n", title, path); - printf("*** %s: %s\n", path, strerror(err)); - if (title) printf("\n"); - return -1; - } - return dump_file_from_fd(title, path, fd); -} - -int dump_file_from_fd(const char *title, const char *path, int fd) { - char buffer[32768]; - +static int _dump_file_from_fd(const char *title, const char *path, int fd) { if (title) printf("------ %s (%s", title, path); if (title) { @@ -279,32 +270,126 @@ int dump_file_from_fd(const char *title, const char *path, int fd) { printf(") ------\n"); } - int newline = 0; - for (;;) { - int ret = read(fd, buffer, sizeof(buffer)); - if (ret > 0) { - newline = (buffer[ret - 1] == '\n'); - ret = fwrite(buffer, ret, 1, stdout); + bool newline = false; + fd_set read_set; + struct timeval tm; + while (1) { + FD_ZERO(&read_set); + FD_SET(fd, &read_set); + /* Timeout if no data is read for 30 seconds. */ + tm.tv_sec = 30; + tm.tv_usec = 0; + uint64_t elapsed = nanotime(); + int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, NULL, NULL, &tm)); + if (ret == -1) { + printf("*** %s: select failed: %s\n", path, strerror(errno)); + newline = true; + break; + } else if (ret == 0) { + elapsed = nanotime() - elapsed; + printf("*** %s: Timed out after %.3fs\n", path, + (float) elapsed / NANOS_PER_SEC); + newline = true; + break; + } else { + char buffer[65536]; + ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer))); + if (bytes_read > 0) { + fwrite(buffer, bytes_read, 1, stdout); + newline = (buffer[bytes_read-1] == '\n'); + } else { + if (bytes_read == -1) { + printf("*** %s: Failed to read from fd: %s", path, strerror(errno)); + newline = true; + } + break; + } } - if (ret <= 0) break; } - close(fd); + TEMP_FAILURE_RETRY(close(fd)); if (!newline) printf("\n"); if (title) printf("\n"); return 0; } -static int64_t nanotime() { +/* prints the contents of a file */ +int dump_file(const char *title, const char *path) { + int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC)); + if (fd < 0) { + int err = errno; + if (title) printf("------ %s (%s) ------\n", title, path); + printf("*** %s: %s\n", path, strerror(err)); + if (title) printf("\n"); + return -1; + } + return _dump_file_from_fd(title, path, fd); +} + +/* fd must have been opened with the flag O_NONBLOCK. With this flag set, + * it's possible to avoid issues where opening the file itself can get + * stuck. + */ +int dump_file_from_fd(const char *title, const char *path, int fd) { + int flags = fcntl(fd, F_GETFL); + if (flags == -1) { + printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno)); + return -1; + } else if (!(flags & O_NONBLOCK)) { + printf("*** %s: fd must have O_NONBLOCK set.\n", path); + return -1; + } + return _dump_file_from_fd(title, path, fd); +} + +bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) { + sigset_t child_mask, old_mask; + sigemptyset(&child_mask); + sigaddset(&child_mask, SIGCHLD); + + if (sigprocmask(SIG_BLOCK, &child_mask, &old_mask) == -1) { + printf("*** sigprocmask failed: %s\n", strerror(errno)); + return false; + } + struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (int64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec; + ts.tv_sec = timeout_seconds; + ts.tv_nsec = 0; + int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts)); + int saved_errno = errno; + // Set the signals back the way they were. + if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) { + printf("*** sigprocmask failed: %s\n", strerror(errno)); + if (ret == 0) { + return false; + } + } + if (ret == -1) { + errno = saved_errno; + if (errno == EAGAIN) { + errno = ETIMEDOUT; + } else { + printf("*** sigtimedwait failed: %s\n", strerror(errno)); + } + return false; + } + + pid_t child_pid = waitpid(pid, status, WNOHANG); + if (child_pid != pid) { + if (child_pid != -1) { + printf("*** Waiting for pid %d, got pid %d instead\n", pid, child_pid); + } else { + printf("*** waitpid failed: %s\n", strerror(errno)); + } + return false; + } + return true; } /* forks a command and waits for it to finish */ int run_command(const char *title, int timeout_seconds, const char *command, ...) { fflush(stdout); - int64_t start = nanotime(); + uint64_t start = nanotime(); pid_t pid = fork(); /* handle error case */ @@ -345,28 +430,35 @@ int run_command(const char *title, int timeout_seconds, const char *command, ... } /* handle parent case */ - for (;;) { - int status; - pid_t p = waitpid(pid, &status, WNOHANG); - int64_t elapsed = nanotime() - start; - if (p == pid) { - if (WIFSIGNALED(status)) { - printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status)); - } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) { - printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status)); - } - if (title) printf("[%s: %.3fs elapsed]\n\n", command, (float)elapsed / NANOS_PER_SEC); - return status; + int status; + bool ret = waitpid_with_timeout(pid, timeout_seconds, &status); + uint64_t elapsed = nanotime() - start; + if (!ret) { + if (errno == ETIMEDOUT) { + printf("*** %s: Timed out after %.3fs (killing pid %d)\n", command, + (float) elapsed / NANOS_PER_SEC, pid); + } else { + printf("*** %s: Error after %.4fs (killing pid %d)\n", command, + (float) elapsed / NANOS_PER_SEC, pid); } - - if (timeout_seconds && elapsed / NANOS_PER_SEC > timeout_seconds) { - printf("*** %s: Timed out after %.3fs (killing pid %d)\n", command, (float) elapsed / NANOS_PER_SEC, pid); - kill(pid, SIGTERM); - return -1; + kill(pid, SIGTERM); + if (!waitpid_with_timeout(pid, 5, NULL)) { + kill(pid, SIGKILL); + if (!waitpid_with_timeout(pid, 5, NULL)) { + printf("*** %s: Cannot kill %d even with SIGKILL.\n", command, pid); + } } + return -1; + } - usleep(100000); // poll every 0.1 sec + if (WIFSIGNALED(status)) { + printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status)); + } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) { + printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status)); } + if (title) printf("[%s: %.3fs elapsed]\n\n", command, (float)elapsed / NANOS_PER_SEC); + + return status; } size_t num_props = 0; @@ -407,6 +499,7 @@ void redirect_to_socket(FILE *redirect, const char *service) { fprintf(stderr, "android_get_control_socket(%s): %s\n", service, strerror(errno)); exit(1); } + fcntl(s, F_SETFD, FD_CLOEXEC); if (listen(s, 4) < 0) { fprintf(stderr, "listen(control socket): %s\n", strerror(errno)); exit(1); @@ -425,8 +518,8 @@ void redirect_to_socket(FILE *redirect, const char *service) { close(fd); } -/* redirect output to a file, optionally gzipping; returns gzip pid (or -1) */ -pid_t redirect_to_file(FILE *redirect, char *path, int gzip_level) { +/* redirect output to a file */ +void redirect_to_file(FILE *redirect, char *path) { char *chp = path; /* skip initial slash */ @@ -443,52 +536,15 @@ pid_t redirect_to_file(FILE *redirect, char *path, int gzip_level) { } } - int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); if (fd < 0) { fprintf(stderr, "%s: %s\n", path, strerror(errno)); exit(1); } - pid_t gzip_pid = -1; - if (gzip_level > 0) { - int fds[2]; - if (pipe(fds)) { - fprintf(stderr, "pipe: %s\n", strerror(errno)); - exit(1); - } - - fflush(redirect); - fflush(stdout); - - gzip_pid = fork(); - if (gzip_pid < 0) { - fprintf(stderr, "fork: %s\n", strerror(errno)); - exit(1); - } - - if (gzip_pid == 0) { - dup2(fds[0], STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - - close(fd); - close(fds[0]); - close(fds[1]); - - char level[10]; - snprintf(level, sizeof(level), "-%d", gzip_level); - execlp("gzip", "gzip", level, NULL); - fprintf(stderr, "exec(gzip): %s\n", strerror(errno)); - _exit(-1); - } - - close(fd); - close(fds[0]); - fd = fds[1]; - } - - dup2(fd, fileno(redirect)); + TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect))); close(fd); - return gzip_pid; } static bool should_dump_native_traces(const char* path) { @@ -536,7 +592,8 @@ const char *dump_traces() { } /* create a new, empty traces.txt file to receive stack dumps */ - int fd = open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666); /* -rw-rw-rw- */ + int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, + 0666)); /* -rw-rw-rw- */ if (fd < 0) { fprintf(stderr, "%s: %s\n", traces_path, strerror(errno)); return NULL; @@ -586,7 +643,7 @@ const char *dump_traces() { if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) { /* skip zygote -- it won't dump its stack anyway */ snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); - int cfd = open(path, O_RDONLY); + int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC)); len = read(cfd, data, sizeof(data) - 1); close(cfd); if (len <= 0) { @@ -598,7 +655,7 @@ const char *dump_traces() { } ++dalvik_found; - int64_t start = nanotime(); + uint64_t start = nanotime(); if (kill(pid, SIGQUIT)) { fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno)); continue; @@ -628,7 +685,7 @@ const char *dump_traces() { fprintf(stderr, "lseek: %s\n", strerror(errno)); } else { static uint16_t timeout_failures = 0; - int64_t start = nanotime(); + uint64_t start = nanotime(); /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */ if (timeout_failures == 3) { @@ -671,7 +728,7 @@ error_close_fd: void dump_route_tables() { const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables"; dump_file("RT_TABLES", RT_TABLES_PATH); - FILE* fp = fopen(RT_TABLES_PATH, "r"); + FILE* fp = fopen(RT_TABLES_PATH, "re"); if (!fp) { printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno)); return; diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk index 8224e94..6dec7f6 100644 --- a/cmds/installd/Android.mk +++ b/cmds/installd/Android.mk @@ -1,6 +1,6 @@ LOCAL_PATH := $(call my-dir) -common_src_files := commands.c utils.c +common_src_files := commands.cpp utils.cpp common_cflags := -Wall -Werror # @@ -12,7 +12,12 @@ LOCAL_MODULE := libinstalld LOCAL_MODULE_TAGS := eng tests LOCAL_SRC_FILES := $(common_src_files) LOCAL_CFLAGS := $(common_cflags) +LOCAL_SHARED_LIBRARIES := \ + libbase \ + liblogwrap \ + LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk +LOCAL_CLANG := true include $(BUILD_STATIC_LIBRARY) # @@ -23,8 +28,15 @@ include $(CLEAR_VARS) LOCAL_MODULE := installd LOCAL_MODULE_TAGS := optional LOCAL_CFLAGS := $(common_cflags) -LOCAL_SRC_FILES := installd.c $(common_src_files) -LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux +LOCAL_SRC_FILES := installd.cpp $(common_src_files) +LOCAL_SHARED_LIBRARIES := \ + libbase \ + libcutils \ + liblog \ + liblogwrap \ + libselinux \ + LOCAL_STATIC_LIBRARIES := libdiskusage LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk +LOCAL_CLANG := true include $(BUILD_EXECUTABLE) diff --git a/cmds/installd/commands.c b/cmds/installd/commands.cpp index 76bc9d5..de6fd96 100644 --- a/cmds/installd/commands.c +++ b/cmds/installd/commands.cpp @@ -14,13 +14,22 @@ ** limitations under the License. */ -#include <inttypes.h> -#include <sys/capability.h> #include "installd.h" + +#include <base/stringprintf.h> +#include <base/logging.h> #include <cutils/sched_policy.h> #include <diskusage/dirsize.h> -#include <selinux/android.h> +#include <logwrap/logwrap.h> #include <system/thread_defs.h> +#include <selinux/android.h> + +#include <inttypes.h> +#include <sys/capability.h> +#include <sys/file.h> +#include <unistd.h> + +using android::base::StringPrintf; /* Directory records that are used in execution of commands. */ dir_rec_t android_data_dir; @@ -29,34 +38,20 @@ dir_rec_t android_app_dir; dir_rec_t android_app_private_dir; dir_rec_t android_app_lib_dir; dir_rec_t android_media_dir; +dir_rec_t android_mnt_expand_dir; dir_rec_array_t android_system_dirs; -int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) -{ - char pkgdir[PKG_PATH_MAX]; - char libsymlink[PKG_PATH_MAX]; - char applibdir[PKG_PATH_MAX]; - struct stat libStat; +static const char* kCpPath = "/system/bin/cp"; +int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) +{ if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { ALOGE("invalid uid/gid: %d %d\n", uid, gid); return -1; } - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) { - ALOGE("cannot create package path\n"); - return -1; - } - - if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) { - ALOGE("cannot create package lib symlink origin path\n"); - return -1; - } - - if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) { - ALOGE("cannot create package lib symlink dest path\n"); - return -1; - } + std::string _pkgdir(create_package_data_path(uuid, pkgname, 0)); + const char* pkgdir = _pkgdir.c_str(); if (mkdir(pkgdir, 0751) < 0) { ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); @@ -68,42 +63,14 @@ int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) return -1; } - if (lstat(libsymlink, &libStat) < 0) { - if (errno != ENOENT) { - ALOGE("couldn't stat lib dir: %s\n", strerror(errno)); - return -1; - } - } else { - if (S_ISDIR(libStat.st_mode)) { - if (delete_dir_contents(libsymlink, 1, NULL) < 0) { - ALOGE("couldn't delete lib directory during install for: %s", libsymlink); - return -1; - } - } else if (S_ISLNK(libStat.st_mode)) { - if (unlink(libsymlink) < 0) { - ALOGE("couldn't unlink lib directory during install for: %s", libsymlink); - return -1; - } - } - } - if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) { ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); - unlink(libsymlink); unlink(pkgdir); return -errno; } - if (symlink(applibdir, libsymlink) < 0) { - ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir, - strerror(errno)); - unlink(pkgdir); - return -1; - } - if (chown(pkgdir, uid, gid) < 0) { ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); - unlink(libsymlink); unlink(pkgdir); return -1; } @@ -111,12 +78,10 @@ int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) return 0; } -int uninstall(const char *pkgname, userid_t userid) +int uninstall(const char *uuid, const char *pkgname, userid_t userid) { - char pkgdir[PKG_PATH_MAX]; - - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) - return -1; + std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + const char* pkgdir = _pkgdir.c_str(); remove_profile_file(pkgname); @@ -141,21 +106,17 @@ int renamepkg(const char *oldpkgname, const char *newpkgname) return 0; } -int fix_uid(const char *pkgname, uid_t uid, gid_t gid) +int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid) { - char pkgdir[PKG_PATH_MAX]; struct stat s; - int rc = 0; if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { ALOGE("invalid uid/gid: %d %d\n", uid, gid); return -1; } - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) { - ALOGE("cannot create package path\n"); - return -1; - } + std::string _pkgdir(create_package_data_path(uuid, pkgname, 0)); + const char* pkgdir = _pkgdir.c_str(); if (stat(pkgdir, &s) < 0) return -1; @@ -178,35 +139,18 @@ int fix_uid(const char *pkgname, uid_t uid, gid_t gid) return 0; } -int delete_user_data(const char *pkgname, userid_t userid) +int delete_user_data(const char *uuid, const char *pkgname, userid_t userid) { - char pkgdir[PKG_PATH_MAX]; - - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) - return -1; + std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + const char* pkgdir = _pkgdir.c_str(); return delete_dir_contents(pkgdir, 0, NULL); } -int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo) +int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo) { - char pkgdir[PKG_PATH_MAX]; - char applibdir[PKG_PATH_MAX]; - char libsymlink[PKG_PATH_MAX]; - struct stat libStat; - - // Create the data dir for the package - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) { - return -1; - } - if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userid)) { - ALOGE("cannot create package lib symlink origin path\n"); - return -1; - } - if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) { - ALOGE("cannot create package lib symlink dest path\n"); - return -1; - } + std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + const char* pkgdir = _pkgdir.c_str(); if (mkdir(pkgdir, 0751) < 0) { ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); @@ -218,47 +162,14 @@ int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* return -errno; } - if (lstat(libsymlink, &libStat) < 0) { - if (errno != ENOENT) { - ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno)); - unlink(pkgdir); - return -1; - } - } else { - if (S_ISDIR(libStat.st_mode)) { - if (delete_dir_contents(libsymlink, 1, NULL) < 0) { - ALOGE("couldn't delete lib directory during install for non-primary: %s", - libsymlink); - unlink(pkgdir); - return -1; - } - } else if (S_ISLNK(libStat.st_mode)) { - if (unlink(libsymlink) < 0) { - ALOGE("couldn't unlink lib directory during install for non-primary: %s", - libsymlink); - unlink(pkgdir); - return -1; - } - } - } - if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) { ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); - unlink(libsymlink); unlink(pkgdir); return -errno; } - if (symlink(applibdir, libsymlink) < 0) { - ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink, - applibdir, strerror(errno)); - unlink(pkgdir); - return -1; - } - if (chown(pkgdir, uid, uid) < 0) { ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); - unlink(libsymlink); unlink(pkgdir); return -errno; } @@ -266,6 +177,80 @@ int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* return 0; } +int move_user_data(const char *from_uuid, const char *to_uuid, + const char *package_name, appid_t appid, const char* seinfo) { + std::vector<userid_t> users = get_known_users(from_uuid); + + // Copy package private data for all known users + for (auto user : users) { + std::string from(create_package_data_path(from_uuid, package_name, user)); + std::string to(create_package_data_path(to_uuid, package_name, user)); + std::string to_user(create_data_user_path(to_uuid, user)); + + // Data source may not exist for all users; that's okay + if (access(from.c_str(), F_OK) != 0) { + LOG(INFO) << "Missing source " << from; + continue; + } + + std::string user_path(create_data_user_path(to_uuid, user)); + if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) { + LOG(ERROR) << "Failed to prepare user target " << user_path; + goto fail; + } + + uid_t uid = multiuser_get_uid(user, appid); + if (make_user_data(to_uuid, package_name, uid, user, seinfo) != 0) { + LOG(ERROR) << "Failed to create package target " << to; + goto fail; + } + + char *argv[] = { + (char*) kCpPath, + (char*) "-F", /* delete any existing destination file first (--remove-destination) */ + (char*) "-p", /* preserve timestamps, ownership, and permissions */ + (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ + (char*) "-P", /* Do not follow symlinks [default] */ + (char*) "-d", /* don't dereference symlinks */ + (char*) from.c_str(), + (char*) to_user.c_str() + }; + + LOG(DEBUG) << "Copying " << from << " to " << to; + int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); + + if (rc != 0) { + LOG(ERROR) << "Failed copying " << from << " to " << to + << ": status " << rc; + goto fail; + } + + if (restorecon_data(to_uuid, package_name, seinfo, uid) != 0) { + LOG(ERROR) << "Failed to restorecon " << to; + goto fail; + } + } + + // Copy successful, so delete old data + for (auto user : users) { + std::string from(create_package_data_path(from_uuid, package_name, user)); + if (delete_dir_contents(from.c_str(), 1, NULL) != 0) { + LOG(WARNING) << "Failed to delete " << from; + } + } + return 0; + +fail: + // Nuke everything we might have already copied + for (auto user : users) { + std::string to(create_package_data_path(to_uuid, package_name, user)); + if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { + LOG(WARNING) << "Failed to rollback " << to; + } + } + return -1; +} + int make_user_config(userid_t userid) { if (ensure_config_user_dirs(userid) == -1) { @@ -275,49 +260,49 @@ int make_user_config(userid_t userid) return 0; } -int delete_user(userid_t userid) +int delete_user(const char *uuid, userid_t userid) { int status = 0; - char data_path[PKG_PATH_MAX]; - if ((create_user_path(data_path, userid) != 0) - || (delete_dir_contents(data_path, 1, NULL) != 0)) { + std::string data_path(create_data_user_path(uuid, userid)); + if (delete_dir_contents(data_path.c_str(), 1, NULL) != 0) { status = -1; } - char media_path[PATH_MAX]; - if ((create_user_media_path(media_path, userid) != 0) - || (delete_dir_contents(media_path, 1, NULL) != 0)) { + std::string media_path(create_data_media_path(uuid, userid)); + if (delete_dir_contents(media_path.c_str(), 1, NULL) != 0) { status = -1; } - char config_path[PATH_MAX]; - if ((create_user_config_path(config_path, userid) != 0) - || (delete_dir_contents(config_path, 1, NULL) != 0)) { - status = -1; + // Config paths only exist on internal storage + if (uuid == nullptr) { + char config_path[PATH_MAX]; + if ((create_user_config_path(config_path, userid) != 0) + || (delete_dir_contents(config_path, 1, NULL) != 0)) { + status = -1; + } } return status; } -int delete_cache(const char *pkgname, userid_t userid) +int delete_cache(const char *uuid, const char *pkgname, userid_t userid) { - char cachedir[PKG_PATH_MAX]; - - if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, userid)) - return -1; + std::string _cachedir( + create_package_data_path(uuid, pkgname, userid) + CACHE_DIR_POSTFIX); + const char* cachedir = _cachedir.c_str(); /* delete contents, not the directory, no exceptions */ return delete_dir_contents(cachedir, 0, NULL); } -int delete_code_cache(const char *pkgname, userid_t userid) +int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid) { - char codecachedir[PKG_PATH_MAX]; - struct stat s; + std::string _codecachedir( + create_package_data_path(uuid, pkgname, userid) + CACHE_DIR_POSTFIX); + const char* codecachedir = _codecachedir.c_str(); - if (create_pkg_path(codecachedir, pkgname, CODE_CACHE_DIR_POSTFIX, userid)) - return -1; + struct stat s; /* it's okay if code cache is missing */ if (lstat(codecachedir, &s) == -1 && errno == ENOENT) { @@ -335,7 +320,7 @@ int delete_code_cache(const char *pkgname, userid_t userid) * also require that apps constantly modify file metadata even * when just reading from the cache, which is pretty awful. */ -int free_cache(int64_t free_size) +int free_cache(const char *uuid, int64_t free_size) { cache_t* cache; int64_t avail; @@ -344,7 +329,9 @@ int free_cache(int64_t free_size) char tmpdir[PATH_MAX]; char *dirpos; - avail = data_disk_free(); + std::string data_path(create_data_path(uuid)); + + avail = data_disk_free(data_path); if (avail < 0) return -1; ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail); @@ -352,15 +339,16 @@ int free_cache(int64_t free_size) cache = start_cache_collection(); - // Collect cache files for primary user. - if (create_user_path(tmpdir, 0) == 0) { - //ALOGI("adding cache files from %s\n", tmpdir); - add_cache_files(cache, tmpdir, "cache"); + // Special case for owner on internal storage + if (uuid == nullptr) { + std::string _tmpdir(create_data_user_path(nullptr, 0)); + add_cache_files(cache, _tmpdir.c_str(), "cache"); } // Search for other users and add any cache files from them. - snprintf(tmpdir, sizeof(tmpdir), "%s%s", android_data_dir.path, - SECONDARY_USER_PREFIX); + std::string _tmpdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX); + strcpy(tmpdir, _tmpdir.c_str()); + dirpos = tmpdir + strlen(tmpdir); d = opendir(tmpdir); if (d != NULL) { @@ -412,10 +400,10 @@ int free_cache(int64_t free_size) closedir(d); } - clear_cache_files(cache, free_size); + clear_cache_files(data_path, cache, free_size); finish_cache_collection(cache); - return data_disk_free() >= free_size ? 0 : -1; + return data_disk_free(data_path) >= free_size ? 0 : -1; } int move_dex(const char *src, const char *dst, const char *instruction_set) @@ -466,7 +454,7 @@ int rm_dex(const char *path, const char *instruction_set) } } -int get_size(const char *pkgname, userid_t userid, const char *apkpath, +int get_size(const char *uuid, const char *pkgname, userid_t userid, const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set, int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize, int64_t* _asecsize) @@ -523,11 +511,10 @@ int get_size(const char *pkgname, userid_t userid, const char *apkpath, } } - if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, userid)) { - goto done; - } + std::string _pkgdir(create_package_data_path(uuid, pkgname, userid)); + const char* pkgdir = _pkgdir.c_str(); - d = opendir(path); + d = opendir(pkgdir); if (d == NULL) { goto done; } @@ -625,30 +612,40 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *inst return 0; } -static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name, - const char* output_file_name) +static int split_count(const char *str) { - /* platform-specific flags affecting optimization and verification */ - char dexopt_flags[PROPERTY_VALUE_MAX]; - property_get("dalvik.vm.dexopt-flags", dexopt_flags, ""); - ALOGV("dalvik.vm.dexopt-flags=%s\n", dexopt_flags); + char *ctx; + int count = 0; + char buf[PROPERTY_VALUE_MAX]; - static const char* DEX_OPT_BIN = "/system/bin/dexopt"; - static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig - char zip_num[MAX_INT_LEN]; - char odex_num[MAX_INT_LEN]; + strncpy(buf, str, sizeof(buf)); + char *pBuf = buf; - sprintf(zip_num, "%d", zip_fd); - sprintf(odex_num, "%d", odex_fd); + while(strtok_r(pBuf, " ", &ctx) != NULL) { + count++; + pBuf = NULL; + } - ALOGV("Running %s in=%s out=%s\n", DEX_OPT_BIN, input_file_name, output_file_name); - execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name, - dexopt_flags, (char*) NULL); - ALOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno)); + return count; +} + +static int split(char *buf, const char **argv) +{ + char *ctx; + int count = 0; + char *tok; + char *pBuf = buf; + + while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) { + argv[count++] = tok; + pBuf = NULL; + } + + return count; } static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name, - const char* output_file_name, const char *pkgname, const char *instruction_set) + const char* output_file_name, const char *pkgname __unused, const char *instruction_set) { static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig static const unsigned int MAX_INSTRUCTION_SET_LEN = 7; @@ -670,7 +667,7 @@ static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name, sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd); sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd); - ALOGE("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n", + ALOGV("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n", PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name); /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */ @@ -689,7 +686,7 @@ static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name, static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set, - bool vm_safe_mode) + bool vm_safe_mode, bool debuggable) { static const unsigned int MAX_INSTRUCTION_SET_LEN = 7; @@ -712,14 +709,32 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter", dex2oat_compiler_filter_flag, NULL) > 0; + char dex2oat_threads_buf[PROPERTY_VALUE_MAX]; + bool have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads", dex2oat_threads_buf, + NULL) > 0; + char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2]; + if (have_dex2oat_threads_flag) { + sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf); + } + char dex2oat_isa_features_key[PROPERTY_KEY_MAX]; sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set); char dex2oat_isa_features[PROPERTY_VALUE_MAX]; bool have_dex2oat_isa_features = property_get(dex2oat_isa_features_key, dex2oat_isa_features, NULL) > 0; + char dex2oat_isa_variant_key[PROPERTY_KEY_MAX]; + sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set); + char dex2oat_isa_variant[PROPERTY_VALUE_MAX]; + bool have_dex2oat_isa_variant = property_get(dex2oat_isa_variant_key, + dex2oat_isa_variant, NULL) > 0; + + const char *dex2oat_norelocation = "-Xnorelocate"; + bool have_dex2oat_relocation_skip_flag = false; + char dex2oat_flags[PROPERTY_VALUE_MAX]; - bool have_dex2oat_flags = property_get("dalvik.vm.dex2oat-flags", dex2oat_flags, NULL) > 0; + int dex2oat_flags_count = property_get("dalvik.vm.dex2oat-flags", + dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags); ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags); // If we booting without the real /data, don't spend time compiling. @@ -729,6 +744,10 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 || (strcmp(vold_decrypt, "1") == 0))); + char use_jit_property[PROPERTY_VALUE_MAX]; + bool have_jit_property = property_get("debug.usejit", use_jit_property, NULL) > 0; + bool use_jit = have_jit_property && strcmp(use_jit_property, "true") == 0; + static const char* DEX2OAT_BIN = "/system/bin/dex2oat"; static const char* RUNTIME_ARG = "--runtime-arg"; @@ -740,6 +759,7 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN]; char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX]; char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN]; + char instruction_set_variant_arg[strlen("--instruction-set-variant=") + PROPERTY_VALUE_MAX]; char instruction_set_features_arg[strlen("--instruction-set-features=") + PROPERTY_VALUE_MAX]; char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX]; char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX]; @@ -754,6 +774,7 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd); sprintf(oat_location_arg, "--oat-location=%s", output_file_name); sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); + sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant); sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features); if (swap_fd >= 0) { have_dex2oat_swap_fd = true; @@ -787,31 +808,49 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, if (skip_compilation) { strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none"); have_dex2oat_compiler_filter_flag = true; + have_dex2oat_relocation_skip_flag = true; } else if (vm_safe_mode) { strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only"); have_dex2oat_compiler_filter_flag = true; + } else if (use_jit) { + strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-at-runtime"); + have_dex2oat_compiler_filter_flag = true; } else if (have_dex2oat_compiler_filter_flag) { sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag); } + // Check whether all apps should be compiled debuggable. + if (!debuggable) { + debuggable = + (property_get("dalvik.vm.always_debuggable", prop_buf, "0") > 0) && + (prop_buf[0] == '1'); + } + ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name); - char* argv[7 // program name, mandatory arguments and the final NULL - + (have_dex2oat_isa_features ? 1 : 0) - + (have_profile_file ? 1 : 0) - + (have_top_k_profile_threshold ? 1 : 0) - + (have_dex2oat_Xms_flag ? 2 : 0) - + (have_dex2oat_Xmx_flag ? 2 : 0) - + (have_dex2oat_compiler_filter_flag ? 1 : 0) - + (have_dex2oat_flags ? 1 : 0) - + (have_dex2oat_swap_fd ? 1 : 0)]; + const char* argv[7 // program name, mandatory arguments and the final NULL + + (have_dex2oat_isa_variant ? 1 : 0) + + (have_dex2oat_isa_features ? 1 : 0) + + (have_profile_file ? 1 : 0) + + (have_top_k_profile_threshold ? 1 : 0) + + (have_dex2oat_Xms_flag ? 2 : 0) + + (have_dex2oat_Xmx_flag ? 2 : 0) + + (have_dex2oat_compiler_filter_flag ? 1 : 0) + + (have_dex2oat_threads_flag ? 1 : 0) + + (have_dex2oat_swap_fd ? 1 : 0) + + (have_dex2oat_relocation_skip_flag ? 2 : 0) + + (debuggable ? 1 : 0) + + dex2oat_flags_count]; int i = 0; - argv[i++] = (char*)DEX2OAT_BIN; + argv[i++] = DEX2OAT_BIN; argv[i++] = zip_fd_arg; argv[i++] = zip_location_arg; argv[i++] = oat_fd_arg; argv[i++] = oat_location_arg; argv[i++] = instruction_set_arg; + if (have_dex2oat_isa_variant) { + argv[i++] = instruction_set_variant_arg; + } if (have_dex2oat_isa_features) { argv[i++] = instruction_set_features_arg; } @@ -822,27 +861,37 @@ static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, argv[i++] = top_k_profile_threshold_arg; } if (have_dex2oat_Xms_flag) { - argv[i++] = (char*)RUNTIME_ARG; + argv[i++] = RUNTIME_ARG; argv[i++] = dex2oat_Xms_arg; } if (have_dex2oat_Xmx_flag) { - argv[i++] = (char*)RUNTIME_ARG; + argv[i++] = RUNTIME_ARG; argv[i++] = dex2oat_Xmx_arg; } if (have_dex2oat_compiler_filter_flag) { argv[i++] = dex2oat_compiler_filter_arg; } - if (have_dex2oat_flags) { - argv[i++] = dex2oat_flags; + if (have_dex2oat_threads_flag) { + argv[i++] = dex2oat_threads_arg; } if (have_dex2oat_swap_fd) { argv[i++] = dex2oat_swap_fd; } + if (debuggable) { + argv[i++] = "--debuggable"; + } + if (dex2oat_flags_count) { + i += split(dex2oat_flags, argv + i); + } + if (have_dex2oat_relocation_skip_flag) { + argv[i++] = RUNTIME_ARG; + argv[i++] = dex2oat_norelocation; + } // Do not add after dex2oat_flags, they should override others for debugging. argv[i] = NULL; - execv(DEX2OAT_BIN, (char* const *)argv); - ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno)); + execv(DEX2OAT_BIN, (char * const *)argv); + ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno)); } static int wait_child(pid_t pid) @@ -888,16 +937,50 @@ static bool ShouldUseSwapFileForDexopt() { return (strcmp(low_mem_buf, "true") == 0); } +/* + * Computes the odex file for the given apk_path and instruction_set. + * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex + * + * Returns false if it failed to determine the odex file path. + */ +static bool calculate_odex_file_path(char path[PKG_PATH_MAX], + const char *apk_path, + const char *instruction_set) +{ + if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set) + + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) { + ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path); + return false; + } + + strcpy(path, apk_path); + char *end = strrchr(path, '/'); + if (end == NULL) { + ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); + return false; + } + const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/'); + + strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0 + strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0 + strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0 + end = strrchr(path, '.'); + if (end == NULL) { + ALOGE("apk_path '%s' has no extension.\n", apk_path); + return false; + } + strcpy(end + 1, "odex"); + return true; +} + int dexopt(const char *apk_path, uid_t uid, bool is_public, - const char *pkgname, const char *instruction_set, - bool vm_safe_mode, bool is_patchoat) + const char *pkgname, const char *instruction_set, int dexopt_needed, + bool vm_safe_mode, bool debuggable, const char* oat_dir) { struct utimbuf ut; - struct stat input_stat, dex_stat; + struct stat input_stat; char out_path[PKG_PATH_MAX]; - char persist_sys_dalvik_vm_lib[PROPERTY_VALUE_MAX]; char swap_file_name[PKG_PATH_MAX]; - char *end; const char *input_file; char in_odex_path[PKG_PATH_MAX]; int res, input_fd=-1, out_fd=-1, swap_fd=-1; @@ -906,55 +989,43 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run // without a swap file, if necessary. if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) { + ALOGE("apk_path too long '%s'\n", apk_path); return -1; } - /* The command to run depend on the value of persist.sys.dalvik.vm.lib */ - property_get("persist.sys.dalvik.vm.lib.2", persist_sys_dalvik_vm_lib, "libart.so"); - - if (is_patchoat && strncmp(persist_sys_dalvik_vm_lib, "libart", 6) != 0) { - /* We may only patch if we are libart */ - ALOGE("Patching is only supported in libart\n"); - return -1; - } - - /* Before anything else: is there a .odex file? If so, we have - * precompiled the apk and there is nothing to do here. - * - * We skip this if we are doing a patchoat. - */ - strcpy(out_path, apk_path); - end = strrchr(out_path, '.'); - if (end != NULL && !is_patchoat) { - strcpy(end, ".odex"); - if (stat(out_path, &dex_stat) == 0) { - return 0; - } - } - - if (create_cache_path(out_path, apk_path, instruction_set)) { - return -1; - } - - if (is_patchoat) { - /* /system/framework/whatever.jar -> /system/framework/<isa>/whatever.odex */ - strcpy(in_odex_path, apk_path); - end = strrchr(in_odex_path, '/'); - if (end == NULL) { - ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); + if (oat_dir != NULL && oat_dir[0] != '!') { + if (validate_apk_path(oat_dir)) { + ALOGE("invalid oat_dir '%s'\n", oat_dir); return -1; } - const char *apk_end = apk_path + (end - in_odex_path); // strrchr(apk_path, '/'); - strcpy(end + 1, instruction_set); // in_odex_path now is /system/framework/<isa>\0 - strcat(in_odex_path, apk_end); - end = strrchr(in_odex_path, '.'); - if (end == NULL) { + if (calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) { return -1; } - strcpy(end + 1, "odex"); - input_file = in_odex_path; } else { - input_file = apk_path; + if (create_cache_path(out_path, apk_path, instruction_set)) { + return -1; + } + } + + switch (dexopt_needed) { + case DEXOPT_DEX2OAT_NEEDED: + input_file = apk_path; + break; + + case DEXOPT_PATCHOAT_NEEDED: + if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) { + return -1; + } + input_file = in_odex_path; + break; + + case DEXOPT_SELF_PATCHOAT_NEEDED: + input_file = out_path; + break; + + default: + ALOGE("Invalid dexopt needed: %d\n", dexopt_needed); + exit(72); } memset(&input_stat, 0, sizeof(input_stat)); @@ -989,7 +1060,7 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, } // Create a swap file if necessary. - if (!is_patchoat && ShouldUseSwapFileForDexopt()) { + if (ShouldUseSwapFileForDexopt()) { // Make sure there really is enough space. size_t out_len = strlen(out_path); if (out_len + strlen(".swap") + 1 <= PKG_PATH_MAX) { @@ -1048,17 +1119,21 @@ int dexopt(const char *apk_path, uid_t uid, bool is_public, exit(67); } - if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) { - run_dexopt(input_fd, out_fd, input_file, out_path); - } else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) { - if (is_patchoat) { - run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set); + if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED + || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) { + run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set); + } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) { + const char *input_file_name = strrchr(input_file, '/'); + if (input_file_name == NULL) { + input_file_name = input_file; } else { - run_dex2oat(input_fd, out_fd, input_file, out_path, swap_fd, pkgname, - instruction_set, vm_safe_mode); + input_file_name++; } + run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname, + instruction_set, vm_safe_mode, debuggable); } else { - exit(69); /* Unexpected persist.sys.dalvik.vm.lib value */ + ALOGE("Invalid dexopt needed: %d\n", dexopt_needed); + exit(73); } exit(68); /* only get here on exec failure */ } else { @@ -1368,21 +1443,16 @@ done: return 0; } -int linklib(const char* pkgname, const char* asecLibDir, int userId) +int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId) { - char pkgdir[PKG_PATH_MAX]; - char libsymlink[PKG_PATH_MAX]; struct stat s, libStat; int rc = 0; - if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) { - ALOGE("cannot create package path\n"); - return -1; - } - if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) { - ALOGE("cannot create package lib symlink origin path\n"); - return -1; - } + std::string _pkgdir(create_package_data_path(uuid, pkgname, userId)); + std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX); + + const char* pkgdir = _pkgdir.c_str(); + const char* libsymlink = _libsymlink.c_str(); if (stat(pkgdir, &s) < 0) return -1; @@ -1551,14 +1621,12 @@ fail: return -1; } -int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid) +int restorecon_data(const char* uuid, const char* pkgName, + const char* seinfo, uid_t uid) { struct dirent *entry; DIR *d; struct stat s; - char *userdir; - char *primarydir; - char *pkgdir; int ret = 0; // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here. @@ -1569,26 +1637,20 @@ int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid) return -1; } - if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) { - return -1; - } - - // Relabel for primary user. - if (selinux_android_restorecon_pkgdir(primarydir, seinfo, uid, flags) < 0) { - ALOGE("restorecon failed for %s: %s\n", primarydir, strerror(errno)); - ret |= -1; - } + // Special case for owner on internal storage + if (uuid == nullptr) { + std::string path(create_package_data_path(nullptr, pkgName, 0)); - if (asprintf(&userdir, "%s%s", android_data_dir.path, SECONDARY_USER_PREFIX) < 0) { - free(primarydir); - return -1; + if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, flags) < 0) { + PLOG(ERROR) << "restorecon failed for " << path; + ret |= -1; + } } // Relabel package directory for all secondary users. - d = opendir(userdir); + std::string userdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX); + d = opendir(userdir.c_str()); if (d == NULL) { - free(primarydir); - free(userdir); return -1; } @@ -1609,25 +1671,75 @@ int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid) continue; } - if (asprintf(&pkgdir, "%s%s/%s", userdir, user, pkgName) < 0) { - continue; - } - - if (stat(pkgdir, &s) < 0) { - free(pkgdir); + std::string pkgdir(StringPrintf("%s%s/%s", userdir.c_str(), user, pkgName)); + if (stat(pkgdir.c_str(), &s) < 0) { continue; } - if (selinux_android_restorecon_pkgdir(pkgdir, seinfo, uid, flags) < 0) { - ALOGE("restorecon failed for %s: %s\n", pkgdir, strerror(errno)); + if (selinux_android_restorecon_pkgdir(pkgdir.c_str(), seinfo, s.st_uid, flags) < 0) { + PLOG(ERROR) << "restorecon failed for " << pkgdir; ret |= -1; } - free(pkgdir); } closedir(d); - free(primarydir); - free(userdir); return ret; } +int create_oat_dir(const char* oat_dir, const char* instruction_set) +{ + char oat_instr_dir[PKG_PATH_MAX]; + + if (validate_apk_path(oat_dir)) { + ALOGE("invalid apk path '%s' (bad prefix)\n", oat_dir); + return -1; + } + if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { + return -1; + } + if (selinux_android_restorecon(oat_dir, 0)) { + ALOGE("cannot restorecon dir '%s': %s\n", oat_dir, strerror(errno)); + return -1; + } + snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set); + if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { + return -1; + } + return 0; +} + +int rm_package_dir(const char* apk_path) +{ + if (validate_apk_path(apk_path)) { + ALOGE("invalid apk path '%s' (bad prefix)\n", apk_path); + return -1; + } + return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */); +} + +int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, + const char *instruction_set) { + char *file_name_start; + char *file_name_end; + + file_name_start = strrchr(apk_path, '/'); + if (file_name_start == NULL) { + ALOGE("apk_path '%s' has no '/'s in it\n", apk_path); + return -1; + } + file_name_end = strrchr(apk_path, '.'); + if (file_name_end < file_name_start) { + ALOGE("apk_path '%s' has no extension\n", apk_path); + return -1; + } + + // Calculate file_name + int file_name_len = file_name_end - file_name_start - 1; + char file_name[file_name_len + 1]; + memcpy(file_name, file_name_start + 1, file_name_len); + file_name[file_name_len] = '\0'; + + // <apk_parent_dir>/oat/<isa>/<file_name>.odex + snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name); + return 0; +} diff --git a/cmds/installd/installd.c b/cmds/installd/installd.cpp index 5b8a1e3..3a86181 100644 --- a/cmds/installd/installd.c +++ b/cmds/installd/installd.cpp @@ -1,90 +1,101 @@ /* ** Copyright 2008, The Android Open Source Project ** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at ** -** http://www.apache.org/licenses/LICENSE-2.0 +** http://www.apache.org/licenses/LICENSE-2.0 ** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and ** limitations under the License. */ +#include "installd.h" + +#include <base/logging.h> + #include <sys/capability.h> #include <sys/prctl.h> #include <selinux/android.h> #include <selinux/avc.h> -#include "installd.h" - - #define BUFFER_MAX 1024 /* input buffer for commands */ -#define TOKEN_MAX 8 /* max number of arguments in buffer */ +#define TOKEN_MAX 16 /* max number of arguments in buffer */ #define REPLY_MAX 256 /* largest reply allowed */ -static int do_ping(char **arg, char reply[REPLY_MAX]) +static char* parse_null(char* arg) { + if (strcmp(arg, "!") == 0) { + return nullptr; + } else { + return arg; + } +} + +static int do_ping(char **arg __unused, char reply[REPLY_MAX] __unused) { return 0; } -static int do_install(char **arg, char reply[REPLY_MAX]) +static int do_install(char **arg, char reply[REPLY_MAX] __unused) { - return install(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); /* pkgname, uid, gid, seinfo */ + return install(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]); /* uuid, pkgname, uid, gid, seinfo */ } -static int do_dexopt(char **arg, char reply[REPLY_MAX]) +static int do_dexopt(char **arg, char reply[REPLY_MAX] __unused) { - /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate */ - return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]), 0); + /* apk_path, uid, is_public, pkgname, instruction_set, + * dexopt_needed, vm_safe_mode, debuggable, oat_dir */ + return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]), + atoi(arg[6]), atoi(arg[7]), arg[8]); } -static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX]) +static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] __unused) { return mark_boot_complete(arg[0] /* instruction set */); } -static int do_move_dex(char **arg, char reply[REPLY_MAX]) +static int do_move_dex(char **arg, char reply[REPLY_MAX] __unused) { return move_dex(arg[0], arg[1], arg[2]); /* src, dst, instruction_set */ } -static int do_rm_dex(char **arg, char reply[REPLY_MAX]) +static int do_rm_dex(char **arg, char reply[REPLY_MAX] __unused) { return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */ } -static int do_remove(char **arg, char reply[REPLY_MAX]) +static int do_remove(char **arg, char reply[REPLY_MAX] __unused) { - return uninstall(arg[0], atoi(arg[1])); /* pkgname, userid */ + return uninstall(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */ } -static int do_rename(char **arg, char reply[REPLY_MAX]) +static int do_rename(char **arg, char reply[REPLY_MAX] __unused) { return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */ } -static int do_fixuid(char **arg, char reply[REPLY_MAX]) +static int do_fixuid(char **arg, char reply[REPLY_MAX] __unused) { - return fix_uid(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */ + return fix_uid(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* uuid, pkgname, uid, gid */ } -static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */ +static int do_free_cache(char **arg, char reply[REPLY_MAX] __unused) /* TODO int:free_size */ { - return free_cache((int64_t)atoll(arg[0])); /* free_size */ + return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */ } -static int do_rm_cache(char **arg, char reply[REPLY_MAX]) +static int do_rm_cache(char **arg, char reply[REPLY_MAX] __unused) { - return delete_cache(arg[0], atoi(arg[1])); /* pkgname, userid */ + return delete_cache(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */ } -static int do_rm_code_cache(char **arg, char reply[REPLY_MAX]) +static int do_rm_code_cache(char **arg, char reply[REPLY_MAX] __unused) { - return delete_code_cache(arg[0], atoi(arg[1])); /* pkgname, userid */ + return delete_code_cache(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */ } static int do_get_size(char **arg, char reply[REPLY_MAX]) @@ -95,9 +106,9 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) int64_t asecsize = 0; int res = 0; - /* pkgdir, userid, apkpath */ - res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4], arg[5], - arg[6], &codesize, &datasize, &cachesize, &asecsize); + /* uuid, pkgdir, userid, apkpath */ + res = get_size(parse_null(arg[0]), arg[1], atoi(arg[2]), arg[3], arg[4], arg[5], arg[6], + arg[7], &codesize, &datasize, &cachesize, &asecsize); /* * Each int64_t can take up 22 characters printed out. Make sure it @@ -108,51 +119,64 @@ static int do_get_size(char **arg, char reply[REPLY_MAX]) return res; } -static int do_rm_user_data(char **arg, char reply[REPLY_MAX]) +static int do_rm_user_data(char **arg, char reply[REPLY_MAX] __unused) { - return delete_user_data(arg[0], atoi(arg[1])); /* pkgname, userid */ + return delete_user_data(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */ } -static int do_mk_user_data(char **arg, char reply[REPLY_MAX]) +static int do_mv_user_data(char **arg, char reply[REPLY_MAX] __unused) { - return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); - /* pkgname, uid, userid, seinfo */ + // from_uuid, to_uuid, pkgname, appid, seinfo + return move_user_data(parse_null(arg[0]), parse_null(arg[1]), arg[2], atoi(arg[3]), arg[4]); } -static int do_mk_user_config(char **arg, char reply[REPLY_MAX]) +static int do_mk_user_data(char **arg, char reply[REPLY_MAX] __unused) +{ + return make_user_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]); + /* uuid, pkgname, uid, userid, seinfo */ +} + +static int do_mk_user_config(char **arg, char reply[REPLY_MAX] __unused) { return make_user_config(atoi(arg[0])); /* userid */ } -static int do_rm_user(char **arg, char reply[REPLY_MAX]) +static int do_rm_user(char **arg, char reply[REPLY_MAX] __unused) { - return delete_user(atoi(arg[0])); /* userid */ + return delete_user(parse_null(arg[0]), atoi(arg[1])); /* uuid, userid */ } -static int do_movefiles(char **arg, char reply[REPLY_MAX]) +static int do_movefiles(char **arg __unused, char reply[REPLY_MAX] __unused) { return movefiles(); } -static int do_linklib(char **arg, char reply[REPLY_MAX]) +static int do_linklib(char **arg, char reply[REPLY_MAX] __unused) { - return linklib(arg[0], arg[1], atoi(arg[2])); + return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3])); } -static int do_idmap(char **arg, char reply[REPLY_MAX]) +static int do_idmap(char **arg, char reply[REPLY_MAX] __unused) { return idmap(arg[0], arg[1], atoi(arg[2])); } static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((unused))) { - return restorecon_data(arg[0], arg[1], atoi(arg[2])); - /* pkgName, seinfo, uid*/ + return restorecon_data(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3])); + /* uuid, pkgName, seinfo, uid*/ +} + +static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] __unused) +{ + /* oat_dir, instruction_set */ + return create_oat_dir(arg[0], arg[1]); } -static int do_patchoat(char **arg, char reply[REPLY_MAX]) { - /* apk_path, uid, is_public, pkgname, instruction_set, vm_safe_mode, should_relocate */ - return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], 0, 1); +static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] __unused) +{ + /* oat_dir */ + return rm_package_dir(arg[0]); } struct cmdinfo { @@ -163,32 +187,34 @@ struct cmdinfo { struct cmdinfo cmds[] = { { "ping", 0, do_ping }, - { "install", 4, do_install }, - { "dexopt", 6, do_dexopt }, + { "install", 5, do_install }, + { "dexopt", 9, do_dexopt }, { "markbootcomplete", 1, do_mark_boot_complete }, { "movedex", 3, do_move_dex }, { "rmdex", 2, do_rm_dex }, - { "remove", 2, do_remove }, + { "remove", 3, do_remove }, { "rename", 2, do_rename }, - { "fixuid", 3, do_fixuid }, - { "freecache", 1, do_free_cache }, - { "rmcache", 2, do_rm_cache }, - { "rmcodecache", 2, do_rm_code_cache }, - { "getsize", 7, do_get_size }, - { "rmuserdata", 2, do_rm_user_data }, + { "fixuid", 4, do_fixuid }, + { "freecache", 2, do_free_cache }, + { "rmcache", 3, do_rm_cache }, + { "rmcodecache", 3, do_rm_code_cache }, + { "getsize", 8, do_get_size }, + { "rmuserdata", 3, do_rm_user_data }, + { "mvuserdata", 5, do_mv_user_data }, { "movefiles", 0, do_movefiles }, - { "linklib", 3, do_linklib }, - { "mkuserdata", 4, do_mk_user_data }, + { "linklib", 4, do_linklib }, + { "mkuserdata", 5, do_mk_user_data }, { "mkuserconfig", 1, do_mk_user_config }, - { "rmuser", 1, do_rm_user }, + { "rmuser", 2, do_rm_user }, { "idmap", 3, do_idmap }, - { "restorecondata", 3, do_restorecon_data }, - { "patchoat", 5, do_patchoat }, + { "restorecondata", 4, do_restorecon_data }, + { "createoatdir", 2, do_create_oat_dir }, + { "rmpackagedir", 1, do_rm_package_dir}, }; static int readx(int s, void *_buf, int count) { - char *buf = _buf; + char *buf = (char *) _buf; int n = 0, r; if (count < 0) return -1; while (n < count) { @@ -209,7 +235,7 @@ static int readx(int s, void *_buf, int count) static int writex(int s, const void *_buf, int count) { - const char *buf = _buf; + const char *buf = (const char *) _buf; int n = 0, r; if (count < 0) return -1; while (n < count) { @@ -255,7 +281,9 @@ static int execute(int s, char cmd[BUFFER_MAX]) goto done; } } - cmd++; + if (*cmd) { + cmd++; + } } for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) { @@ -333,10 +361,15 @@ int initialize_globals() { return -1; } + // Get the android external app directory. + if (get_path_from_string(&android_mnt_expand_dir, "/mnt/expand/") < 0) { + return -1; + } + // Take note of the system and vendor directories. android_system_dirs.count = 4; - android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t)); + android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t)); if (android_system_dirs.dirs == NULL) { ALOGE("Couldn't allocate array for dirs; aborting\n"); return -1; @@ -354,10 +387,10 @@ int initialize_globals() { android_system_dirs.dirs[1].path = build_string2(android_root_dir.path, PRIV_APP_SUBDIR); android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path); - android_system_dirs.dirs[2].path = "/vendor/app/"; + android_system_dirs.dirs[2].path = strdup("/vendor/app/"); android_system_dirs.dirs[2].len = strlen(android_system_dirs.dirs[2].path); - android_system_dirs.dirs[3].path = "/oem/app/"; + android_system_dirs.dirs[3].path = strdup("/oem/app/"); android_system_dirs.dirs[3].len = strlen(android_system_dirs.dirs[3].path); return 0; @@ -501,7 +534,7 @@ int initialize_directories() { version = 2; } - if (ensure_media_user_dirs(0) == -1) { + if (ensure_media_user_dirs(nullptr, 0) == -1) { ALOGE("Failed to setup media for user 0"); goto fail; } @@ -596,46 +629,6 @@ fail: return res; } -static void drop_privileges() { - if (prctl(PR_SET_KEEPCAPS, 1) < 0) { - ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno)); - exit(1); - } - - if (setgid(AID_INSTALL) < 0) { - ALOGE("setgid() can't drop privileges; exiting.\n"); - exit(1); - } - - if (setuid(AID_INSTALL) < 0) { - ALOGE("setuid() can't drop privileges; exiting.\n"); - exit(1); - } - - struct __user_cap_header_struct capheader; - struct __user_cap_data_struct capdata[2]; - memset(&capheader, 0, sizeof(capheader)); - memset(&capdata, 0, sizeof(capdata)); - capheader.version = _LINUX_CAPABILITY_VERSION_3; - capheader.pid = 0; - - capdata[CAP_TO_INDEX(CAP_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE); - capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted |= CAP_TO_MASK(CAP_CHOWN); - capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID); - capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID); - capdata[CAP_TO_INDEX(CAP_FOWNER)].permitted |= CAP_TO_MASK(CAP_FOWNER); - - capdata[0].effective = capdata[0].permitted; - capdata[1].effective = capdata[1].permitted; - capdata[0].inheritable = 0; - capdata[1].inheritable = 0; - - if (capset(&capheader, &capdata[0]) < 0) { - ALOGE("capset failed: %s\n", strerror(errno)); - exit(1); - } -} - static int log_callback(int type, const char *fmt, ...) { va_list ap; int priority; @@ -657,13 +650,16 @@ static int log_callback(int type, const char *fmt, ...) { return 0; } -int main(const int argc, const char *argv[]) { +int main(const int argc __unused, char *argv[]) { char buf[BUFFER_MAX]; struct sockaddr addr; socklen_t alen; - int lsocket, s, count; + int lsocket, s; int selinux_enabled = (is_selinux_enabled() > 0); + setenv("ANDROID_LOG_TAGS", "*:v", 1); + android::base::InitLogging(argv); + ALOGI("installd firing up\n"); union selinux_callback cb; @@ -685,8 +681,6 @@ int main(const int argc, const char *argv[]) { exit(1); } - drop_privileges(); - lsocket = android_get_control_socket(SOCKET_PATH); if (lsocket < 0) { ALOGE("Failed to get socket from environment: %s\n", strerror(errno)); diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h index a3a5c16..f31bf4f 100644 --- a/cmds/installd/installd.h +++ b/cmds/installd/installd.h @@ -31,6 +31,8 @@ #include <sys/socket.h> #include <sys/types.h> #include <sys/wait.h> +#include <string> +#include <vector> #include <cutils/fs.h> #include <cutils/sockets.h> @@ -40,7 +42,7 @@ #include <private/android_filesystem_config.h> -#if INCLUDE_SYS_MOUNT_FOR_STATFS +#if defined(__APPLE__) #include <sys/mount.h> #else #include <sys/statfs.h> @@ -83,6 +85,13 @@ #define PKG_NAME_MAX 128 /* largest allowed package name */ #define PKG_PATH_MAX 256 /* max size of any path we use */ +/* dexopt needed flags matching those in dalvik.system.DexFile */ +#define DEXOPT_DEX2OAT_NEEDED 1 +#define DEXOPT_PATCHOAT_NEEDED 2 +#define DEXOPT_SELF_PATCHOAT_NEEDED 3 + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) + /* data structures */ typedef struct { @@ -101,6 +110,7 @@ extern dir_rec_t android_app_lib_dir; extern dir_rec_t android_data_dir; extern dir_rec_t android_asec_dir; extern dir_rec_t android_media_dir; +extern dir_rec_t android_mnt_expand_dir; extern dir_rec_array_t android_system_dirs; typedef struct cache_dir_struct { @@ -132,20 +142,22 @@ typedef struct { /* util.c */ -int create_pkg_path_in_dir(char path[PKG_PATH_MAX], - const dir_rec_t* dir, - const char* pkgname, - const char* postfix); +// TODO: rename to create_data_user_package_path +std::string create_package_data_path(const char* volume_uuid, + const char* package_name, userid_t user); int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, const char *postfix, userid_t userid); -int create_user_path(char path[PKG_PATH_MAX], - userid_t userid); +std::string create_data_path(const char* volume_uuid); + +std::string create_data_user_path(const char* volume_uuid, userid_t userid); + +std::string create_data_media_path(const char* volume_uuid, userid_t userid); -int create_user_media_path(char path[PKG_PATH_MAX], userid_t userid); +std::vector<userid_t> get_known_users(const char* volume_uuid); int create_user_config_path(char path[PKG_PATH_MAX], userid_t userid); @@ -169,13 +181,13 @@ int copy_dir_files(const char *srcname, const char *dstname, uid_t owner, gid_t int lookup_media_dir(char basepath[PATH_MAX], const char *dir); -int64_t data_disk_free(); +int64_t data_disk_free(const std::string& data_path); cache_t* start_cache_collection(); void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir); -void clear_cache_files(cache_t* cache, int64_t free_size); +void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size); void finish_cache_collection(cache_t* cache); @@ -191,38 +203,48 @@ int validate_apk_path(const char *path); int append_and_increment(char** dst, const char* src, size_t* dst_size); -char *build_string2(char *s1, char *s2); -char *build_string3(char *s1, char *s2, char *s3); +char *build_string2(const char *s1, const char *s2); +char *build_string3(const char *s1, const char *s2, const char *s3); int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid); -int ensure_media_user_dirs(userid_t userid); +int ensure_media_user_dirs(const char* uuid, userid_t userid); int ensure_config_user_dirs(userid_t userid); int create_profile_file(const char *pkgname, gid_t gid); void remove_profile_file(const char *pkgname); /* commands.c */ -int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo); -int uninstall(const char *pkgname, userid_t userid); +int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo); +int uninstall(const char *uuid, const char *pkgname, userid_t userid); int renamepkg(const char *oldpkgname, const char *newpkgname); -int fix_uid(const char *pkgname, uid_t uid, gid_t gid); -int delete_user_data(const char *pkgname, userid_t userid); -int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo); +int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid); +int delete_user_data(const char *uuid, const char *pkgname, userid_t userid); +int make_user_data(const char *uuid, const char *pkgname, uid_t uid, + userid_t userid, const char* seinfo); +int move_user_data(const char* from_uuid, const char *to_uuid, + const char *package_name, appid_t appid, const char* seinfo); int make_user_config(userid_t userid); -int delete_user(userid_t userid); -int delete_cache(const char *pkgname, userid_t userid); -int delete_code_cache(const char *pkgname, userid_t userid); +int delete_user(const char *uuid, userid_t userid); +int delete_cache(const char *uuid, const char *pkgname, userid_t userid); +int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid); int move_dex(const char *src, const char *dst, const char *instruction_set); int rm_dex(const char *path, const char *instruction_set); int protect(char *pkgname, gid_t gid); -int get_size(const char *pkgname, userid_t userid, const char *apkpath, const char *libdirpath, +int get_size(const char *uuid, const char *pkgname, userid_t userid, const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, const char *instruction_set, int64_t *codesize, int64_t *datasize, int64_t *cachesize, int64_t *asecsize); -int free_cache(int64_t free_size); +int free_cache(const char *uuid, int64_t free_size); int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName, - const char *instruction_set, bool vm_safe_mode, bool should_relocate); + const char *instruction_set, int dexopt_needed, bool vm_safe_mode, + bool debuggable, const char* oat_dir); int mark_boot_complete(const char *instruction_set); int movefiles(); -int linklib(const char* target, const char* source, int userId); +int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId); int idmap(const char *target_path, const char *overlay_path, uid_t uid); -int restorecon_data(); +int restorecon_data(const char *uuid, const char* pkgName, const char* seinfo, uid_t uid); +int create_oat_dir(const char* oat_dir, const char *instruction_set); +int rm_package_dir(const char* apk_path); +int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, + const char *instruction_set); +int move_package_dir(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, + const char *instruction_set); diff --git a/cmds/installd/tests/Android.mk b/cmds/installd/tests/Android.mk index 4faf3c0..38a9f69 100644 --- a/cmds/installd/tests/Android.mk +++ b/cmds/installd/tests/Android.mk @@ -1,21 +1,20 @@ # Build the unit tests for installd LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk # Build the unit tests. test_src_files := \ installd_utils_test.cpp shared_libraries := \ + libbase \ libutils \ libcutils \ - libstlport static_libraries := \ libinstalld \ libdiskusage \ - libgtest \ - libgtest_main c_includes := \ frameworks/native/cmds/installd @@ -27,5 +26,6 @@ $(foreach file,$(test_src_files), \ $(eval LOCAL_SRC_FILES := $(file)) \ $(eval LOCAL_C_INCLUDES := $(c_includes)) \ $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \ + $(eval LOCAL_CLANG := true) \ $(eval include $(BUILD_NATIVE_TEST)) \ ) diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp index 94e4792..4ce559d 100644 --- a/cmds/installd/tests/installd_utils_test.cpp +++ b/cmds/installd/tests/installd_utils_test.cpp @@ -17,19 +17,18 @@ #include <stdlib.h> #include <string.h> -#define LOG_TAG "utils_test" -#include <utils/Log.h> - #include <gtest/gtest.h> -extern "C" { #include "installd.h" -} + +#undef LOG_TAG +#define LOG_TAG "utils_test" #define TEST_DATA_DIR "/data/" #define TEST_APP_DIR "/data/app/" #define TEST_APP_PRIVATE_DIR "/data/app-private/" #define TEST_ASEC_DIR "/mnt/asec/" +#define TEST_EXPAND_DIR "/mnt/expand/" #define TEST_SYSTEM_DIR1 "/system/app/" #define TEST_SYSTEM_DIR2 "/vendor/app/" @@ -49,25 +48,28 @@ namespace android { class UtilsTest : public testing::Test { protected: virtual void SetUp() { - android_app_dir.path = TEST_APP_DIR; + android_app_dir.path = (char*) TEST_APP_DIR; android_app_dir.len = strlen(TEST_APP_DIR); - android_app_private_dir.path = TEST_APP_PRIVATE_DIR; + android_app_private_dir.path = (char*) TEST_APP_PRIVATE_DIR; android_app_private_dir.len = strlen(TEST_APP_PRIVATE_DIR); - android_data_dir.path = TEST_DATA_DIR; + android_data_dir.path = (char*) TEST_DATA_DIR; android_data_dir.len = strlen(TEST_DATA_DIR); - android_asec_dir.path = TEST_ASEC_DIR; + android_asec_dir.path = (char*) TEST_ASEC_DIR; android_asec_dir.len = strlen(TEST_ASEC_DIR); + android_mnt_expand_dir.path = (char*) TEST_EXPAND_DIR; + android_mnt_expand_dir.len = strlen(TEST_EXPAND_DIR); + android_system_dirs.count = 2; android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t)); - android_system_dirs.dirs[0].path = TEST_SYSTEM_DIR1; + android_system_dirs.dirs[0].path = (char*) TEST_SYSTEM_DIR1; android_system_dirs.dirs[0].len = strlen(TEST_SYSTEM_DIR1); - android_system_dirs.dirs[1].path = TEST_SYSTEM_DIR2; + android_system_dirs.dirs[1].path = (char*) TEST_SYSTEM_DIR2; android_system_dirs.dirs[1].len = strlen(TEST_SYSTEM_DIR2); } @@ -319,6 +321,7 @@ TEST_F(UtilsTest, CreatePkgPath_LongPkgNameSuccess) { const char *prefix = TEST_DATA_DIR PRIMARY_USER_PREFIX; size_t offset = strlen(prefix); + EXPECT_STREQ(pkgname, path + offset) << "Package path should be a really long string of a's"; } @@ -369,40 +372,6 @@ TEST_F(UtilsTest, CreatePkgPath_SecondaryUser) { << "Package path should be in /data/user/"; } -TEST_F(UtilsTest, CreatePkgPathInDir_ProtectedDir) { - char path[PKG_PATH_MAX]; - - dir_rec_t dir; - dir.path = "/data/app-private/"; - dir.len = strlen(dir.path); - - EXPECT_EQ(0, create_pkg_path_in_dir(path, &dir, "com.example.package", ".apk")) - << "Should successfully create package path."; - - EXPECT_STREQ("/data/app-private/com.example.package.apk", path) - << "Package path should be in /data/app-private/"; -} - -TEST_F(UtilsTest, CreatePersonaPath_Primary) { - char path[PKG_PATH_MAX]; - - EXPECT_EQ(0, create_user_path(path, 0)) - << "Should successfully build primary user path."; - - EXPECT_STREQ("/data/data/", path) - << "Primary user should have correct path"; -} - -TEST_F(UtilsTest, CreatePersonaPath_Secondary) { - char path[PKG_PATH_MAX]; - - EXPECT_EQ(0, create_user_path(path, 1)) - << "Should successfully build primary user path."; - - EXPECT_STREQ("/data/user/1/", path) - << "Primary user should have correct path"; -} - TEST_F(UtilsTest, CreateMovePath_Primary) { char path[PKG_PATH_MAX]; @@ -432,7 +401,7 @@ TEST_F(UtilsTest, CopyAndAppend_Normal) { dir_rec_t dst; dir_rec_t src; - src.path = "/data/"; + src.path = (char*) "/data/"; src.len = strlen(src.path); EXPECT_EQ(0, copy_and_append(&dst, &src, "app/")) @@ -480,4 +449,40 @@ TEST_F(UtilsTest, AppendAndIncrement_TooBig) { << "String should fail because it's too large to fit"; } +TEST_F(UtilsTest, CreateDataPath) { + EXPECT_EQ("/data", create_data_path(nullptr)); + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b", + create_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b")); +} + +TEST_F(UtilsTest, CreateDataUserPath) { + EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0)); + EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10)); + + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0", + create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0)); + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10", + create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10)); +} + +TEST_F(UtilsTest, CreateDataMediaPath) { + EXPECT_EQ("/data/media/0", create_data_media_path(nullptr, 0)); + EXPECT_EQ("/data/media/10", create_data_media_path(nullptr, 10)); + + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/media/0", + create_data_media_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0)); + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/media/10", + create_data_media_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10)); +} + +TEST_F(UtilsTest, CreatePackageDataPath) { + EXPECT_EQ("/data/data/com.example", create_package_data_path(nullptr, "com.example", 0)); + EXPECT_EQ("/data/user/10/com.example", create_package_data_path(nullptr, "com.example", 10)); + + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example", + create_package_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example", 0)); + EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example", + create_package_data_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example", 10)); +} + } diff --git a/cmds/installd/utils.c b/cmds/installd/utils.cpp index e381aef..ba411cd 100644 --- a/cmds/installd/utils.c +++ b/cmds/installd/utils.cpp @@ -16,137 +16,119 @@ #include "installd.h" -#define CACHE_NOISY(x) //x - -int create_pkg_path_in_dir(char path[PKG_PATH_MAX], - const dir_rec_t* dir, - const char* pkgname, - const char* postfix) -{ - const size_t postfix_len = strlen(postfix); - - const size_t pkgname_len = strlen(pkgname); - if (pkgname_len > PKG_NAME_MAX) { - return -1; - } - - if (is_valid_package_name(pkgname) < 0) { - return -1; - } - - if ((pkgname_len + dir->len + postfix_len) >= PKG_PATH_MAX) { - return -1; - } - - char *dst = path; - size_t dst_size = PKG_PATH_MAX; +#include <base/stringprintf.h> +#include <base/logging.h> - if (append_and_increment(&dst, dir->path, &dst_size) < 0 - || append_and_increment(&dst, pkgname, &dst_size) < 0 - || append_and_increment(&dst, postfix, &dst_size) < 0) { - ALOGE("Error building APK path"); - return -1; - } +#define CACHE_NOISY(x) //x - return 0; -} +using android::base::StringPrintf; /** - * Create the package path name for a given package name with a postfix for - * a certain userid. Returns 0 on success, and -1 on failure. + * Check that given string is valid filename, and that it attempts no + * parent or child directory traversal. */ -int create_pkg_path(char path[PKG_PATH_MAX], - const char *pkgname, - const char *postfix, - userid_t userid) -{ - size_t userid_len; - char* userid_prefix; - if (userid == 0) { - userid_prefix = PRIMARY_USER_PREFIX; - userid_len = 0; +static bool is_valid_filename(const std::string& name) { + if (name.empty() || (name == ".") || (name == "..") + || (name.find('/') != std::string::npos)) { + return false; } else { - userid_prefix = SECONDARY_USER_PREFIX; - userid_len = snprintf(NULL, 0, "%d", userid); + return true; } +} - const size_t prefix_len = android_data_dir.len + strlen(userid_prefix) - + userid_len + 1 /*slash*/; - char prefix[prefix_len + 1]; +/** + * Create the path name where package data should be stored for the given + * volume UUID, package name, and user ID. An empty UUID is assumed to be + * internal storage. + */ +std::string create_package_data_path(const char* volume_uuid, + const char* package_name, userid_t user) { + CHECK(is_valid_filename(package_name)); + CHECK(is_valid_package_name(package_name) == 0); - char *dst = prefix; - size_t dst_size = sizeof(prefix); + return StringPrintf("%s/%s", create_data_user_path(volume_uuid, user).c_str(), package_name); +} - if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0 - || append_and_increment(&dst, userid_prefix, &dst_size) < 0) { - ALOGE("Error building prefix for APK path"); +int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname, + const char *postfix, userid_t userid) { + if (is_valid_package_name(pkgname) != 0) { + path[0] = '\0'; return -1; } - if (userid != 0) { - int ret = snprintf(dst, dst_size, "%d/", userid); - if (ret < 0 || (size_t) ret != userid_len + 1) { - ALOGW("Error appending UID to APK path"); - return -1; - } + std::string _tmp(create_package_data_path(nullptr, pkgname, userid) + postfix); + const char* tmp = _tmp.c_str(); + if (strlen(tmp) >= PKG_PATH_MAX) { + path[0] = '\0'; + return -1; + } else { + strcpy(path, tmp); + return 0; } +} - dir_rec_t dir; - dir.path = prefix; - dir.len = prefix_len; - - return create_pkg_path_in_dir(path, &dir, pkgname, postfix); +std::string create_data_path(const char* volume_uuid) { + if (volume_uuid == nullptr) { + return "/data"; + } else { + CHECK(is_valid_filename(volume_uuid)); + return StringPrintf("/mnt/expand/%s", volume_uuid); + } } /** * Create the path name for user data for a certain userid. - * Returns 0 on success, and -1 on failure. */ -int create_user_path(char path[PKG_PATH_MAX], - userid_t userid) -{ - size_t userid_len; - char* userid_prefix; - if (userid == 0) { - userid_prefix = PRIMARY_USER_PREFIX; - userid_len = 0; +std::string create_data_user_path(const char* volume_uuid, userid_t userid) { + std::string data(create_data_path(volume_uuid)); + if (volume_uuid == nullptr) { + if (userid == 0) { + return StringPrintf("%s/data", data.c_str()); + } else { + return StringPrintf("%s/user/%u", data.c_str(), userid); + } } else { - userid_prefix = SECONDARY_USER_PREFIX; - userid_len = snprintf(NULL, 0, "%d/", userid); + return StringPrintf("%s/user/%u", data.c_str(), userid); } +} - char *dst = path; - size_t dst_size = PKG_PATH_MAX; +/** + * Create the path name for media for a certain userid. + */ +std::string create_data_media_path(const char* volume_uuid, userid_t userid) { + return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid); +} - if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0 - || append_and_increment(&dst, userid_prefix, &dst_size) < 0) { - ALOGE("Error building prefix for user path"); - return -1; +std::vector<userid_t> get_known_users(const char* volume_uuid) { + std::vector<userid_t> users; + + // We always have an owner + users.push_back(0); + + std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX); + DIR* dir = opendir(path.c_str()); + if (dir == NULL) { + // Unable to discover other users, but at least return owner + PLOG(ERROR) << "Failed to opendir " << path; + return users; } - if (userid != 0) { - if (dst_size < userid_len + 1) { - ALOGE("Error building user path"); - return -1; + struct dirent* ent; + while ((ent = readdir(dir))) { + if (ent->d_type != DT_DIR) { + continue; } - int ret = snprintf(dst, dst_size, "%d/", userid); - if (ret < 0 || (size_t) ret != userid_len) { - ALOGE("Error appending userid to path"); - return -1; + + char* end; + userid_t user = strtol(ent->d_name, &end, 10); + if (*end == '\0' && user != 0) { + LOG(DEBUG) << "Found valid user " << user; + users.push_back(user); } } - return 0; -} + closedir(dir); -/** - * Create the path name for media for a certain userid. - * Returns 0 on success, and -1 on failure. - */ -int create_user_media_path(char path[PATH_MAX], userid_t userid) { - if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) { - return -1; - } - return 0; + return users; } /** @@ -163,7 +145,7 @@ int create_user_config_path(char path[PATH_MAX], userid_t userid) { int create_move_path(char path[PKG_PATH_MAX], const char* pkgname, const char* leaf, - userid_t userid) + userid_t userid __unused) { if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1) >= PKG_PATH_MAX) { @@ -182,6 +164,10 @@ int is_valid_package_name(const char* pkgname) { const char *x = pkgname; int alpha = -1; + if (strlen(pkgname) > PKG_NAME_MAX) { + return -1; + } + while (*x) { if (isalnum(*x) || (*x == '_')) { /* alphanumeric or underscore are fine */ @@ -239,7 +225,7 @@ static int _delete_dir_contents(DIR *d, } if (de->d_type == DT_DIR) { - int r, subfd; + int subfd; DIR *subdir; /* always skip "." and ".." */ @@ -472,13 +458,13 @@ int lookup_media_dir(char basepath[PATH_MAX], const char *dir) return -1; } -int64_t data_disk_free() +int64_t data_disk_free(const std::string& data_path) { struct statfs sfs; - if (statfs(android_data_dir.path, &sfs) == 0) { + if (statfs(data_path.c_str(), &sfs) == 0) { return sfs.f_bavail * sfs.f_bsize; } else { - ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno)); + PLOG(ERROR) << "Couldn't statfs " << data_path; return -1; } } @@ -516,7 +502,7 @@ static void* _cache_malloc(cache_t* cache, size_t len) int8_t* res = cache->curMemBlockAvail; int8_t* nextPos = res + len; if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) { - int8_t* newBlock = malloc(CACHE_BLOCK_SIZE); + int8_t* newBlock = (int8_t*) malloc(CACHE_BLOCK_SIZE); if (newBlock == NULL) { return NULL; } @@ -836,7 +822,7 @@ static int cache_modtime_sort(const void *lhsP, const void *rhsP) return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0); } -void clear_cache_files(cache_t* cache, int64_t free_size) +void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size) { size_t i; int skip = 0; @@ -861,7 +847,7 @@ void clear_cache_files(cache_t* cache, int64_t free_size) for (i=0; i<cache->numFiles; i++) { skip++; if (skip > 10) { - if (data_disk_free() > free_size) { + if (data_disk_free(data_path) > free_size) { return; } skip = 0; @@ -881,7 +867,7 @@ void clear_cache_files(cache_t* cache, int64_t free_size) void finish_cache_collection(cache_t* cache) { - size_t i; + CACHE_NOISY(size_t i;) CACHE_NOISY(ALOGI("clear_cache_files: %d dirs, %d files\n", cache->numDirs, cache->numFiles)); CACHE_NOISY( @@ -910,14 +896,14 @@ void finish_cache_collection(cache_t* cache) * The path is allowed to have at most one subdirectory and no indirections * to top level directories (i.e. have ".."). */ -static int validate_path(const dir_rec_t* dir, const char* path) { +static int validate_path(const dir_rec_t* dir, const char* path, int maxSubdirs) { size_t dir_len = dir->len; const char* subdir = strchr(path + dir_len, '/'); // Only allow the path to have at most one subdirectory. if (subdir != NULL) { ++subdir; - if (strchr(subdir, '/') != NULL) { + if ((--maxSubdirs == 0) && strchr(subdir, '/') != NULL) { ALOGE("invalid apk path '%s' (subdir?)\n", path); return -1; } @@ -942,7 +928,7 @@ int validate_system_app_path(const char* path) { for (i = 0; i < android_system_dirs.count; i++) { const size_t dir_len = android_system_dirs.dirs[i].len; if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) { - return validate_path(android_system_dirs.dirs + i, path); + return validate_path(android_system_dirs.dirs + i, path, 1); } } @@ -1000,7 +986,7 @@ int get_path_from_string(dir_rec_t* rec, const char* path) { // Add space for slash and terminating null. size_t dst_size = path_len + 2; - rec->path = malloc(dst_size); + rec->path = (char*) malloc(dst_size); if (rec->path == NULL) { return -1; } @@ -1042,6 +1028,7 @@ int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) { int validate_apk_path(const char *path) { const dir_rec_t* dir = NULL; + int maxSubdirs = 1; if (!strncmp(path, android_app_dir.path, android_app_dir.len)) { dir = &android_app_dir; @@ -1049,11 +1036,14 @@ int validate_apk_path(const char *path) dir = &android_app_private_dir; } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) { dir = &android_asec_dir; + } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) { + dir = &android_mnt_expand_dir; + maxSubdirs = 2; } else { return -1; } - return validate_path(dir, path); + return validate_path(dir, path, maxSubdirs); } int append_and_increment(char** dst, const char* src, size_t* dst_size) { @@ -1066,13 +1056,13 @@ int append_and_increment(char** dst, const char* src, size_t* dst_size) { return 0; } -char *build_string2(char *s1, char *s2) { +char *build_string2(const char *s1, const char *s2) { if (s1 == NULL || s2 == NULL) return NULL; int len_s1 = strlen(s1); int len_s2 = strlen(s2); int len = len_s1 + len_s2 + 1; - char *result = malloc(len); + char *result = (char *) malloc(len); if (result == NULL) return NULL; strcpy(result, s1); @@ -1081,14 +1071,14 @@ char *build_string2(char *s1, char *s2) { return result; } -char *build_string3(char *s1, char *s2, char *s3) { +char *build_string3(const char *s1, const char *s2, const char *s3) { if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL; int len_s1 = strlen(s1); int len_s2 = strlen(s2); int len_s3 = strlen(s3); int len = len_s1 + len_s2 + len_s3 + 1; - char *result = malloc(len); + char *result = (char *) malloc(len); if (result == NULL) return NULL; strcpy(result, s1); @@ -1099,13 +1089,9 @@ char *build_string3(char *s1, char *s2, char *s3) { } /* Ensure that /data/media directories are prepared for given user. */ -int ensure_media_user_dirs(userid_t userid) { - char media_user_path[PATH_MAX]; - char path[PATH_MAX]; - - // Ensure /data/media/<userid> exists - create_user_media_path(media_user_path, userid); - if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { +int ensure_media_user_dirs(const char* uuid, userid_t userid) { + std::string media_user_path(create_data_media_path(uuid, userid)); + if (fs_prepare_dir(media_user_path.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { return -1; } @@ -1114,7 +1100,6 @@ int ensure_media_user_dirs(userid_t userid) { int ensure_config_user_dirs(userid_t userid) { char config_user_path[PATH_MAX]; - char path[PATH_MAX]; // writable by system, readable by any app within the same user const int uid = multiuser_get_uid(userid, AID_SYSTEM); diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c index e02b45d..fd91633 100644 --- a/cmds/servicemanager/bctest.c +++ b/cmds/servicemanager/bctest.c @@ -3,6 +3,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <errno.h> #include "binder.h" diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c index db7632d..6eecee1 100644 --- a/cmds/servicemanager/binder.c +++ b/cmds/servicemanager/binder.c @@ -4,6 +4,7 @@ #include <inttypes.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> @@ -112,7 +113,9 @@ struct binder_state *binder_open(size_t mapsize) if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) || (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) { - fprintf(stderr, "binder: driver version differs from user space\n"); + fprintf(stderr, + "binder: kernel driver version (%d) differs from user space version (%d)\n", + vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION); goto fail_open; } diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c index f37427a..cacfe14 100644 --- a/cmds/servicemanager/service_manager.c +++ b/cmds/servicemanager/service_manager.c @@ -1,10 +1,12 @@ /* Copyright 2008 The Android Open Source Project */ -#include <stdio.h> -#include <stdlib.h> #include <errno.h> #include <fcntl.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <private/android_filesystem_config.h> @@ -21,8 +23,6 @@ #include <cutils/log.h> #endif -uint32_t svcmgr_handle; - const char *str8(const uint16_t *x, size_t x_len) { static char buf[128]; @@ -169,28 +169,26 @@ uint16_t svcmgr_id[] = { uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid) { - struct svcinfo *si; + struct svcinfo *si = find_svc(s, len); - if (!svc_can_find(s, len, spid)) { - ALOGE("find_service('%s') uid=%d - PERMISSION DENIED\n", - str8(s, len), uid); + if (!si || !si->handle) { return 0; } - si = find_svc(s, len); - //ALOGI("check_service('%s') handle = %x\n", str8(s, len), si ? si->handle : 0); - if (si && si->handle) { - if (!si->allow_isolated) { - // If this service doesn't allow access from isolated processes, - // then check the uid to see if it is isolated. - uid_t appid = uid % AID_USER; - if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { - return 0; - } + + if (!si->allow_isolated) { + // If this service doesn't allow access from isolated processes, + // then check the uid to see if it is isolated. + uid_t appid = uid % AID_USER; + if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) { + return 0; } - return si->handle; - } else { + } + + if (!svc_can_find(s, len, spid)) { return 0; } + + return si->handle; } int do_add_service(struct binder_state *bs, @@ -255,10 +253,10 @@ int svcmgr_handler(struct binder_state *bs, uint32_t strict_policy; int allow_isolated; - //ALOGI("target=%x code=%d pid=%d uid=%d\n", - // txn->target.handle, txn->code, txn->sender_pid, txn->sender_euid); + //ALOGI("target=%p code=%d pid=%d uid=%d\n", + // (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid); - if (txn->target.handle != svcmgr_handle) + if (txn->target.ptr != BINDER_SERVICE_MANAGER) return -1; if (txn->code == PING_TRANSACTION) @@ -382,7 +380,6 @@ int main(int argc, char **argv) cb.func_log = selinux_log_callback; selinux_set_callback(SELINUX_CB_LOG, cb); - svcmgr_handle = BINDER_SERVICE_MANAGER; binder_loop(bs, svcmgr_handler); return 0; |