From e2965141716530898964afcc0cc03d72be190b21 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 16 Dec 2015 13:20:37 -0700 Subject: Re-derive permissions after package changes. When packages change, existing package-specific directories may have gained/lost a UID mapping, so we need to update the permissions for any in-memory nodes. This allows an app to deliver data for another package before that package is installed, which is the typical pattern of how OBB files are delivered. Also fix bug by re-deriving permissions when files are moved. Bug: 25399427 Change-Id: I06f38a24ad7dee5f5099ba81429aef03208e5683 (cherry picked from commit f7aad11c1cc133e352333f83e3abbf323cd41ead) --- sdcard/sdcard.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index a79e2dd..06452aa 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -507,6 +507,16 @@ static void derive_permissions_locked(struct fuse* fuse, struct node *parent, } } +static void derive_permissions_recursive_locked(struct fuse* fuse, struct node *parent) { + struct node *node; + for (node = parent->child; node; node = node->next) { + derive_permissions_locked(fuse, parent, node); + if (node->child) { + derive_permissions_recursive_locked(fuse, node); + } + } +} + /* Kernel has already enforced everything we returned through * derive_permissions_locked(), so this is used to lock down access * even further, such as enforcing that apps hold sdcard_rw. */ @@ -1145,6 +1155,8 @@ static int handle_rename(struct fuse* fuse, struct fuse_handler* handler, res = rename_node_locked(child_node, new_name, new_actual_name); if (!res) { remove_node_from_parent_locked(child_node); + derive_permissions_locked(fuse, new_parent_node, child_node); + derive_permissions_recursive_locked(fuse, child_node); add_node_to_parent_locked(child_node, new_parent_node); } goto done; @@ -1663,6 +1675,10 @@ static int read_package_list(struct fuse_global* global) { TRACE("read_package_list: found %zu packages\n", hashmapSize(global->package_to_appid)); fclose(file); + + /* Regenerate ownership details using newly loaded mapping */ + derive_permissions_recursive_locked(global->fuse_default, &global->root); + pthread_mutex_unlock(&global->lock); return 0; } -- cgit v1.1 From e1d784619a3c5de9073465645eb98ea6595a4507 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Tue, 16 Feb 2016 15:01:43 -0800 Subject: Don't create tombstone directory. Partial backport of cf79748. Bug: http://b/26403620 Change-Id: Ib877ab6cfab6aef079830c5a50ba81141ead35ee --- debuggerd/tombstone.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp index b0ad274..aeffc66 100644 --- a/debuggerd/tombstone.cpp +++ b/debuggerd/tombstone.cpp @@ -788,21 +788,8 @@ char* engrave_tombstone(pid_t pid, pid_t tid, int signal, int original_si_code, log.current_tid = tid; log.crashed_tid = tid; - if ((mkdir(TOMBSTONE_DIR, 0755) == -1) && (errno != EEXIST)) { - _LOG(&log, logtype::ERROR, "failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno)); - } - - if (chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM) == -1) { - _LOG(&log, logtype::ERROR, "failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno)); - } - int fd = -1; - char* path = NULL; - if (selinux_android_restorecon(TOMBSTONE_DIR, 0) == 0) { - path = find_and_open_tombstone(&fd); - } else { - _LOG(&log, logtype::ERROR, "Failed to restore security context, not writing tombstone.\n"); - } + char* path = find_and_open_tombstone(&fd); if (fd < 0) { _LOG(&log, logtype::ERROR, "Skipping tombstone write, nothing to do.\n"); -- cgit v1.1 From 213af3ac2a9cac2049e930bef6b63f582901c922 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Tue, 16 Feb 2016 15:01:43 -0800 Subject: Don't create tombstone directory. Partial backport of cf79748. Bug: http://b/26403620 Change-Id: Ib877ab6cfab6aef079830c5a50ba81141ead35ee --- debuggerd/tombstone.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp index b0ad274..aeffc66 100644 --- a/debuggerd/tombstone.cpp +++ b/debuggerd/tombstone.cpp @@ -788,21 +788,8 @@ char* engrave_tombstone(pid_t pid, pid_t tid, int signal, int original_si_code, log.current_tid = tid; log.crashed_tid = tid; - if ((mkdir(TOMBSTONE_DIR, 0755) == -1) && (errno != EEXIST)) { - _LOG(&log, logtype::ERROR, "failed to create %s: %s\n", TOMBSTONE_DIR, strerror(errno)); - } - - if (chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM) == -1) { - _LOG(&log, logtype::ERROR, "failed to change ownership of %s: %s\n", TOMBSTONE_DIR, strerror(errno)); - } - int fd = -1; - char* path = NULL; - if (selinux_android_restorecon(TOMBSTONE_DIR, 0) == 0) { - path = find_and_open_tombstone(&fd); - } else { - _LOG(&log, logtype::ERROR, "Failed to restore security context, not writing tombstone.\n"); - } + char* path = find_and_open_tombstone(&fd); if (fd < 0) { _LOG(&log, logtype::ERROR, "Skipping tombstone write, nothing to do.\n"); -- cgit v1.1 From 8b964f37d7826d7531d42a66ca446e2dc23aff74 Mon Sep 17 00:00:00 2001 From: Pat Erley Date: Fri, 18 Mar 2016 14:00:26 -0700 Subject: libcutils: make sched_policy more robust If you compile with cpusets enabled but the permissions are wrong the behavior becomes no real policy enforced at all. Fix this by making sched_policy fall back gracefully. Change-Id: Ife96ca64b991e23232a5bd0d6c21e30a5d16bde8 --- libcutils/sched_policy.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c index 70dc8c4..a243c90 100644 --- a/libcutils/sched_policy.c +++ b/libcutils/sched_policy.c @@ -55,6 +55,7 @@ static inline SchedPolicy _policy(SchedPolicy p) static pthread_once_t the_once = PTHREAD_ONCE_INIT; static int __sys_supports_schedgroups = -1; +static int __sys_supports_cpusets = -1; // File descriptors open to /dev/cpuctl/../tasks, setup by initialize, or -1 on error. static int bg_cgroup_fd = -1; @@ -109,12 +110,22 @@ static void __initialize(void) { fg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC); if (fg_cgroup_fd < 0) { SLOGE("open of %s failed: %s\n", filename, strerror(errno)); + __sys_supports_schedgroups = 0; } filename = "/dev/cpuctl/bg_non_interactive/tasks"; bg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC); if (bg_cgroup_fd < 0) { SLOGE("open of %s failed: %s\n", filename, strerror(errno)); + __sys_supports_schedgroups = 0; + } + + if (!__sys_supports_schedgroups) { + close(bg_cgroup_fd); + bg_cgroup_fd = -1; + + close(fg_cgroup_fd); + fg_cgroup_fd = -1; } } else { __sys_supports_schedgroups = 0; @@ -122,13 +133,41 @@ static void __initialize(void) { #ifdef USE_CPUSETS if (!access("/dev/cpuset/tasks", F_OK)) { + __sys_supports_cpusets = 1; filename = "/dev/cpuset/foreground/tasks"; fg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC); + if (fg_cpuset_fd < 0) { + SLOGE("open of %s failed %s\n", filename, strerror(errno)); + __sys_supports_cpusets = 0; + } + filename = "/dev/cpuset/background/tasks"; bg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC); + if (bg_cpuset_fd < 0) { + SLOGE("open of %s failed %s\n", filename, strerror(errno)); + __sys_supports_cpusets = 0; + } + filename = "/dev/cpuset/system-background/tasks"; system_bg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC); + if (system_bg_cpuset_fd < 0) { + SLOGE("open of %s failed %s\n", filename, strerror(errno)); + __sys_supports_cpusets = 0; + } + + if (!__sys_supports_cpusets) { + close(fg_cpuset_fd); + fg_cpuset_fd = -1; + + close(bg_cpuset_fd); + bg_cpuset_fd = -1; + + close(system_bg_cpuset_fd); + system_bg_cpuset_fd = -1; + } + } else { + __sys_supports_cpusets = 0; } #endif @@ -250,9 +289,14 @@ int set_cpuset_policy(int tid, SchedPolicy policy) if (tid == 0) { tid = gettid(); } - policy = _policy(policy); + pthread_once(&the_once, __initialize); + if (!__sys_supports_cpusets) + return set_sched_policy(tid, policy); + + policy = _policy(policy); + int fd; switch (policy) { case SP_BACKGROUND: -- cgit v1.1 From 266e3dd01105ad4e7004835d0688a7a3d9edf5dc Mon Sep 17 00:00:00 2001 From: Pat Erley Date: Fri, 18 Mar 2016 13:58:24 -0700 Subject: libcutils: Add process name to logs This can help resolve permissions issues for tasks that want to twiddle the perf bits but don't have permissions. Change-Id: I6285c5c38224d1fb207cb26229cd7b779a8322ac --- libcutils/sched_policy.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c index a243c90..4d69eac 100644 --- a/libcutils/sched_policy.c +++ b/libcutils/sched_policy.c @@ -56,6 +56,7 @@ static pthread_once_t the_once = PTHREAD_ONCE_INIT; static int __sys_supports_schedgroups = -1; static int __sys_supports_cpusets = -1; +static char proc_name[32] = {0}; // File descriptors open to /dev/cpuctl/../tasks, setup by initialize, or -1 on error. static int bg_cgroup_fd = -1; @@ -70,7 +71,7 @@ static int fg_cpuset_fd = -1; static int add_tid_to_cgroup(int tid, int fd) { if (fd < 0) { - SLOGE("add_tid_to_cgroup failed; fd=%d\n", fd); + SLOGE("%s add_tid_to_cgroup failed; fd=%d\n", proc_name, fd); errno = EINVAL; return -1; } @@ -92,8 +93,8 @@ static int add_tid_to_cgroup(int tid, int fd) */ if (errno == ESRCH) return 0; - SLOGW("add_tid_to_cgroup failed to write '%s' (%s); fd=%d\n", - ptr, strerror(errno), fd); + SLOGW("%s add_tid_to_cgroup failed to write '%s' (%s); fd=%d\n", + proc_name, ptr, strerror(errno), fd); errno = EINVAL; return -1; } @@ -102,6 +103,17 @@ static int add_tid_to_cgroup(int tid, int fd) } static void __initialize(void) { + int pfd; + int ptid = gettid(); + + sprintf(proc_name, "/proc/%d/cmdline", ptid); + + pfd = open(proc_name, O_RDONLY); + if (pfd > 0) { + read(pfd, proc_name, sizeof(proc_name) - 1); + close(pfd); + } + char* filename; if (!access("/dev/cpuctl/tasks", F_OK)) { __sys_supports_schedgroups = 1; @@ -109,14 +121,14 @@ static void __initialize(void) { filename = "/dev/cpuctl/tasks"; fg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC); if (fg_cgroup_fd < 0) { - SLOGE("open of %s failed: %s\n", filename, strerror(errno)); + SLOGE("%s open of %s failed: %s\n", proc_name, filename, strerror(errno)); __sys_supports_schedgroups = 0; } filename = "/dev/cpuctl/bg_non_interactive/tasks"; bg_cgroup_fd = open(filename, O_WRONLY | O_CLOEXEC); if (bg_cgroup_fd < 0) { - SLOGE("open of %s failed: %s\n", filename, strerror(errno)); + SLOGE("%s open of %s failed: %s\n", proc_name, filename, strerror(errno)); __sys_supports_schedgroups = 0; } @@ -138,21 +150,21 @@ static void __initialize(void) { filename = "/dev/cpuset/foreground/tasks"; fg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC); if (fg_cpuset_fd < 0) { - SLOGE("open of %s failed %s\n", filename, strerror(errno)); + SLOGE("%s open of %s failed %s\n", proc_name, filename, strerror(errno)); __sys_supports_cpusets = 0; } filename = "/dev/cpuset/background/tasks"; bg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC); if (bg_cpuset_fd < 0) { - SLOGE("open of %s failed %s\n", filename, strerror(errno)); + SLOGE("%s open of %s failed %s\n", proc_name, filename, strerror(errno)); __sys_supports_cpusets = 0; } filename = "/dev/cpuset/system-background/tasks"; system_bg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC); if (system_bg_cpuset_fd < 0) { - SLOGE("open of %s failed %s\n", filename, strerror(errno)); + SLOGE("%s open of %s failed %s\n", proc_name, filename, strerror(errno)); __sys_supports_cpusets = 0; } @@ -232,11 +244,11 @@ static int getSchedulerGroup(int tid, char* buf, size_t bufLen) return 0; } - SLOGE("Failed to find cpu subsys"); + SLOGE("%s Failed to find cpu subsys", proc_name); fclose(fp); return -1; out_bad_data: - SLOGE("Bad cgroup data {%s}", lineBuf); + SLOGE("%s Bad cgroup data {%s}", proc_name, lineBuf); fclose(fp); return -1; #else -- cgit v1.1 From bc667ac5f12fd82fe16f4aa9f4883a4b010f10ca Mon Sep 17 00:00:00 2001 From: Pat Erley Date: Fri, 18 Mar 2016 14:01:14 -0700 Subject: sched_policy: Split cpuset/cgroup init If a task only ever touches cgroups, don't initialize cpusets. This makes logging fails for cpusets much less spammy. Change-Id: Iad9c58db68ecd2c2445255bfe5564318064949a5 --- libcutils/sched_policy.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c index 4d69eac..2c29003 100644 --- a/libcutils/sched_policy.c +++ b/libcutils/sched_policy.c @@ -53,6 +53,8 @@ static inline SchedPolicy _policy(SchedPolicy p) #define TIMER_SLACK_FG 50000 static pthread_once_t the_once = PTHREAD_ONCE_INIT; +static pthread_once_t sched_once = PTHREAD_ONCE_INIT; +static pthread_once_t cpuset_once = PTHREAD_ONCE_INIT; static int __sys_supports_schedgroups = -1; static int __sys_supports_cpusets = -1; @@ -113,8 +115,13 @@ static void __initialize(void) { read(pfd, proc_name, sizeof(proc_name) - 1); close(pfd); } +} +static void __init_sched(void) { char* filename; + + pthread_once(&the_once, __initialize); + if (!access("/dev/cpuctl/tasks", F_OK)) { __sys_supports_schedgroups = 1; @@ -142,6 +149,12 @@ static void __initialize(void) { } else { __sys_supports_schedgroups = 0; } +} + +static void __init_cpuset(void) { + char *filename; + + pthread_once(&the_once, __initialize); #ifdef USE_CPUSETS if (!access("/dev/cpuset/tasks", F_OK)) { @@ -262,7 +275,8 @@ int get_sched_policy(int tid, SchedPolicy *policy) if (tid == 0) { tid = gettid(); } - pthread_once(&the_once, __initialize); + + pthread_once(&sched_once, __init_sched); if (__sys_supports_schedgroups) { char grpBuf[32]; @@ -302,7 +316,7 @@ int set_cpuset_policy(int tid, SchedPolicy policy) tid = gettid(); } - pthread_once(&the_once, __initialize); + pthread_once(&cpuset_once, __init_cpuset); if (!__sys_supports_cpusets) return set_sched_policy(tid, policy); @@ -342,7 +356,8 @@ int set_sched_policy(int tid, SchedPolicy policy) tid = gettid(); } policy = _policy(policy); - pthread_once(&the_once, __initialize); + + pthread_once(&sched_once, __init_sched); #if POLICY_DEBUG char statfile[64]; -- cgit v1.1 From 26bc3e918e79909fed67ddca66045b9faf888c84 Mon Sep 17 00:00:00 2001 From: Pat Erley Date: Tue, 22 Mar 2016 15:58:47 -0700 Subject: sched_policy: split add_tid_to_cgroup add_tid_to_cgroup was also being used to add threads to cpusets. Split this into a generic write_tid_to_fd, and wrap it for cpusets and cgroups. This lets errors align with what the actual failure is. Change-Id: I2c5c97117428a33b6a328f73741d3516d4141f78 --- libcutils/sched_policy.c | 49 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c index 2c29003..aa4f39d 100644 --- a/libcutils/sched_policy.c +++ b/libcutils/sched_policy.c @@ -69,15 +69,8 @@ static int system_bg_cpuset_fd = -1; static int bg_cpuset_fd = -1; static int fg_cpuset_fd = -1; -/* Add tid to the scheduling group defined by the policy */ -static int add_tid_to_cgroup(int tid, int fd) +static int write_tid_to_fd(int tid, int fd) { - if (fd < 0) { - SLOGE("%s add_tid_to_cgroup failed; fd=%d\n", proc_name, fd); - errno = EINVAL; - return -1; - } - // specialized itoa -- works for tid > 0 char text[22]; char *end = text + sizeof(text) - 1; @@ -95,8 +88,42 @@ static int add_tid_to_cgroup(int tid, int fd) */ if (errno == ESRCH) return 0; - SLOGW("%s add_tid_to_cgroup failed to write '%s' (%s); fd=%d\n", - proc_name, ptr, strerror(errno), fd); + return -1; + } + + return 0; +} + +/* Add tid to the scheduling group defined by the policy */ +static int add_tid_to_cgroup(int tid, int fd) +{ + if (fd < 0) { + SLOGE("%s add_tid_to_cgroup failed; fd=%d\n", proc_name, fd); + errno = EINVAL; + return -1; + } + + if (write_tid_to_fd(tid, fd) != 0) { + SLOGW("%s add_tid_to_cgroup failed to write '%d' (%s); fd=%d\n", + proc_name, tid, strerror(errno), fd); + errno = EINVAL; + return -1; + } + + return 0; +} + +static int add_tid_to_cpuset(int tid, int fd) +{ + if (fd < 0) { + SLOGE("%s add_tid_to_cpuset failed; fd=%d\n", proc_name, fd); + errno = EINVAL; + return -1; + } + + if (write_tid_to_fd(tid, fd) != 0) { + SLOGW("%s add_tid_to_cpuset failed to write '%d' (%s); fd=%d\n", + proc_name, tid, strerror(errno), fd); errno = EINVAL; return -1; } @@ -341,7 +368,7 @@ int set_cpuset_policy(int tid, SchedPolicy policy) break; } - if (add_tid_to_cgroup(tid, fd) != 0) { + if (add_tid_to_cpuset(tid, fd) != 0) { if (errno != ESRCH && errno != ENOENT) return -errno; } -- cgit v1.1 From ad54cfed4516292654c997910839153264ae00a0 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Wed, 23 Mar 2016 11:42:53 -0700 Subject: Don't demangle symbol names. Bug: http://b/27299236 Change-Id: I26ef47f80d4d6048a316ba51e83365ff65d70439 --- libbacktrace/Backtrace.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp index 97f0ef4..42769ed 100644 --- a/libbacktrace/Backtrace.cpp +++ b/libbacktrace/Backtrace.cpp @@ -54,24 +54,8 @@ Backtrace::~Backtrace() { } } -extern "C" char* __cxa_demangle(const char* mangled, char* buf, size_t* len, - int* status); - std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) { std::string func_name = GetFunctionNameRaw(pc, offset); - if (!func_name.empty()) { -#if defined(__APPLE__) - // Mac OS' __cxa_demangle demangles "f" as "float"; last tested on 10.7. - if (func_name[0] != '_') { - return func_name; - } -#endif - char* name = __cxa_demangle(func_name.c_str(), 0, 0, 0); - if (name) { - func_name = name; - free(name); - } - } return func_name; } -- cgit v1.1 From 40a38897b450093b61719015d8f8b6fa80f31595 Mon Sep 17 00:00:00 2001 From: Scott Mertz Date: Wed, 30 Mar 2016 10:27:31 -0700 Subject: sched_policy: zero proc_name buffer before populating The process name will be read into the buffer containing the proc name filepath. We need to reinitialize the buffer before reading into it. Change-Id: I67710819c895d3f9e2b0d486ab8a11f29f8318e8 --- libcutils/sched_policy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c index aa4f39d..b302bef 100644 --- a/libcutils/sched_policy.c +++ b/libcutils/sched_policy.c @@ -138,6 +138,7 @@ static void __initialize(void) { sprintf(proc_name, "/proc/%d/cmdline", ptid); pfd = open(proc_name, O_RDONLY); + memset(proc_name, 0, sizeof(proc_name)); if (pfd > 0) { read(pfd, proc_name, sizeof(proc_name) - 1); close(pfd); -- cgit v1.1 From 02ee37333288a2d628b358f22aea6e330e7cb8b8 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Wed, 16 Mar 2016 19:51:18 +0000 Subject: liblog: Add xlog symbols on MTK hardware Change-Id: I1c4bfb228ee261ae4d15e223b4605e39205b5b54 --- liblog/logd_write.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/liblog/logd_write.c b/liblog/logd_write.c index bdee28f..7f772af 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -513,3 +513,42 @@ int __android_log_bswrite(int32_t tag, const char *payload) return write_to_log(LOG_ID_EVENTS, vec, 4); } + +#ifdef MTK_HARDWARE +struct xlog_record { + const char *tag_str; + const char *fmt_str; + int prio; +}; + +void __attribute__((weak)) __xlog_buf_printf(__unused int bufid, const struct xlog_record *xlog_record, ...) { + va_list args; + va_start(args, xlog_record); +#if HAVE_LIBC_SYSTEM_PROPERTIES + int len = 0; + int do_xlog = 0; + char results[PROP_VALUE_MAX]; + + + // MobileLog + len = __system_property_get ("debug.MB.running", results); + if (len && atoi(results)) + do_xlog = 1; + + // ModemLog + len = __system_property_get ("debug.mdlogger.Running", results); + if (len && atoi(results)) + do_xlog = 1; + + // Manual + len = __system_property_get ("persist.debug.xlog.enable", results); + if (len && atoi(results)) + do_xlog = 1; + + if (do_xlog > 0) +#endif + __android_log_vprint(xlog_record->prio, xlog_record->tag_str, xlog_record->fmt_str, args); + + return; +} +#endif -- cgit v1.1 From 48506abb2d2c0ac670d6b85edf56c2cbb99c04df Mon Sep 17 00:00:00 2001 From: Diogo Ferreira Date: Wed, 16 Mar 2016 19:53:12 +0000 Subject: fs_mgr: Add an optional libfs_mgr shared library Change-Id: I79aec4549af3f71c8c08f8901f5edf9b5a6b8f62 --- fs_mgr/Android.mk | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk index d105b0b..43c64fb 100644 --- a/fs_mgr/Android.mk +++ b/fs_mgr/Android.mk @@ -23,6 +23,30 @@ endif include $(BUILD_STATIC_LIBRARY) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c fs_mgr_fstab.c +LOCAL_SRC_FILES += fs_mgr_format.c + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include \ + system/vold \ + system/extras/ext4_utils \ + external/openssl/include \ + system/core/logwrapper/include + +LOCAL_MODULE:= libfs_mgr +LOCAL_WHOLE_STATIC_LIBRARIES := liblogwrap libmincrypt libext4_utils_static libsquashfs_utils libsparse_static libext2_blkid libext2_uuid_static +LOCAL_STATIC_LIBRARIES := libcutils liblog libsparse_static libz libselinux +LOCAL_C_INCLUDES += system/extras/ext4_utils system/extras/squashfs_utils external/e2fsprogs/lib +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_CFLAGS := -Werror + +ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT))) +LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1 +endif + +include $(BUILD_SHARED_LIBRARY) + include $(CLEAR_VARS) -- cgit v1.1 From 0373c8deeb21f116354676116cf58e76a94d46a3 Mon Sep 17 00:00:00 2001 From: Gabriele M Date: Mon, 11 Apr 2016 12:35:40 -0700 Subject: Revert "Revert "init: Temporarily increase coldboot timeout to 5s"" 1 second might not be enough for some devices to complete the coldboot phase, so bring the timeout back to 5 seconds. This reverts commit c9e804ffd8d4108806eb8162fe7cf35f179b0596. Change-Id: If10cd4bb1ea66d1c98cdd16f5bfbdae7a04b52e8 --- init/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init/init.cpp b/init/init.cpp index 402331b..58d7d34 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -642,7 +642,7 @@ static int wait_for_coldboot_done_action(int nargs, char **args) { // Any longer than 1s is an unreasonable length of time to delay booting. // If you're hitting this timeout, check that you didn't make your // sepolicy regular expressions too expensive (http://b/19899875). - if (wait_for_file(COLDBOOT_DONE, 1)) { + if (wait_for_file(COLDBOOT_DONE, 5)) { ERROR("Timed out waiting for %s\n", COLDBOOT_DONE); } -- cgit v1.1 From 05a3648f9529cffecb24f939768868380de307d9 Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Thu, 14 Apr 2016 16:53:23 -0700 Subject: healthd: Rename default QCOM libhealthd library * Avoid possible module name conflicts Change-Id: I4a804a4d1e7266e8918b5a5b50adaffe219ff226 --- healthd/Android.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/healthd/Android.mk b/healthd/Android.mk index d1e005e..5345338 100644 --- a/healthd/Android.mk +++ b/healthd/Android.mk @@ -10,7 +10,7 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_SRC_FILES := healthd_board_msm.cpp -LOCAL_MODULE := libhealthd.msm +LOCAL_MODULE := libhealthd.qcom LOCAL_CFLAGS := -Werror include $(BUILD_STATIC_LIBRARY) @@ -62,7 +62,7 @@ endif LOCAL_HAL_STATIC_LIBRARIES := libhealthd ifeq ($(BOARD_USES_QCOM_HARDWARE),true) -BOARD_HAL_STATIC_LIBRARIES ?= libhealthd.msm +BOARD_HAL_STATIC_LIBRARIES ?= libhealthd.qcom endif # Symlink /charger to /sbin/healthd -- cgit v1.1 From 74f658f70599c283a5dd559343756565d562bf22 Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Thu, 14 Apr 2016 16:49:56 -0700 Subject: healthd: Allow devices to opt-out of enabling charger LED * Not all devices will want to enable this, and it may also cause symbol conflicts with static HAL libraries. Change-Id: I0a2a082f9bf84b6ecfecf3de88c6d494d5e2cf44 --- healthd/Android.mk | 4 ++++ healthd/healthd_mode_charger.cpp | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/healthd/Android.mk b/healthd/Android.mk index 5345338..7db4ad5 100644 --- a/healthd/Android.mk +++ b/healthd/Android.mk @@ -51,6 +51,10 @@ ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true) LOCAL_CFLAGS += -DCHARGER_ENABLE_SUSPEND endif +ifeq ($(strip $(BOARD_NO_CHARGER_LED)),true) +LOCAL_CFLAGS += -DNO_CHARGER_LED +endif + LOCAL_C_INCLUDES := bootable/recovery LOCAL_STATIC_LIBRARIES := libbatteryservice libbinder libminui libpng libz libutils libstdc++ libcutils liblog libm libc diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp index eb93d6a..5dd666d 100644 --- a/healthd/healthd_mode_charger.cpp +++ b/healthd/healthd_mode_charger.cpp @@ -183,6 +183,7 @@ enum { BLUE_LED = 0x01 << 2, }; +#ifdef NO_CHARGER_LED struct led_ctl { int color; const char *path; @@ -203,6 +204,7 @@ struct soc_led_color_mapping soc_leds[3] = { {90, RED_LED | GREEN_LED}, {100, GREEN_LED}, }; +#endif static struct charger charger_state; static struct healthd_config *healthd_config; @@ -211,6 +213,7 @@ static int char_width; static int char_height; static bool minui_inited; +#ifdef NO_CHARGER_LED static int set_tricolor_led(int on, int color) { int fd, i; @@ -257,6 +260,7 @@ static int set_battery_soc_leds(int soc) return 0; } +#endif /* current time in milliseconds */ static int64_t curr_time_ms(void) @@ -667,14 +671,17 @@ static void handle_input_state(struct charger *charger, int64_t now) static void handle_power_supply_state(struct charger *charger, int64_t now) { +#ifndef NO_CHARGER_LED static int old_soc = 0; int soc = 0; +#endif if (!charger->have_battery_state) return; healthd_board_mode_charger_battery_update(batt_prop); +#ifndef NO_CHARGER_LED if (batt_prop && batt_prop->batteryLevel >= 0) { soc = batt_prop->batteryLevel; } @@ -683,6 +690,7 @@ static void handle_power_supply_state(struct charger *charger, int64_t now) old_soc = soc; set_battery_soc_leds(soc); } +#endif if (!charger->charger_connected) { -- cgit v1.1 From f5eb7307401b7b8e1f05c509adb64970997ee1aa Mon Sep 17 00:00:00 2001 From: "Christopher R. Palmer" Date: Fri, 15 Apr 2016 19:44:38 -0400 Subject: healthd: Fix NO_CHARGER_LED Change-Id: Iaae43e2a236318011b7aefb59250c19dd954521e --- healthd/healthd_mode_charger.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp index 5dd666d..d6c31cf 100644 --- a/healthd/healthd_mode_charger.cpp +++ b/healthd/healthd_mode_charger.cpp @@ -183,7 +183,7 @@ enum { BLUE_LED = 0x01 << 2, }; -#ifdef NO_CHARGER_LED +#ifndef NO_CHARGER_LED struct led_ctl { int color; const char *path; @@ -213,7 +213,7 @@ static int char_width; static int char_height; static bool minui_inited; -#ifdef NO_CHARGER_LED +#ifndef NO_CHARGER_LED static int set_tricolor_led(int on, int color) { int fd, i; -- cgit v1.1 From 408bb87b6951267a96a25830da7a7621266858dd Mon Sep 17 00:00:00 2001 From: sndnvaps Date: Thu, 21 Apr 2016 19:44:20 +0800 Subject: fastboot: add ZTE to the list of known vendors Change-Id: I741d0e4068d948fb7b4036d7f02e68b896863795 Signed-off-by: sndnvaps --- fastboot/fastboot.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 5112c15..a3fa115 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -207,7 +207,8 @@ int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial) (info->dev_vendor != 0x0421) && // Nokia (info->dev_vendor != 0x1ebf) && // Coolpad (info->dev_vendor != 0x2b4c) && // Zuk - (info->dev_vendor != 0x2a96)) // MMX + (info->dev_vendor != 0x2a96) && // MMX + (info->dev_vendor != 0x19d2)) // ZTE return -1; if(info->ifc_class != 0xff) return -1; if(info->ifc_subclass != 0x42) return -1; -- cgit v1.1 From 864e2e22fcd0cba3f5e67680ccabd0302dfda45d Mon Sep 17 00:00:00 2001 From: Daniel Rosenberg Date: Tue, 12 Apr 2016 16:30:28 -0700 Subject: Fix overflow in path building An incorrect size was causing an unsigned value to wrap, causing it to write past the end of the buffer. Bug: 28085658 Change-Id: Ie9625c729cca024d514ba2880ff97209d435a165 --- sdcard/sdcard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index 06452aa..123fce6 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -337,7 +337,7 @@ static ssize_t get_node_path_locked(struct node* node, char* buf, size_t bufsize ssize_t pathlen = 0; if (node->parent && node->graft_path == NULL) { - pathlen = get_node_path_locked(node->parent, buf, bufsize - namelen - 2); + pathlen = get_node_path_locked(node->parent, buf, bufsize - namelen - 1); if (pathlen < 0) { return -1; } -- cgit v1.1 From acd185636cbe809bea218aec834d215162b73681 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Tue, 26 Apr 2016 15:01:35 -0700 Subject: fastboot: Add Nextbit's USB vendor id Change-Id: I400611a6f256cd6c2a721b9ad8496fd60d257f3f --- fastboot/fastboot.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index a3fa115..6a2f10d 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -208,7 +208,8 @@ int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial) (info->dev_vendor != 0x1ebf) && // Coolpad (info->dev_vendor != 0x2b4c) && // Zuk (info->dev_vendor != 0x2a96) && // MMX - (info->dev_vendor != 0x19d2)) // ZTE + (info->dev_vendor != 0x19d2) && // ZTE + (info->dev_vendor != 0x2c3f)) // Nextbit return -1; if(info->ifc_class != 0xff) return -1; if(info->ifc_subclass != 0x42) return -1; -- cgit v1.1 From bbc34f83fcb8511c2f2eb575882b0670793342a8 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Sat, 30 Apr 2016 14:09:48 -0700 Subject: rootdir: Remove cpufreq mode settings * AFAIK we no longer should have anything which depends on system server or settings writing to the cpufreq controls. Since new devices have their cpufreq config nodes nested per-cpu, this configuration is no longer valid. It also depends on sketchy kernel patches which only work when the moon is in the correct phase. Additionally, I see a lot of random logspam when devices are hotplugged. * If a device needs this functionality, a better way to do it is via a userspace daemon which is dedicated to the task since it can poll() on the various states and get notified in realtime. Change-Id: Ib526663d760d6cb758e13f1fa29e7d6229de3daa --- rootdir/ueventd.rc | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc index f82d899..67eaabc 100644 --- a/rootdir/ueventd.rc +++ b/rootdir/ueventd.rc @@ -99,42 +99,3 @@ subsystem adf # DVB API device nodes /dev/dvb* 0660 root system -# Governor permissions -/sys/devices/system/cpu/cpu* cpufreq/scaling_governor 0664 system system - -/sys/devices/system/cpu/cpufreq ondemand/boostfreq 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/boostpulse 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/boosttime 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/down_differential 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/down_differential_multi_core 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/ignore_nice_load 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/input_boost 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/io_is_busy 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/optimal_freq 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/powersave_bias 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/sampling_down_factor 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/sampling_rate 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/sampling_rate_min 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/sync_freq 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/up_threshold 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/up_threshold_any_cpu_load 0664 system system -/sys/devices/system/cpu/cpufreq ondemand/up_threshold_multi_core 0664 system system - -/sys/devices/system/cpu/cpufreq interactive/above_hispeed_delay 0664 system system -/sys/devices/system/cpu/cpufreq interactive/align_windows 0664 system system -/sys/devices/system/cpu/cpufreq interactive/boost 0664 system system -/sys/devices/system/cpu/cpufreq interactive/boostpulse 0664 system system -/sys/devices/system/cpu/cpufreq interactive/boostpulse_duration 0664 system system -/sys/devices/system/cpu/cpufreq interactive/go_hispeed_load 0664 system system -/sys/devices/system/cpu/cpufreq interactive/hispeed_freq 0664 system system -/sys/devices/system/cpu/cpufreq interactive/io_is_busy 0664 system system -/sys/devices/system/cpu/cpufreq interactive/max_freq_hysteresis 0664 system system -/sys/devices/system/cpu/cpufreq interactive/min_sample_rate 0664 system system -/sys/devices/system/cpu/cpufreq interactive/min_sample_time 0664 system system -/sys/devices/system/cpu/cpufreq interactive/sampling_down_factor 0664 system system -/sys/devices/system/cpu/cpufreq interactive/sync_freq 0664 system system -/sys/devices/system/cpu/cpufreq interactive/target_loads 0664 system system -/sys/devices/system/cpu/cpufreq interactive/timer_rate 0664 system system -/sys/devices/system/cpu/cpufreq interactive/timer_slack 0664 system system -/sys/devices/system/cpu/cpufreq interactive/up_threshold_any_cpu_freq 0664 system system -/sys/devices/system/cpu/cpufreq interactive/up_threshold_any_cpu_load 0664 system system -- cgit v1.1 From 0d6557ec30fc8c3e06badcae93efff1ee5f6b6a1 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Thu, 24 Dec 2015 21:21:04 -0800 Subject: Revert "Revert "fs_mgr: let fsck.f2fs actually attempt a fix"" This reverts commit 33ecd3756347ef2663e500949ab4b33392086fbc. Change-Id: Ifa430fca72eee3e6f49d5a259c1058f5c3829960 --- fs_mgr/fs_mgr.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index c80e531..6e20560 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -161,12 +161,12 @@ static void check_fs(char *blk_device, char *fs_type, char *target) } } } else if (!strcmp(fs_type, "f2fs")) { - char *f2fs_fsck_argv[] = { - F2FS_FSCK_BIN, - "-a", - blk_device - }; - INFO("Running %s on %s\n", F2FS_FSCK_BIN, blk_device); + char *f2fs_fsck_argv[] = { + F2FS_FSCK_BIN, + "-f", + blk_device + }; + INFO("Running %s -f %s\n", F2FS_FSCK_BIN, blk_device); ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, true, LOG_KLOG | LOG_FILE, -- cgit v1.1 From 784c22c8388e50db243ac4ca3871747cd3eefadc Mon Sep 17 00:00:00 2001 From: Yusuke Sato Date: Wed, 8 Jul 2015 14:57:07 -0700 Subject: Use fsck.f2fs -a instead of -f for faster boot and run fsck with -f on clean shutdown instead. With -f, fsck.f2fs always performs a full scan of the /data partition regardless of whether the partition is clean or not. The full scan takes more than 2 seconds on volantis-userdebug and delays the OS boot. With -a, the command does almost nothing when the partition is clean and finishes within 20-30ms on volantis-userdebug. When the partition has an error or its check point has CP_FSCK_FLAG (aka "need_fsck"), the command does exactly the same full scan as -f to fix it. Bug: 21853106 Change-Id: I126263caf34c0f5bb8f5e6794454d4e72526ce38 --- fs_mgr/fs_mgr.c | 4 +- include/cutils/android_reboot.h | 5 ++ init/builtins.cpp | 71 ++++++++++++++- libcutils/android_reboot.c | 187 +++++++++++++++++++++++++++++++++------- logwrapper/logwrap.c | 7 +- 5 files changed, 236 insertions(+), 38 deletions(-) diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c index 6e20560..e78b581 100644 --- a/fs_mgr/fs_mgr.c +++ b/fs_mgr/fs_mgr.c @@ -163,10 +163,10 @@ static void check_fs(char *blk_device, char *fs_type, char *target) } else if (!strcmp(fs_type, "f2fs")) { char *f2fs_fsck_argv[] = { F2FS_FSCK_BIN, - "-f", + "-a", blk_device }; - INFO("Running %s -f %s\n", F2FS_FSCK_BIN, blk_device); + INFO("Running %s -a %s\n", F2FS_FSCK_BIN, blk_device); ret = android_fork_execvp_ext(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, true, LOG_KLOG | LOG_FILE, diff --git a/include/cutils/android_reboot.h b/include/cutils/android_reboot.h index 85e1b7e..a3861a0 100644 --- a/include/cutils/android_reboot.h +++ b/include/cutils/android_reboot.h @@ -17,6 +17,8 @@ #ifndef __CUTILS_ANDROID_REBOOT_H__ #define __CUTILS_ANDROID_REBOOT_H__ +#include + __BEGIN_DECLS /* Commands */ @@ -28,6 +30,9 @@ __BEGIN_DECLS #define ANDROID_RB_PROPERTY "sys.powerctl" int android_reboot(int cmd, int flags, const char *arg); +int android_reboot_with_callback( + int cmd, int flags, const char *arg, + void (*cb_on_remount)(const struct mntent*)); __END_DECLS diff --git a/init/builtins.cpp b/init/builtins.cpp index b290ce3..d0dbecc 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -16,7 +16,9 @@ #include #include +#include #include +#include #include #include #include @@ -38,6 +40,7 @@ #include #include #include +#include #include #include "init.h" @@ -49,6 +52,8 @@ #include "log.h" #define chmod DO_NOT_USE_CHMOD_USE_FCHMODAT_SYMLINK_NOFOLLOW +#define UNMOUNT_CHECK_MS 5000 +#define UNMOUNT_CHECK_TIMES 10 int add_environment(const char *name, const char *value); @@ -109,6 +114,67 @@ static void service_start_if_not_disabled(struct service *svc) } } +static void unmount_and_fsck(const struct mntent *entry) +{ + if (strcmp(entry->mnt_type, "f2fs") && strcmp(entry->mnt_type, "ext4")) + return; + + /* First, lazily unmount the directory. This unmount request finishes when + * all processes that open a file or directory in |entry->mnt_dir| exit. + */ + TEMP_FAILURE_RETRY(umount2(entry->mnt_dir, MNT_DETACH)); + + /* Next, kill all processes except init, kthreadd, and kthreadd's + * children to finish the lazy unmount. Killing all processes here is okay + * because this callback function is only called right before reboot(). + * It might be cleaner to selectively kill processes that actually use + * |entry->mnt_dir| rather than killing all, probably by reusing a function + * like killProcessesWithOpenFiles() in vold/, but the selinux policy does + * not allow init to scan /proc/ files which the utility function + * heavily relies on. The policy does not allow the process to execute + * killall/pkill binaries either. Note that some processes might + * automatically restart after kill(), but that is not really a problem + * because |entry->mnt_dir| is no longer visible to such new processes. + */ + service_for_each(service_stop); + TEMP_FAILURE_RETRY(kill(-1, SIGKILL)); + + int count = 0; + while (count++ < UNMOUNT_CHECK_TIMES) { + int fd = TEMP_FAILURE_RETRY(open(entry->mnt_fsname, O_RDONLY | O_EXCL)); + if (fd >= 0) { + /* |entry->mnt_dir| has sucessfully been unmounted. */ + close(fd); + break; + } else if (errno == EBUSY) { + /* Some processes using |entry->mnt_dir| are still alive. Wait for a + * while then retry. + */ + TEMP_FAILURE_RETRY( + usleep(UNMOUNT_CHECK_MS * 1000 / UNMOUNT_CHECK_TIMES)); + continue; + } else { + /* Cannot open the device. Give up. */ + return; + } + } + + int st; + if (!strcmp(entry->mnt_type, "f2fs")) { + const char *f2fs_argv[] = { + "/system/bin/fsck.f2fs", "-f", entry->mnt_fsname, + }; + android_fork_execvp_ext(ARRAY_SIZE(f2fs_argv), (char **)f2fs_argv, + &st, true, LOG_KLOG, true, NULL); + } else if (!strcmp(entry->mnt_type, "ext4")) { + const char *ext4_argv[] = { + "/system/bin/e2fsck", "-f", "-y", entry->mnt_fsname, + }; + android_fork_execvp_ext(ARRAY_SIZE(ext4_argv), (char **)ext4_argv, + &st, true, LOG_KLOG, true, NULL); + } +} + int do_class_start(int nargs, char **args) { char prop[PROP_NAME_MAX]; @@ -577,6 +643,7 @@ int do_powerctl(int nargs, char **args) int len = 0; int cmd = 0; const char *reboot_target; + void (*callback_on_ro_remount)(const struct mntent*) = NULL; res = expand_props(command, args[1], sizeof(command)); if (res) { @@ -590,6 +657,7 @@ int do_powerctl(int nargs, char **args) } cmd = ANDROID_RB_POWEROFF; len = 8; + callback_on_ro_remount = unmount_and_fsck; } else if (strncmp(command, "reboot", 6) == 0) { cmd = ANDROID_RB_RESTART2; len = 6; @@ -614,7 +682,8 @@ int do_powerctl(int nargs, char **args) return -EINVAL; } - return android_reboot(cmd, 0, reboot_target); + return android_reboot_with_callback(cmd, 0, reboot_target, + callback_on_ro_remount); } int do_trigger(int nargs, char **args) diff --git a/libcutils/android_reboot.c b/libcutils/android_reboot.c index 6ae23c1..af7e189 100644 --- a/libcutils/android_reboot.c +++ b/libcutils/android_reboot.c @@ -14,43 +14,108 @@ * limitations under the License. */ -#include -#include -#include -#include -#include +#include #include #include +#include #include +#include #include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include -#define UNUSED __attribute__((unused)) +#define TAG "android_reboot" +#define READONLY_CHECK_MS 5000 +#define READONLY_CHECK_TIMES 50 -/* Check to see if /proc/mounts contains any writeable filesystems - * backed by a block device. - * Return true if none found, else return false. +typedef struct { + struct listnode list; + struct mntent entry; +} mntent_list; + +static bool has_mount_option(const char* opts, const char* opt_to_find) +{ + bool ret = false; + char* copy = NULL; + char* opt; + char* rem; + + while ((opt = strtok_r(copy ? NULL : (copy = strdup(opts)), ",", &rem))) { + if (!strcmp(opt, opt_to_find)) { + ret = true; + break; + } + } + + free(copy); + return ret; +} + +static bool is_block_device(const char* fsname) +{ + return !strncmp(fsname, "/dev/block", 10); +} + +/* Find all read+write block devices in /proc/mounts and add them to + * |rw_entries|. */ -static int remount_ro_done(void) +static void find_rw(struct listnode* rw_entries) { FILE* fp; struct mntent* mentry; - int found_rw_fs = 0; if ((fp = setmntent("/proc/mounts", "r")) == NULL) { - /* If we can't read /proc/mounts, just give up. */ - return 1; + KLOG_WARNING(TAG, "Failed to open /proc/mounts.\n"); + return; } while ((mentry = getmntent(fp)) != NULL) { - if (!strncmp(mentry->mnt_fsname, "/dev/block", 10) && strstr(mentry->mnt_opts, "rw,")) { - found_rw_fs = 1; - break; + if (is_block_device(mentry->mnt_fsname) && + has_mount_option(mentry->mnt_opts, "rw")) { + mntent_list* item = (mntent_list*)calloc(1, sizeof(mntent_list)); + item->entry = *mentry; + item->entry.mnt_fsname = strdup(mentry->mnt_fsname); + item->entry.mnt_dir = strdup(mentry->mnt_dir); + item->entry.mnt_type = strdup(mentry->mnt_type); + item->entry.mnt_opts = strdup(mentry->mnt_opts); + list_add_tail(rw_entries, &item->list); } } endmntent(fp); +} + +static void free_entries(struct listnode* entries) +{ + struct listnode* node; + struct listnode* n; + list_for_each_safe(node, n, entries) { + mntent_list* item = node_to_item(node, mntent_list, list); + free(item->entry.mnt_fsname); + free(item->entry.mnt_dir); + free(item->entry.mnt_type); + free(item->entry.mnt_opts); + free(item); + } +} - return !found_rw_fs; +static mntent_list* find_item(struct listnode* rw_entries, const char* fsname_to_find) +{ + struct listnode* node; + list_for_each(node, rw_entries) { + mntent_list* item = node_to_item(node, mntent_list, list); + if (!strcmp(item->entry.mnt_fsname, fsname_to_find)) { + return item; + } + } + return NULL; } /* Remounting filesystems read-only is difficult when there are files @@ -64,38 +129,92 @@ static int remount_ro_done(void) * repeatedly until there are no more writable filesystems mounted on * block devices. */ -static void remount_ro(void) +static void remount_ro(void (*cb_on_remount)(const struct mntent*)) { - int fd, cnt = 0; + int fd, cnt; + FILE* fp; + struct mntent* mentry; + struct listnode* node; + + list_declare(rw_entries); + list_declare(ro_entries); + + sync(); + find_rw(&rw_entries); /* Trigger the remount of the filesystems as read-only, * which also marks them clean. */ - fd = open("/proc/sysrq-trigger", O_WRONLY); + fd = TEMP_FAILURE_RETRY(open("/proc/sysrq-trigger", O_WRONLY)); if (fd < 0) { - return; + KLOG_WARNING(TAG, "Failed to open sysrq-trigger.\n"); + /* TODO: Try to remount each rw parition manually in readonly mode. + * This may succeed if no process is using the partition. + */ + goto out; + } + if (TEMP_FAILURE_RETRY(write(fd, "u", 1)) != 1) { + close(fd); + KLOG_WARNING(TAG, "Failed to write to sysrq-trigger.\n"); + /* TODO: The same. Manually remount the paritions. */ + goto out; } - write(fd, "u", 1); close(fd); - /* Now poll /proc/mounts till it's done */ - while (!remount_ro_done() && (cnt < 50)) { - usleep(100000); + cnt = 0; + while (cnt < READONLY_CHECK_TIMES) { + if ((fp = setmntent("/proc/mounts", "r")) == NULL) { + /* If we can't read /proc/mounts, just give up. */ + KLOG_WARNING(TAG, "Failed to open /proc/mounts.\n"); + goto out; + } + while ((mentry = getmntent(fp)) != NULL) { + if (!is_block_device(mentry->mnt_fsname) || + !has_mount_option(mentry->mnt_opts, "ro")) { + continue; + } + mntent_list* item = find_item(&rw_entries, mentry->mnt_fsname); + if (item) { + /* |item| has now been ro remounted. */ + list_remove(&item->list); + list_add_tail(&ro_entries, &item->list); + } + } + endmntent(fp); + if (list_empty(&rw_entries)) { + /* All rw block devices are now readonly. */ + break; + } + TEMP_FAILURE_RETRY( + usleep(READONLY_CHECK_MS * 1000 / READONLY_CHECK_TIMES)); cnt++; } - return; -} + list_for_each(node, &rw_entries) { + mntent_list* item = node_to_item(node, mntent_list, list); + KLOG_WARNING(TAG, "Failed to remount %s in readonly mode.\n", + item->entry.mnt_fsname); + } + + if (cb_on_remount) { + list_for_each(node, &ro_entries) { + mntent_list* item = node_to_item(node, mntent_list, list); + cb_on_remount(&item->entry); + } + } +out: + free_entries(&rw_entries); + free_entries(&ro_entries); +} -int android_reboot(int cmd, int flags UNUSED, const char *arg) +int android_reboot_with_callback( + int cmd, int flags __unused, const char *arg, + void (*cb_on_remount)(const struct mntent*)) { int ret; - - sync(); - remount_ro(); - + remount_ro(cb_on_remount); switch (cmd) { case ANDROID_RB_RESTART: ret = reboot(RB_AUTOBOOT); @@ -117,3 +236,7 @@ int android_reboot(int cmd, int flags UNUSED, const char *arg) return ret; } +int android_reboot(int cmd, int flags, const char *arg) +{ + return android_reboot_with_callback(cmd, flags, arg, NULL); +} diff --git a/logwrapper/logwrap.c b/logwrapper/logwrap.c index 83576fb..44455d1 100644 --- a/logwrapper/logwrap.c +++ b/logwrapper/logwrap.c @@ -355,7 +355,8 @@ static int parent(const char *tag, int parent_read, pid_t pid, } if (poll_fds[0].revents & POLLIN) { - sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b); + sz = TEMP_FAILURE_RETRY( + read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)); sz += b; // Log one line at a time @@ -490,7 +491,7 @@ int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int } /* Use ptty instead of socketpair so that STDOUT is not buffered */ - parent_ptty = open("/dev/ptmx", O_RDWR); + parent_ptty = TEMP_FAILURE_RETRY(open("/dev/ptmx", O_RDWR)); if (parent_ptty < 0) { ERROR("Cannot create parent ptty\n"); rc = -1; @@ -505,7 +506,7 @@ int android_fork_execvp_ext(int argc, char* argv[], int *status, bool ignore_int goto err_ptty; } - child_ptty = open(child_devname, O_RDWR); + child_ptty = TEMP_FAILURE_RETRY(open(child_devname, O_RDWR)); if (child_ptty < 0) { ERROR("Cannot open child_ptty\n"); rc = -1; -- cgit v1.1 From 8284bce0e87d18e0779b12b63797515406c2d553 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Mon, 16 May 2016 00:42:37 -0700 Subject: rootdir: Put bootanimation service in system-background group * This keeps it from hogging the big cores and heating up the device. Change-Id: I0ba6abef537ad65978dd77ec706f6e3777cac804 --- rootdir/init.rc | 1 + 1 file changed, 1 insertion(+) diff --git a/rootdir/init.rc b/rootdir/init.rc index 78adacc..ec5a2f6 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -693,6 +693,7 @@ service bootanim /system/bin/bootanimation group graphics audio disabled oneshot + writepid /dev/cpuset/system-background/tasks service gatekeeperd /system/bin/gatekeeperd /data/misc/gatekeeper class late_start -- cgit v1.1 From 516d6913dc5acd695581b3999fab0b5192353022 Mon Sep 17 00:00:00 2001 From: "Christopher R. Palmer" Date: Mon, 16 May 2016 05:21:28 -0400 Subject: init: Allow devices to opt-out of fsck'ing on power off On the zenfone2 the fsck code patch kills alls processes. This causes watchdogd to get killed which then causes the system to emergency reboot instead of powering off. Change-Id: Ibcc74825df6571caa70e2dde7766a72b7749581b --- init/Android.mk | 4 ++++ init/builtins.cpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/init/Android.mk b/init/Android.mk index aa32236..85dfbfc 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -68,6 +68,10 @@ ifneq ($(TARGET_IGNORE_RO_BOOT_REVISION),) LOCAL_CFLAGS += -DIGNORE_RO_BOOT_REVISION endif +ifneq ($(TARGET_INIT_UMOUNT_AND_FSCK_IS_UNSAFE),) +LOCAL_CFLAGS += -DUMOUNT_AND_FSCK_IS_UNSAFE +endif + LOCAL_MODULE:= init LOCAL_C_INCLUDES += \ external/zlib \ diff --git a/init/builtins.cpp b/init/builtins.cpp index d0dbecc..1681d17 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -116,6 +116,7 @@ static void service_start_if_not_disabled(struct service *svc) static void unmount_and_fsck(const struct mntent *entry) { +#ifndef UMOUNT_AND_FSCK_IS_UNSAFE if (strcmp(entry->mnt_type, "f2fs") && strcmp(entry->mnt_type, "ext4")) return; @@ -173,6 +174,7 @@ static void unmount_and_fsck(const struct mntent *entry) android_fork_execvp_ext(ARRAY_SIZE(ext4_argv), (char **)ext4_argv, &st, true, LOG_KLOG, true, NULL); } +#endif } int do_class_start(int nargs, char **args) -- cgit v1.1 From 2a0279924b973308cb2a95cc92ab62b09b54cb3f Mon Sep 17 00:00:00 2001 From: Scott Mertz Date: Wed, 25 May 2016 15:47:42 -0700 Subject: debuggerd: add CM version to tombstones Change-Id: I7822a2e133a2f326ad2d8da8f79b0064344d59bf --- debuggerd/tombstone.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp index aeffc66..0c9fc49 100644 --- a/debuggerd/tombstone.cpp +++ b/debuggerd/tombstone.cpp @@ -167,10 +167,13 @@ static const char* get_sigcode(int signo, int code) { static void dump_header_info(log_t* log) { char fingerprint[PROPERTY_VALUE_MAX]; char revision[PROPERTY_VALUE_MAX]; + char cm_version[PROPERTY_VALUE_MAX]; + property_get("ro.cm.version", cm_version, "unknown"); property_get("ro.build.fingerprint", fingerprint, "unknown"); property_get("ro.revision", revision, "unknown"); + _LOG(log, logtype::HEADER, "CM Version: '%s'\n", cm_version); _LOG(log, logtype::HEADER, "Build fingerprint: '%s'\n", fingerprint); _LOG(log, logtype::HEADER, "Revision: '%s'\n", revision); _LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING); -- cgit v1.1 From ae18eb014609948a40e22192b87b10efc680daa7 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Tue, 19 Apr 2016 14:57:09 -0700 Subject: Fix scanf %s in lsof. Bug: http://b/28175237 Change-Id: Ief0ba299b09693ad9afc0e3d17a8f664c2fbb8c2 --- toolbox/lsof.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/toolbox/lsof.c b/toolbox/lsof.c index 982f5aa..da78ddd 100644 --- a/toolbox/lsof.c +++ b/toolbox/lsof.c @@ -100,10 +100,11 @@ out: static void print_maps(struct pid_info_t* info) { FILE *maps; + size_t offset; char device[10]; long int inode; - char file[PATH_MAX]; + char file[1024]; strlcat(info->path, "maps", sizeof(info->path)); @@ -111,8 +112,8 @@ static void print_maps(struct pid_info_t* info) if (!maps) goto out; - while (fscanf(maps, "%*x-%*x %*s %zx %s %ld %s\n", &offset, device, &inode, - file) == 4) { + while (fscanf(maps, "%*x-%*x %*s %zx %5s %ld %1023s\n", + &offset, device, &inode, file) == 4) { // We don't care about non-file maps if (inode == 0 || !strcmp(device, "00:00")) continue; -- cgit v1.1 From 671d62d73c9c643159107ca77721b6540ef79eea Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Fri, 4 Sep 2015 16:23:01 -0400 Subject: add a property for controlling perf_event_paranoid This adds a system property for controlling unprivileged access to perf_event_paranoid. It depends on adding kernel support for perf_event_paranoid=3 based on grsecurity's PERF_HARDEN feature to completely disable unprivileged access to perf. A minimal port of this feature is used in the vanilla Debian kernel by default. It hides the non-hardened value as an implementation detail, since while it is currently 1, it will probably become 2 in the future. (Cherry picked from commit 2b22a66382db8a2fdf5ed7a685085a6d7d67cf12) Bug: 29054680 Change-Id: I6e3ae3cf18d8c76df94f879c34fb6fde519b89a9 --- rootdir/init.rc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rootdir/init.rc b/rootdir/init.rc index 317207c..900e356 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -544,6 +544,11 @@ on property:sys.sysctl.extra_free_kbytes=* on property:sys.sysctl.tcp_def_init_rwnd=* write /proc/sys/net/ipv4/tcp_default_init_rwnd ${sys.sysctl.tcp_def_init_rwnd} +on property:security.perf_harden=0 + write /proc/sys/kernel/perf_event_paranoid 1 + +on property:security.perf_harden=1 + write /proc/sys/kernel/perf_event_paranoid 3 ## Daemon processes to be run by init. ## -- cgit v1.1 From 00c551e284b61d458f05759a489d615933e3667b Mon Sep 17 00:00:00 2001 From: sanketk Date: Fri, 12 Jun 2015 16:38:56 +0800 Subject: Don't use global variable in libnetutils. In netd, both CommandListener and NetlinkHandler thread will use libnetutils' function. Original implementation will use a global file descriptor in mutiple functions. It will cause problems when these functions are invoked from different thread. This change will make NetlinkHandler thread use local file descriptor instead of global one. CRs-fixed: 853158 Change-Id: I66458e99e48197e7a56cbb212344423290db12bd --- libnetutils/ifc_utils.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c index 3bd59c7..0bd7628 100644 --- a/libnetutils/ifc_utils.c +++ b/libnetutils/ifc_utils.c @@ -597,23 +597,26 @@ int ifc_disable(const char *ifname) int ifc_reset_connections(const char *ifname, const int reset_mask) { #ifdef HAVE_ANDROID_OS - int result, success; + int result = 0, success; in_addr_t myaddr = 0; struct ifreq ifr; struct in6_ifreq ifr6; + int ctl_sock = -1; if (reset_mask & RESET_IPV4_ADDRESSES) { /* IPv4. Clear connections on the IP address. */ - ifc_init(); - if (!(reset_mask & RESET_IGNORE_INTERFACE_ADDRESS)) { - ifc_get_info(ifname, &myaddr, NULL, NULL); + ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (ctl_sock >= 0) { + if (!(reset_mask & RESET_IGNORE_INTERFACE_ADDRESS)) { + ifc_get_info(ifname, &myaddr, NULL, NULL); + } + ifc_init_ifr(ifname, &ifr); + init_sockaddr_in(&ifr.ifr_addr, myaddr); + result = ioctl(ctl_sock, SIOCKILLADDR, &ifr); + close(ctl_sock); + } else { + result = -1; } - ifc_init_ifr(ifname, &ifr); - init_sockaddr_in(&ifr.ifr_addr, myaddr); - result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); - ifc_close(); - } else { - result = 0; } if (reset_mask & RESET_IPV6_ADDRESSES) { @@ -623,14 +626,18 @@ int ifc_reset_connections(const char *ifname, const int reset_mask) * So we clear all unused IPv6 connections on the device by specifying an * empty IPv6 address. */ - ifc_init6(); + ctl_sock = socket(AF_INET6, SOCK_DGRAM, 0); // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets. memset(&ifr6, 0, sizeof(ifr6)); - success = ioctl(ifc_ctl_sock6, SIOCKILLADDR, &ifr6); - if (result == 0) { - result = success; + if (ctl_sock >= 0) { + success = ioctl(ctl_sock, SIOCKILLADDR, &ifr6); + if (result == 0) { + result = success; + } + close(ctl_sock); + } else { + result = -1; } - ifc_close6(); } return result; -- cgit v1.1 From d68de66ea754d8b49815d20b10e69d162ca0a7e1 Mon Sep 17 00:00:00 2001 From: Maunik Shah Date: Tue, 22 Sep 2015 16:15:39 +0530 Subject: Copy the ETB dumps and maps file to /data/core On enabling the persist.debug.trace, ETB maps and dumps will be copied to /data/core only for the first crash. Change-Id: I521ee02e30ce1b4ebaca2c6b398c828286a5115d --- debuggerd/debuggerd.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 984b931..4e1f53e 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -1,5 +1,6 @@ /* * Copyright 2006, The Android Open Source Project + * Copyright (c) 2015, The Linux Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -138,6 +139,84 @@ static int get_process_info(pid_t tid, pid_t* out_pid, uid_t* out_uid, uid_t* ou return fields == 7 ? 0 : -1; } +static bool copy_file(const char* src, char* dest) +{ + #define BUF_SIZE 64 + ssize_t bytes; + int source_fh, dest_fh; + int total_size = 0; + char buffer[BUF_SIZE]; + + if ((source_fh = open(src, O_RDONLY, O_NOFOLLOW)) == -1) { + ALOGE("Unable to open source file %s\n", src); + } else { + if((dest_fh = open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0640)) == -1) { + ALOGE("Unable to write destination file %s\n", dest); + } else { + while ((bytes = read(source_fh, buffer, BUF_SIZE)) > 0) { + if (write(dest_fh, buffer, bytes) < 0) { + ALOGE("Write failed for destination file %s. Copied %d bytes\n", + dest, total_size); + break; + } + total_size += bytes; + } + ALOGI("Copied %s to %s - size: %d\n", src, dest, total_size); + fsync(dest_fh); + close(dest_fh); + } + close(source_fh); + if (total_size > 0) { + return true; + } + } + return false; +} + +static void collect_etb_map(int cr_pid) +{ + struct stat s; + char src_buf[64]; + char dest_buf[64]; + + snprintf(dest_buf, sizeof dest_buf, "/data/core/etb.%d", cr_pid); + if (!copy_file("/dev/coresight-tmc-etf", dest_buf)) { + ALOGE("Unable to copy ETB buffer file /dev/coresight-tmc-etf\n"); + } else { + memset(src_buf, 0, sizeof(src_buf)); + snprintf(src_buf, sizeof(src_buf), "/proc/%d/maps", cr_pid); + if(stat(src_buf, &s)) { + ALOGE("map file /proc/%d/maps does not exist for pid %d\n", + cr_pid, cr_pid); + } else { + snprintf(dest_buf, sizeof dest_buf, "/data/core/maps.%d", cr_pid); + if (!copy_file(src_buf, dest_buf)) { + ALOGE("Unable to copy map file /proc/%d/maps", cr_pid); + } + } + } +} + +static void enable_etb_trace(struct ucred cr) { + char value[PROPERTY_VALUE_MAX]; + property_get("persist.debug.trace", value, ""); + if ((strcmp(value,"1") == 0)) { + /* Allow ETB collection only once; Note: in future this behavior can be changed + * To allow this, use a property to indicate whether the ETB has been collected */ + property_get("debug.etb.collected", value, ""); + if(strcmp(value,"1")) { + ALOGI("Collecting ETB dumps (from pid=%d uid=%d)\n", + cr.pid, cr.uid); + property_set("debug.etb.collected", "1"); + collect_etb_map(cr.pid); + } + else { + ALOGI("ETB already collected once, skipping (from pid=%d uid=%d)\n", + cr.pid, cr.uid); + } + } +} + static int selinux_enabled; /* @@ -231,6 +310,7 @@ static int read_request(int fd, debugger_request_t* out_request) { // Ensure that the tid reported by the crashing process is valid. char buf[64]; struct stat s; + enable_etb_trace(cr); snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid); if (stat(buf, &s)) { ALOGE("tid %d does not exist in pid %d. ignoring debug request\n", -- cgit v1.1 From dd0866421e41fb2a38e22c8a94ee93e199599ec1 Mon Sep 17 00:00:00 2001 From: Benson Leung Date: Wed, 7 Oct 2015 16:12:04 -0700 Subject: healthd: Support new PD and USB Type C types See the new types added here : https://chromium-review.googlesource.com/304660 Add support for these. Signed-off-by: Benson Leung Change-Id: I12c51e0611692a763a7f1cda57c77ad83d7aa7ea --- healthd/BatteryMonitor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp index 67a8ad0..dfa59b8 100644 --- a/healthd/BatteryMonitor.cpp +++ b/healthd/BatteryMonitor.cpp @@ -140,6 +140,9 @@ BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String { "USB_ACA", ANDROID_POWER_SUPPLY_TYPE_AC }, { "USB_HVDCP", ANDROID_POWER_SUPPLY_TYPE_AC }, { "USB_HVDCP_3", ANDROID_POWER_SUPPLY_TYPE_AC }, + { "USB_C", ANDROID_POWER_SUPPLY_TYPE_AC }, + { "USB_PD", ANDROID_POWER_SUPPLY_TYPE_AC }, + { "USB_PD_DRP", ANDROID_POWER_SUPPLY_TYPE_USB }, { "Wireless", ANDROID_POWER_SUPPLY_TYPE_WIRELESS }, { "Wipower", ANDROID_POWER_SUPPLY_TYPE_WIRELESS }, { "DockBattery", ANDROID_POWER_SUPPLY_TYPE_DOCK_BATTERY }, -- cgit v1.1 From 5d90c85e977df6dd34443b6050db5c994570f410 Mon Sep 17 00:00:00 2001 From: Tom Marshall Date: Tue, 5 Jul 2016 13:33:47 -0700 Subject: healthd: Write to blink file to fix LED Many devices (such as bacon) require touching a blink file before changes to the LED are committed to hardware. Jira: CYAN-7689 Change-Id: Ia18a62134d196a636352bcd1af924c407c19d5b4 --- healthd/Android.mk | 1 + healthd/healthd_mode_charger.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/healthd/Android.mk b/healthd/Android.mk index 7db4ad5..f509ace 100644 --- a/healthd/Android.mk +++ b/healthd/Android.mk @@ -34,6 +34,7 @@ LOCAL_CFLAGS := -D__STDC_LIMIT_MACROS -Werror HEALTHD_CHARGER_DEFINES := RED_LED_PATH \ GREEN_LED_PATH \ BLUE_LED_PATH \ + BLINK_PATH \ BACKLIGHT_PATH \ CHARGING_ENABLED_PATH diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp index d6c31cf..6df9f12 100644 --- a/healthd/healthd_mode_charger.cpp +++ b/healthd/healthd_mode_charger.cpp @@ -82,6 +82,10 @@ char *locale; #define BLUE_LED_PATH "/sys/class/leds/blue/brightness" #endif +#ifndef BLINK_PATH +#define BLINK_PATH "/sys/class/leds/red/device/blink" +#endif + #define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0) #define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0) #define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0) @@ -214,6 +218,26 @@ static int char_height; static bool minui_inited; #ifndef NO_CHARGER_LED +static int set_blink(int val) +{ + int fd; + char buffer[10]; + + fd = open(BLINK_PATH, O_RDWR); + if (fd < 0) { + LOGE("Could not open blink file\n"); + return -1; + } + snprintf(buffer, sizeof(buffer), "%d\n", val); + if (write(fd, buffer, strlen(buffer)) < 0) { + LOGE("Could not write to blink file\n"); + close(fd); + return -1; + } + close(fd); + return 0; +} + static int set_tricolor_led(int on, int color) { int fd, i; @@ -258,6 +282,9 @@ static int set_battery_soc_leds(int soc) LOGV("soc = %d, set led color 0x%x\n", soc, soc_leds[i].color); } + /* This is required to commit the changes to hardware */ + set_blink(0); + return 0; } #endif -- cgit v1.1 From 5b537bbac12ada45240f441d830bb94c42696230 Mon Sep 17 00:00:00 2001 From: Ruchi Kandoi Date: Mon, 29 Feb 2016 13:13:39 -0800 Subject: healthd: Check if battery device exists instead of charger drivers before setting fake properties. healthd used to check for registered charger drivers to determine if the device is an always-plugged device with no battery. This patch changes it to check for battery instead. Change-Id: Ie4ff5d3f21dc1a83a780a41eb0c929f66b86d631 Signed-off-by: Ruchi Kandoi --- healthd/BatteryMonitor.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp index dfa59b8..a59c779 100644 --- a/healthd/BatteryMonitor.cpp +++ b/healthd/BatteryMonitor.cpp @@ -835,19 +835,15 @@ void BatteryMonitor::init(struct healthd_config *hc) { closedir(dir); } - // This indicates that there is no charger driver registered. // Typically the case for devices which do not have a battery and // and are always plugged into AC mains. - if (!mChargerNames.size()) { - KLOG_ERROR(LOG_TAG, "No charger supplies found\n"); - mBatteryFixedCapacity = ALWAYS_PLUGGED_CAPACITY; - mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE; - mAlwaysPluggedDevice = true; - } if (!mBatteryDevicePresent && !mDockBatteryDevicePresent) { KLOG_WARNING(LOG_TAG, "No battery devices found\n"); hc->periodic_chores_interval_fast = -1; hc->periodic_chores_interval_slow = -1; + mBatteryFixedCapacity = ALWAYS_PLUGGED_CAPACITY; + mBatteryFixedTemperature = FAKE_BATTERY_TEMPERATURE; + mAlwaysPluggedDevice = true; } else { if (mHealthdConfig->batteryStatusPath.isEmpty()) KLOG_WARNING(LOG_TAG, "BatteryStatusPath not found\n"); -- cgit v1.1 From b619152148dadeda1acef702420f43c30e7d6d30 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 2 Feb 2016 08:05:54 -0800 Subject: libcutils: ashmem fortify and comply with Android coding standard - sort header order and in groups - remove all tabs, use only spaces - use TEMP_FAILURE_RETRY in system calls - preserve errno for -1 return Bug: 26871259 Change-Id: I94fffbcaeba01fcc18a3ed07c02389c06c54d3b7 --- libcutils/ashmem-dev.c | 63 +++++++++++++++++++++++++++---------------------- libcutils/ashmem-host.c | 7 ++++-- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c index 3089a94..a5203e1 100644 --- a/libcutils/ashmem-dev.c +++ b/libcutils/ashmem-dev.c @@ -20,17 +20,19 @@ * used by the simulator. */ -#include +#include +#include #include -#include -#include #include -#include +#include +#include +#include #include + #include -#define ASHMEM_DEVICE "/dev/ashmem" +#define ASHMEM_DEVICE "/dev/ashmem" /* * ashmem_create_region - creates a new ashmem region and returns the file @@ -41,50 +43,55 @@ */ int ashmem_create_region(const char *name, size_t size) { - int fd, ret; + int ret, save_errno; - fd = open(ASHMEM_DEVICE, O_RDWR); - if (fd < 0) - return fd; + int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR)); + if (fd < 0) { + return fd; + } - if (name) { - char buf[ASHMEM_NAME_LEN] = {0}; + if (name) { + char buf[ASHMEM_NAME_LEN] = {0}; - strlcpy(buf, name, sizeof(buf)); - ret = ioctl(fd, ASHMEM_SET_NAME, buf); - if (ret < 0) - goto error; - } + strlcpy(buf, name, sizeof(buf)); + ret = TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_NAME, buf)); + if (ret < 0) { + goto error; + } + } - ret = ioctl(fd, ASHMEM_SET_SIZE, size); - if (ret < 0) - goto error; + ret = TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_SIZE, size)); + if (ret < 0) { + goto error; + } - return fd; + return fd; error: - close(fd); - return ret; + save_errno = errno; + close(fd); + errno = save_errno; + return ret; } int ashmem_set_prot_region(int fd, int prot) { - return ioctl(fd, ASHMEM_SET_PROT_MASK, prot); + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot)); } int ashmem_pin_region(int fd, size_t offset, size_t len) { - struct ashmem_pin pin = { offset, len }; - return ioctl(fd, ASHMEM_PIN, &pin); + struct ashmem_pin pin = { offset, len }; + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin)); } int ashmem_unpin_region(int fd, size_t offset, size_t len) { - struct ashmem_pin pin = { offset, len }; - return ioctl(fd, ASHMEM_UNPIN, &pin); + struct ashmem_pin pin = { offset, len }; + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin)); } int ashmem_get_size_region(int fd) { - return ioctl(fd, ASHMEM_GET_SIZE, NULL); + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)); } diff --git a/libcutils/ashmem-host.c b/libcutils/ashmem-host.c index abc4f94..99a2759 100644 --- a/libcutils/ashmem-host.c +++ b/libcutils/ashmem-host.c @@ -73,8 +73,11 @@ int ashmem_get_size_region(int fd) return -1; } - // Check if this is an "ashmem" region. - // TODO: This is very hacky, and can easily break. We need some reliable indicator. + /* + * Check if this is an "ashmem" region. + * TODO: This is very hacky, and can easily break. + * We need some reliable indicator. + */ if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) { errno = ENOTTY; return -1; -- cgit v1.1 From 2895e11453da7afc326864a097ff59833a0bffea Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 2 Feb 2016 08:21:32 -0800 Subject: libcutils: ashmem check fd validity - collect st_rdev on open, or when required, for /dev/ashmem. - check in all cases if fd is a character device and matches rdev. - requires that we have open, read and write access to /dev/ashmem to check, assumption being that if we can not, then we have no right playing with the associated misdirected file descriptor. NB: ashmem libcutil library entry points can no longer be called in signal context. Bug: 26871259 Change-Id: I9a17e33317a9be795131473a51c16f761b5f7407 --- libcutils/ashmem-dev.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c index a5203e1..77e4d0d 100644 --- a/libcutils/ashmem-dev.c +++ b/libcutils/ashmem-dev.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,89 @@ #define ASHMEM_DEVICE "/dev/ashmem" +/* ashmem identity */ +static dev_t __ashmem_rdev; +/* + * If we trigger a signal handler in the middle of locked activity and the + * signal handler calls ashmem, we could get into a deadlock state. + */ +static pthread_mutex_t __ashmem_lock = PTHREAD_MUTEX_INITIALIZER; + +/* logistics of getting file descriptor for ashmem */ +static int __ashmem_open_locked() +{ + int ret; + struct stat st; + + int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR)); + if (fd < 0) { + return fd; + } + + ret = TEMP_FAILURE_RETRY(fstat(fd, &st)); + if (ret < 0) { + int save_errno = errno; + close(fd); + errno = save_errno; + return ret; + } + if (!S_ISCHR(st.st_mode) || !st.st_rdev) { + close(fd); + errno = ENOTTY; + return -1; + } + + __ashmem_rdev = st.st_rdev; + return fd; +} + +static int __ashmem_open() +{ + int fd; + + pthread_mutex_lock(&__ashmem_lock); + fd = __ashmem_open_locked(); + pthread_mutex_unlock(&__ashmem_lock); + + return fd; +} + +/* Make sure file descriptor references ashmem, negative number means false */ +static int __ashmem_is_ashmem(int fd) +{ + dev_t rdev; + struct stat st; + + if (TEMP_FAILURE_RETRY(fstat(fd, &st)) < 0) { + return -1; + } + + if (S_ISCHR(st.st_mode) && st.st_rdev) { + pthread_mutex_lock(&__ashmem_lock); + rdev = __ashmem_rdev; + if (rdev) { + pthread_mutex_unlock(&__ashmem_lock); + } else { + int fd = __ashmem_open_locked(); + if (fd < 0) { + pthread_mutex_unlock(&__ashmem_lock); + return -1; + } + rdev = __ashmem_rdev; + pthread_mutex_unlock(&__ashmem_lock); + + close(fd); + } + + if (st.st_rdev == rdev) { + return 0; + } + } + + errno = ENOTTY; + return -1; +} + /* * ashmem_create_region - creates a new ashmem region and returns the file * descriptor, or <0 on error @@ -45,7 +129,7 @@ int ashmem_create_region(const char *name, size_t size) { int ret, save_errno; - int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR)); + int fd = __ashmem_open(); if (fd < 0) { return fd; } @@ -76,22 +160,44 @@ error: int ashmem_set_prot_region(int fd, int prot) { + int ret = __ashmem_is_ashmem(fd); + if (ret < 0) { + return ret; + } + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_SET_PROT_MASK, prot)); } int ashmem_pin_region(int fd, size_t offset, size_t len) { struct ashmem_pin pin = { offset, len }; + + int ret = __ashmem_is_ashmem(fd); + if (ret < 0) { + return ret; + } + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_PIN, &pin)); } int ashmem_unpin_region(int fd, size_t offset, size_t len) { struct ashmem_pin pin = { offset, len }; + + int ret = __ashmem_is_ashmem(fd); + if (ret < 0) { + return ret; + } + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_UNPIN, &pin)); } int ashmem_get_size_region(int fd) { + int ret = __ashmem_is_ashmem(fd); + if (ret < 0) { + return ret; + } + return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_SIZE, NULL)); } -- cgit v1.1 From 70a8c7aef01d843eb390e744243667e1af6c5615 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 2 Feb 2016 09:19:39 -0800 Subject: libcutils: ashmem print error message for invalid fd NB: We decided to not sniff for the constant saved __ashmem_rdev in the early error path; requiring either the use of atomic operations, or acquiring a lock to do it correctly. The heroics are not worth it. Bug: 26871259 Change-Id: I46249838850ae32063eb5b7d08c731c5bb0fbf6b --- libcutils/ashmem-dev.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c index 77e4d0d..d6a48c9 100644 --- a/libcutils/ashmem-dev.c +++ b/libcutils/ashmem-dev.c @@ -19,6 +19,7 @@ * ashmem-enabled kernel. See ashmem-sim.c for the "fake" tmp-based version, * used by the simulator. */ +#define LOG_TAG "ashmem" #include #include @@ -32,6 +33,7 @@ #include #include +#include #define ASHMEM_DEVICE "/dev/ashmem" @@ -92,6 +94,7 @@ static int __ashmem_is_ashmem(int fd) return -1; } + rdev = 0; /* Too much complexity to sniff __ashmem_rdev */ if (S_ISCHR(st.st_mode) && st.st_rdev) { pthread_mutex_lock(&__ashmem_lock); rdev = __ashmem_rdev; @@ -114,6 +117,17 @@ static int __ashmem_is_ashmem(int fd) } } + if (rdev) { + ALOGE("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o %d:%d", + fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP, + major(rdev), minor(rdev)); + } else { + ALOGE("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o", + fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev), + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP); + } + errno = ENOTTY; return -1; } -- cgit v1.1 From 53bf23431d5e9f5b320d9e2adb7b10f650178dc9 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 2 Feb 2016 09:20:31 -0800 Subject: libcutils: abort for invalid fd If ashmem accessors are being called with a file descriptor that belongs to anything other than ashmem, we need to stop it right now so that they can fix the caller. Bug: 26871259 Change-Id: Icf9aafc3631a80b9af6fe0fea03599d61e285d21 --- libcutils/ashmem-dev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c index d6a48c9..4a07d66 100644 --- a/libcutils/ashmem-dev.c +++ b/libcutils/ashmem-dev.c @@ -118,15 +118,16 @@ static int __ashmem_is_ashmem(int fd) } if (rdev) { - ALOGE("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o %d:%d", + LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o %d:%d", fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP, major(rdev), minor(rdev)); } else { - ALOGE("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o", + LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o", fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP); } + /* NOTREACHED */ errno = ENOTTY; return -1; -- cgit v1.1 From 3c28cda5d0120eb7bf7a49b36b96f45c0a588232 Mon Sep 17 00:00:00 2001 From: Sergio Giro Date: Tue, 28 Jun 2016 18:02:29 +0100 Subject: libutils/Unicode.cpp: Correct length computation and add checks for utf16->utf8 Inconsistent behaviour between utf16_to_utf8 and utf16_to_utf8_length is causing a heap overflow. Correcting the length computation and adding bound checks to the conversion functions. Test: ran libutils_tests Bug: 29250543 Change-Id: I6115e3357141ed245c63c6eb25fc0fd0a9a7a2bb (cherry picked from commit c4966a363e46d2e1074d1a365e232af0dcedd6a1) --- include/utils/Unicode.h | 4 ++-- libutils/String8.cpp | 25 +++++++++++++------------ libutils/Unicode.cpp | 15 +++++++++++---- libutils/tests/String8_test.cpp | 19 +++++++++++++++++++ 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/include/utils/Unicode.h b/include/utils/Unicode.h index b76a5e2..4e17cc3 100644 --- a/include/utils/Unicode.h +++ b/include/utils/Unicode.h @@ -87,7 +87,7 @@ ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len); * "dst" becomes \xE3\x81\x82\xE3\x81\x84 * (note that "dst" is NOT null-terminated, like strncpy) */ -void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst); +void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len); /** * Returns the unicode value at "index". @@ -109,7 +109,7 @@ ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len); * enough to fit the UTF-16 as measured by utf16_to_utf8_length with an added * NULL terminator. */ -void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst); +void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len); /** * Returns the length of "src" when "src" is valid UTF-8 string. diff --git a/libutils/String8.cpp b/libutils/String8.cpp index ad65fdb..75dfa29 100644 --- a/libutils/String8.cpp +++ b/libutils/String8.cpp @@ -102,20 +102,21 @@ static char* allocFromUTF16(const char16_t* in, size_t len) { if (len == 0) return getEmptyString(); - const ssize_t bytes = utf16_to_utf8_length(in, len); - if (bytes < 0) { + // Allow for closing '\0' + const ssize_t resultStrLen = utf16_to_utf8_length(in, len) + 1; + if (resultStrLen < 1) { return getEmptyString(); } - SharedBuffer* buf = SharedBuffer::alloc(bytes+1); + SharedBuffer* buf = SharedBuffer::alloc(resultStrLen); ALOG_ASSERT(buf, "Unable to allocate shared buffer"); if (!buf) { return getEmptyString(); } - char* str = (char*)buf->data(); - utf16_to_utf8(in, len, str); - return str; + char* resultStr = (char*)buf->data(); + utf16_to_utf8(in, len, resultStr, resultStrLen); + return resultStr; } static char* allocFromUTF32(const char32_t* in, size_t len) @@ -124,21 +125,21 @@ static char* allocFromUTF32(const char32_t* in, size_t len) return getEmptyString(); } - const ssize_t bytes = utf32_to_utf8_length(in, len); - if (bytes < 0) { + const ssize_t resultStrLen = utf32_to_utf8_length(in, len) + 1; + if (resultStrLen < 1) { return getEmptyString(); } - SharedBuffer* buf = SharedBuffer::alloc(bytes+1); + SharedBuffer* buf = SharedBuffer::alloc(resultStrLen); ALOG_ASSERT(buf, "Unable to allocate shared buffer"); if (!buf) { return getEmptyString(); } - char* str = (char*) buf->data(); - utf32_to_utf8(in, len, str); + char* resultStr = (char*) buf->data(); + utf32_to_utf8(in, len, resultStr, resultStrLen); - return str; + return resultStr; } // --------------------------------------------------------------------------- diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp index fb876c9..2b5293e 100644 --- a/libutils/Unicode.cpp +++ b/libutils/Unicode.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include @@ -182,7 +183,7 @@ ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len) return ret; } -void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst) +void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len) { if (src == NULL || src_len == 0 || dst == NULL) { return; @@ -193,9 +194,12 @@ void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst) char *cur = dst; while (cur_utf32 < end_utf32) { size_t len = utf32_codepoint_utf8_length(*cur_utf32); + LOG_ALWAYS_FATAL_IF(dst_len < len, "%zu < %zu", dst_len, len); utf32_codepoint_to_utf8((uint8_t *)cur, *cur_utf32++, len); cur += len; + dst_len -= len; } + LOG_ALWAYS_FATAL_IF(dst_len < 1, "dst_len < 1: %zu < 1", dst_len); *cur = '\0'; } @@ -324,7 +328,7 @@ int strzcmp16_h_n(const char16_t *s1H, size_t n1, const char16_t *s2N, size_t n2 : 0); } -void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst) +void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len) { if (src == NULL || src_len == 0 || dst == NULL) { return; @@ -345,9 +349,12 @@ void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst) utf32 = (char32_t) *cur_utf16++; } const size_t len = utf32_codepoint_utf8_length(utf32); + LOG_ALWAYS_FATAL_IF(dst_len < len, "%zu < %zu", dst_len, len); utf32_codepoint_to_utf8((uint8_t*)cur, utf32, len); cur += len; + dst_len -= len; } + LOG_ALWAYS_FATAL_IF(dst_len < 1, "%zu < 1", dst_len); *cur = '\0'; } @@ -408,10 +415,10 @@ ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len) const char16_t* const end = src + src_len; while (src < end) { if ((*src & 0xFC00) == 0xD800 && (src + 1) < end - && (*++src & 0xFC00) == 0xDC00) { + && (*(src + 1) & 0xFC00) == 0xDC00) { // surrogate pairs are always 4 bytes. ret += 4; - src++; + src += 2; } else { ret += utf32_codepoint_utf8_length((char32_t) *src++); } diff --git a/libutils/tests/String8_test.cpp b/libutils/tests/String8_test.cpp index c42c68d..7cd67d3 100644 --- a/libutils/tests/String8_test.cpp +++ b/libutils/tests/String8_test.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "String8_test" #include #include +#include #include @@ -72,4 +73,22 @@ TEST_F(String8Test, OperatorPlusEquals) { EXPECT_STREQ(src3, " Verify me."); } +// http://b/29250543 +TEST_F(String8Test, CorrectInvalidSurrogate) { + // d841d8 is an invalid start for a surrogate pair. Make sure this is handled by ignoring the + // first character in the pair and handling the rest correctly. + String16 string16(u"\xd841\xd841\xdc41\x0000"); + String8 string8(string16); + + EXPECT_EQ(4U, string8.length()); +} + +TEST_F(String8Test, CheckUtf32Conversion) { + // Since bound checks were added, check the conversion can be done without fatal errors. + // The utf8 lengths of these are chars are 1 + 2 + 3 + 4 = 10. + const char32_t string32[] = U"\x0000007f\x000007ff\x0000911\x0010fffe"; + String8 string8(string32); + EXPECT_EQ(10U, string8.length()); +} + } -- cgit v1.1 From 014b1592fd10ef5733a943325cf20cb6c1cdf187 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Tue, 17 May 2016 19:23:39 -0700 Subject: adb: switch the socket list mutex to a recursive_mutex. sockets.cpp was branching on whether a socket close function was local_socket_close in order to avoid a potential deadlock if the socket list lock was held while closing a peer socket. Bug: http://b/28347842 Change-Id: I5e56f17fa54275284787f0f1dc150d1960256ab3 (functionally a cherrypick of 903b749f + 9b587dec, with windows disabled) --- adb/Android.mk | 3 ++ adb/mutex_list.h | 1 - adb/sockets.cpp | 78 +++++++++++++--------------- adb/sysdeps/mutex.h | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 45 deletions(-) create mode 100644 adb/sysdeps/mutex.h diff --git a/adb/Android.mk b/adb/Android.mk index 425bf9b..d4adbfb 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -200,7 +200,10 @@ endif # will violate ODR LOCAL_SHARED_LIBRARIES := +# Don't build the host adb on Windows (this branch should only be used for security updates.) +ifneq ($(HOST_OS),windows) include $(BUILD_HOST_EXECUTABLE) +endif $(call dist-for-goals,dist_files sdk,$(LOCAL_BUILT_MODULE)) diff --git a/adb/mutex_list.h b/adb/mutex_list.h index ff72751..15e383c 100644 --- a/adb/mutex_list.h +++ b/adb/mutex_list.h @@ -6,7 +6,6 @@ #ifndef ADB_MUTEX #error ADB_MUTEX not defined when including this file #endif -ADB_MUTEX(socket_list_lock) ADB_MUTEX(transport_lock) #if ADB_HOST ADB_MUTEX(local_transports_lock) diff --git a/adb/sockets.cpp b/adb/sockets.cpp index 32ca17d..31b5443 100644 --- a/adb/sockets.cpp +++ b/adb/sockets.cpp @@ -25,18 +25,27 @@ #include #include +#include +#include +#include +#include + #if !ADB_HOST #include "cutils/properties.h" #endif #include "adb.h" #include "adb_io.h" +#include "sysdeps/mutex.h" #include "transport.h" -ADB_MUTEX_DEFINE( socket_list_lock ); +#if !defined(__BIONIC__) +using std::recursive_mutex; +#endif -static void local_socket_close_locked(asocket *s); +static void local_socket_close(asocket* s); +static recursive_mutex& local_socket_list_lock = *new recursive_mutex(); static unsigned local_socket_next_id = 1; static asocket local_socket_list = { @@ -61,7 +70,7 @@ asocket *find_local_socket(unsigned local_id, unsigned peer_id) asocket *s; asocket *result = NULL; - adb_mutex_lock(&socket_list_lock); + std::lock_guard lock(local_socket_list_lock); for (s = local_socket_list.next; s != &local_socket_list; s = s->next) { if (s->id != local_id) continue; @@ -70,7 +79,6 @@ asocket *find_local_socket(unsigned local_id, unsigned peer_id) } break; } - adb_mutex_unlock(&socket_list_lock); return result; } @@ -84,20 +92,17 @@ insert_local_socket(asocket* s, asocket* list) s->next->prev = s; } - -void install_local_socket(asocket *s) -{ - adb_mutex_lock(&socket_list_lock); +void install_local_socket(asocket* s) { + std::lock_guard lock(local_socket_list_lock); s->id = local_socket_next_id++; // Socket ids should never be 0. - if (local_socket_next_id == 0) - local_socket_next_id = 1; + if (local_socket_next_id == 0) { + fatal("local socket id overflow"); + } insert_local_socket(s, &local_socket_list); - - adb_mutex_unlock(&socket_list_lock); } void remove_socket(asocket *s) @@ -116,19 +121,17 @@ void remove_socket(asocket *s) void close_all_sockets(atransport *t) { asocket *s; - - /* this is a little gross, but since s->close() *will* modify - ** the list out from under you, your options are limited. - */ - adb_mutex_lock(&socket_list_lock); + /* this is a little gross, but since s->close() *will* modify + ** the list out from under you, your options are limited. + */ + std::lock_guard lock(local_socket_list_lock); restart: - for(s = local_socket_list.next; s != &local_socket_list; s = s->next){ - if(s->transport == t || (s->peer && s->peer->transport == t)) { - local_socket_close_locked(s); + for (s = local_socket_list.next; s != &local_socket_list; s = s->next) { + if (s->transport == t || (s->peer && s->peer->transport == t)) { + local_socket_close(s); goto restart; } } - adb_mutex_unlock(&socket_list_lock); } static int local_socket_enqueue(asocket *s, apacket *p) @@ -191,13 +194,6 @@ static void local_socket_ready(asocket *s) fdevent_add(&s->fde, FDE_READ); } -static void local_socket_close(asocket *s) -{ - adb_mutex_lock(&socket_list_lock); - local_socket_close_locked(s); - adb_mutex_unlock(&socket_list_lock); -} - // be sure to hold the socket list lock when calling this static void local_socket_destroy(asocket *s) { @@ -226,27 +222,21 @@ static void local_socket_destroy(asocket *s) } } - -static void local_socket_close_locked(asocket *s) -{ - D("entered local_socket_close_locked. LS(%d) fd=%d\n", s->id, s->fd); - if(s->peer) { - D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n", - s->id, s->peer->id, s->peer->fd); +static void local_socket_close(asocket* s) { + D("entered local_socket_close. LS(%d) fd=%d", s->id, s->fd); + std::lock_guard lock(local_socket_list_lock); + if (s->peer) { + D("LS(%d): closing peer. peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd); /* Note: it's important to call shutdown before disconnecting from * the peer, this ensures that remote sockets can still get the id * of the local socket they're connected to, to send a CLOSE() * protocol event. */ - if (s->peer->shutdown) - s->peer->shutdown(s->peer); - s->peer->peer = 0; - // tweak to avoid deadlock - if (s->peer->close == local_socket_close) { - local_socket_close_locked(s->peer); - } else { - s->peer->close(s->peer); + if (s->peer->shutdown) { + s->peer->shutdown(s->peer); } - s->peer = 0; + s->peer->peer = nullptr; + s->peer->close(s->peer); + s->peer = nullptr; } /* If we are already closing, or if there are no diff --git a/adb/sysdeps/mutex.h b/adb/sysdeps/mutex.h new file mode 100644 index 0000000..ef5d9b1 --- /dev/null +++ b/adb/sysdeps/mutex.h @@ -0,0 +1,143 @@ +#pragma once + +/* + * Copyright (C) 2016 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. + */ + +#if defined(_WIN32) + +#include + +#include + +#include "adb.h" + +// The prebuilt version of mingw we use doesn't support mutex or recursive_mutex. +// Therefore, implement our own using the Windows primitives. +// Put them directly into the std namespace, so that when they're actually available, the build +// breaks until they're removed. + +#include +namespace std { + +// CRITICAL_SECTION is recursive, so just wrap it in a Mutex-compatible class. +class recursive_mutex { + public: + recursive_mutex() { + InitializeCriticalSection(&mutex_); + } + + ~recursive_mutex() { + DeleteCriticalSection(&mutex_); + } + + void lock() { + EnterCriticalSection(&mutex_); + } + + bool try_lock() { + return TryEnterCriticalSection(&mutex_); + } + + void unlock() { + LeaveCriticalSection(&mutex_); + } + + private: + CRITICAL_SECTION mutex_; + + DISALLOW_COPY_AND_ASSIGN(recursive_mutex); +}; + +class mutex { + public: + mutex() { + } + + ~mutex() { + } + + void lock() { + mutex_.lock(); + if (++lock_count_ != 1) { + fatal("non-recursive mutex locked reentrantly"); + } + } + + void unlock() { + if (--lock_count_ != 0) { + fatal("non-recursive mutex unlock resulted in unexpected lock count: %d", lock_count_); + } + mutex_.unlock(); + } + + bool try_lock() { + if (!mutex_.try_lock()) { + return false; + } + + if (lock_count_ != 0) { + mutex_.unlock(); + return false; + } + + ++lock_count_; + return true; + } + + private: + recursive_mutex mutex_; + size_t lock_count_ = 0; +}; + +} + +#elif defined(__BIONIC__) + +// On M, the recovery image uses parts of adb that depends on recursive_mutex, and uses libstdc++, +// which lacks it. + +#include +#include + +#include + +class recursive_mutex { + public: + recursive_mutex() { + } + + ~recursive_mutex() { + } + + void lock() { + pthread_mutex_lock(&mutex_); + } + + bool try_lock() { + return pthread_mutex_trylock(&mutex_); + } + + void unlock() { + pthread_mutex_unlock(&mutex_); + } + + private: + pthread_mutex_t mutex_ = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + + DISALLOW_COPY_AND_ASSIGN(recursive_mutex); +}; + +#endif -- cgit v1.1 From f483354e592c9edd836acbc0fffcedfb6958c889 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Wed, 18 May 2016 10:39:48 -0700 Subject: adb: use asocket's close function when closing. close_all_sockets was assuming that all registered local sockets used local_socket_close as their close function. However, this is not true for JDWP sockets. Bug: http://b/28347842 Change-Id: I40a1174845cd33f15f30ce70828a7081cd5a087e (cherry picked from commit 53eb31d87cb84a4212f4850bf745646e1fb12814) (cherry picked from commit 014b01706cc64dc9c2ad94a96f62e07c058d0b5d) --- adb/sockets.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/adb/sockets.cpp b/adb/sockets.cpp index 31b5443..3919147 100644 --- a/adb/sockets.cpp +++ b/adb/sockets.cpp @@ -43,8 +43,6 @@ using std::recursive_mutex; #endif -static void local_socket_close(asocket* s); - static recursive_mutex& local_socket_list_lock = *new recursive_mutex(); static unsigned local_socket_next_id = 1; @@ -128,7 +126,7 @@ void close_all_sockets(atransport *t) restart: for (s = local_socket_list.next; s != &local_socket_list; s = s->next) { if (s->transport == t || (s->peer && s->peer->transport == t)) { - local_socket_close(s); + s->close(s); goto restart; } } -- cgit v1.1 From c764dcd6977a04e272e44b0381c13ac4aed8a280 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Thu, 14 Jul 2016 16:43:12 -0700 Subject: DO NOT MERGE: debuggerd: verify that traced threads belong to the right process. Fix two races in debuggerd's PTRACE_ATTACH logic: 1. The target thread in a crash dump request could exit between the /proc//task/ check and the PTRACE_ATTACH. 2. Sibling threads could exit between listing /proc//task and the PTRACE_ATTACH. Backport of NYC change I4dfe1ea30e2c211d2389321bd66e3684dd757591 Bug: http://b/29555636 Change-Id: I6c6efcf82a49bca140d761b2d1de04215ba4d252 --- debuggerd/backtrace.cpp | 10 +++++----- debuggerd/debuggerd.cpp | 33 +++++++++++++++++++++++++++------ debuggerd/utility.cpp | 29 +++++++++++++++++++++++++++++ debuggerd/utility.h | 5 +++++ 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/debuggerd/backtrace.cpp b/debuggerd/backtrace.cpp index b8084c5..ad6a6ee 100644 --- a/debuggerd/backtrace.cpp +++ b/debuggerd/backtrace.cpp @@ -67,8 +67,8 @@ static void dump_process_footer(log_t* log, pid_t pid) { _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid); } -static void dump_thread( - log_t* log, pid_t tid, bool attached, bool* detach_failed, int* total_sleep_time_usec) { +static void dump_thread(log_t* log, pid_t pid, pid_t tid, bool attached, + bool* detach_failed, int* total_sleep_time_usec) { char path[PATH_MAX]; char threadnamebuf[1024]; char* threadname = NULL; @@ -88,7 +88,7 @@ static void dump_thread( _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "", tid); - if (!attached && ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) { + if (!attached && !ptrace_attach_thread(pid, tid)) { _LOG(log, logtype::BACKTRACE, "Could not attach to thread: %s\n", strerror(errno)); return; } @@ -117,7 +117,7 @@ void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, log.amfd = amfd; dump_process_header(&log, pid); - dump_thread(&log, tid, true, detach_failed, total_sleep_time_usec); + dump_thread(&log, pid, tid, true, detach_failed, total_sleep_time_usec); char task_path[64]; snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); @@ -135,7 +135,7 @@ void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, continue; } - dump_thread(&log, new_tid, false, detach_failed, total_sleep_time_usec); + dump_thread(&log, pid, new_tid, false, detach_failed, total_sleep_time_usec); } closedir(d); } diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 9c8a41e..2ab716d 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -225,12 +225,10 @@ static int read_request(int fd, debugger_request_t* out_request) { if (msg.action == DEBUGGER_ACTION_CRASH) { // Ensure that the tid reported by the crashing process is valid. - char buf[64]; - struct stat s; - snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid); - if (stat(buf, &s)) { + // This check needs to happen again after ptracing the requested thread to prevent a race. + if (!pid_contains_tid(out_request->pid, out_request->tid)) { ALOGE("tid %d does not exist in pid %d. ignoring debug request\n", - out_request->tid, out_request->pid); + out_request->tid, out_request->pid); return -1; } } else if (cr.uid == 0 @@ -380,9 +378,32 @@ static void handle_request(int fd) { // ensure that it can run as soon as we call PTRACE_CONT below. // See details in bionic/libc/linker/debugger.c, in function // debugger_signal_handler(). - if (ptrace(PTRACE_ATTACH, request.tid, 0, 0)) { + if (!ptrace_attach_thread(request.pid, request.tid)) { ALOGE("ptrace attach failed: %s\n", strerror(errno)); } else { + // DEBUGGER_ACTION_CRASH requests can come from arbitrary processes and the tid field in + // the request is sent from the other side. If an attacker can cause a process to be + // spawned with the pid of their process, they could trick debuggerd into dumping that + // process by exiting after sending the request. Validate the trusted request.uid/gid + // to defend against this. + if (request.action == DEBUGGER_ACTION_CRASH) { + pid_t pid; + uid_t uid; + gid_t gid; + if (get_process_info(request.tid, &pid, &uid, &gid) != 0) { + ALOGE("debuggerd: failed to get process info for tid '%d'", request.tid); + exit(1); + } + + if (pid != request.pid || uid != request.uid || gid != request.gid) { + ALOGE( + "debuggerd: attached task %d does not match request: " + "expected pid=%d,uid=%d,gid=%d, actual pid=%d,uid=%d,gid=%d", + request.tid, request.pid, request.uid, request.gid, pid, uid, gid); + exit(1); + } + } + bool detach_failed = false; bool tid_unresponsive = false; bool attach_gdb = should_attach_gdb(&request); diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp index 9f340a8..236d667 100644 --- a/debuggerd/utility.cpp +++ b/debuggerd/utility.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -207,3 +208,31 @@ void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* f _LOG(log, logtype::MEMORY, "%s %s\n", logline.c_str(), ascii.c_str()); } } + +bool pid_contains_tid(pid_t pid, pid_t tid) { + char task_path[PATH_MAX]; + if (snprintf(task_path, PATH_MAX, "/proc/%d/task/%d", pid, tid) >= PATH_MAX) { + ALOGE("debuggerd: task path overflow (pid = %d, tid = %d)\n", pid, tid); + exit(1); + } + + return access(task_path, F_OK) == 0; +} + +// Attach to a thread, and verify that it's still a member of the given process +bool ptrace_attach_thread(pid_t pid, pid_t tid) { + if (ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) { + return false; + } + + // Make sure that the task we attached to is actually part of the pid we're dumping. + if (!pid_contains_tid(pid, tid)) { + if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { + ALOGE("debuggerd: failed to detach from thread '%d'", tid); + exit(1); + } + return false; + } + + return true; +} diff --git a/debuggerd/utility.h b/debuggerd/utility.h index 263374d..e8ec7ef 100644 --- a/debuggerd/utility.h +++ b/debuggerd/utility.h @@ -79,4 +79,9 @@ int wait_for_sigstop(pid_t, int*, bool*); void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...); +bool pid_contains_tid(pid_t pid, pid_t tid); + +// Attach to a thread, and verify that it's still a member of the given process +bool ptrace_attach_thread(pid_t pid, pid_t tid); + #endif // _DEBUGGERD_UTILITY_H -- cgit v1.1 From d63e6757fa22fcb58653233fce035deed8036a1b Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Sat, 23 Jul 2016 20:16:24 -0700 Subject: sdcard: Add support for sdcardfs! * sdcardfs is a kernel filesystem developed by Samsung and recently seen in AOSP's common kernel branches. It entirely eliminates the need to use FUSE for sdcard emulation and moves all the wrapping logic to kernel. This vastly improves performance for use cases which read/write to emulated as well as removable cards. Change-Id: I3e394a99e0a4b5beacaeddc0d4dd4855ff0cf082 --- sdcard/sdcard.c | 63 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index 98af250..c0f60ed 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -1776,24 +1777,39 @@ static int usage() { return 1; } -static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask) { +static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask, bool use_sdcardfs) { char opts[256]; - fuse->fd = open("/dev/fuse", O_RDWR); - if (fuse->fd == -1) { - ERROR("failed to open fuse device: %s\n", strerror(errno)); - return -1; + if (use_sdcardfs) { + fuse->fd = open("/dev/fuse", O_RDWR); + if (fuse->fd == -1) { + ERROR("failed to open fuse device: %s\n", strerror(errno)); + return -1; + } } umount2(fuse->dest_path, MNT_DETACH); - snprintf(opts, sizeof(opts), - "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d", - fuse->fd, fuse->global->uid, fuse->global->gid); - if (mount("/dev/fuse", fuse->dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC | - MS_NOATIME, opts) != 0) { - ERROR("failed to mount fuse filesystem: %s\n", strerror(errno)); - return -1; + if (use_sdcardfs) { + snprintf(opts, sizeof(opts), + "%sfsuid=%d,fsgid=%d,userid=%d,gid=%d,mask=%04o,reserved_mb=20", + (fuse->global->multi_user ? "multiuser," : ""), + fuse->global->uid, fuse->global->gid, + fuse->global->root.userid, gid, mask); + if (mount(fuse->global->source_path, fuse->dest_path, "sdcardfs", + MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts) != 0) { + ERROR("failed to mount sdcardfs filesystem: %s\n", strerror(errno)); + return -1; + } + } else { + snprintf(opts, sizeof(opts), + "fd=%i,rootmode=40000,default_permissions,allow_other,user_id=%d,group_id=%d", + fuse->fd, fuse->global->uid, fuse->global->gid); + if (mount("/dev/fuse", fuse->dest_path, "fuse", MS_NOSUID | MS_NODEV | MS_NOEXEC | + MS_NOATIME, opts) != 0) { + ERROR("failed to mount fuse filesystem: %s\n", strerror(errno)); + return -1; + } } fuse->gid = gid; @@ -1803,7 +1819,7 @@ static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask) { } static void run(const char* source_path, const char* label, uid_t uid, - gid_t gid, userid_t userid, bool multi_user, bool full_write) { + gid_t gid, userid_t userid, bool multi_user, bool full_write, bool use_sdcardfs) { struct fuse_global global; struct fuse fuse_default; struct fuse fuse_read; @@ -1875,9 +1891,9 @@ static void run(const char* source_path, const char* label, uid_t uid, if (multi_user) { /* Multi-user storage is fully isolated per user, so "other" * permissions are completely masked off. */ - if (fuse_setup(&fuse_default, AID_SDCARD_RW, 0006) - || fuse_setup(&fuse_read, AID_EVERYBODY, 0027) - || fuse_setup(&fuse_write, AID_EVERYBODY, full_write ? 0007 : 0027)) { + if (fuse_setup(&fuse_default, AID_SDCARD_RW, 0006, use_sdcardfs) + || fuse_setup(&fuse_read, AID_EVERYBODY, 0027, use_sdcardfs) + || fuse_setup(&fuse_write, AID_EVERYBODY, full_write ? 0007 : 0027, use_sdcardfs)) { ERROR("failed to fuse_setup\n"); exit(1); } @@ -1885,14 +1901,19 @@ static void run(const char* source_path, const char* label, uid_t uid, /* Physical storage is readable by all users on device, but * the Android directories are masked off to a single user * deep inside attr_from_stat(). */ - if (fuse_setup(&fuse_default, AID_SDCARD_RW, 0006) - || fuse_setup(&fuse_read, AID_EVERYBODY, full_write ? 0027 : 0022) - || fuse_setup(&fuse_write, AID_EVERYBODY, full_write ? 0007 : 0022)) { + if (fuse_setup(&fuse_default, AID_SDCARD_RW, 0006, use_sdcardfs) + || fuse_setup(&fuse_read, AID_EVERYBODY, full_write ? 0027 : 0022, use_sdcardfs) + || fuse_setup(&fuse_write, AID_EVERYBODY, full_write ? 0007 : 0022, use_sdcardfs)) { ERROR("failed to fuse_setup\n"); exit(1); } } + // Nothing else for us to do if sdcardfs is in use! + if (use_sdcardfs) { + exit(0); + } + /* Drop privs */ if (setgroups(sizeof(kGroups) / sizeof(kGroups[0]), kGroups) < 0) { ERROR("cannot setgroups: %s\n", strerror(errno)); @@ -1995,6 +2016,8 @@ int sdcard_main(int argc, char **argv) { sleep(1); } - run(source_path, label, uid, gid, userid, multi_user, full_write); + bool use_sdcardfs = property_get_bool("ro.sdcardfs.enable", false); + + run(source_path, label, uid, gid, userid, multi_user, full_write, use_sdcardfs); return 1; } -- cgit v1.1 From 7f9b2ce419e8d9abfff61bca852c5cb652ee2361 Mon Sep 17 00:00:00 2001 From: Zhao Wei Liew Date: Sun, 24 Jul 2016 15:45:31 +0800 Subject: sdcard: Fix sdcardFS check This check is inverted, breaking FUSE. Change-Id: I81a710f464bce73f49fb1af6050a198b5f443f52 --- sdcard/sdcard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index c0f60ed..5309bbd 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -1780,7 +1780,7 @@ static int usage() { static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask, bool use_sdcardfs) { char opts[256]; - if (use_sdcardfs) { + if (!use_sdcardfs) { fuse->fd = open("/dev/fuse", O_RDWR); if (fuse->fd == -1) { ERROR("failed to open fuse device: %s\n", strerror(errno)); -- cgit v1.1 From 1576854573b0ee5525f4a3476d0f58d2f45eeae1 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Tue, 26 Jul 2016 03:03:06 -0700 Subject: sdcard: Pass the umask to sdcardfs correctly * Google version of the kernel code expects unsigned int rather than octal. Don't confuse it. Change-Id: I40f060dc5212ec587e612dc275001e1a660cce67 --- sdcard/sdcard.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index 5309bbd..227982c 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -1792,7 +1792,7 @@ static int fuse_setup(struct fuse* fuse, gid_t gid, mode_t mask, bool use_sdcard if (use_sdcardfs) { snprintf(opts, sizeof(opts), - "%sfsuid=%d,fsgid=%d,userid=%d,gid=%d,mask=%04o,reserved_mb=20", + "%sfsuid=%u,fsgid=%u,userid=%d,gid=%u,mask=%u,reserved_mb=20", (fuse->global->multi_user ? "multiuser," : ""), fuse->global->uid, fuse->global->gid, fuse->global->root.userid, gid, mask); @@ -1909,11 +1909,6 @@ static void run(const char* source_path, const char* label, uid_t uid, } } - // Nothing else for us to do if sdcardfs is in use! - if (use_sdcardfs) { - exit(0); - } - /* Drop privs */ if (setgroups(sizeof(kGroups) / sizeof(kGroups[0]), kGroups) < 0) { ERROR("cannot setgroups: %s\n", strerror(errno)); @@ -1932,6 +1927,11 @@ static void run(const char* source_path, const char* label, uid_t uid, fs_prepare_dir(global.obb_path, 0775, uid, gid); } + // Nothing else for us to do if sdcardfs is in use! + if (use_sdcardfs) { + exit(0); + } + if (pthread_create(&thread_default, NULL, start_handler, &handler_default) || pthread_create(&thread_read, NULL, start_handler, &handler_read) || pthread_create(&thread_write, NULL, start_handler, &handler_write)) { -- cgit v1.1 From 4123d86b8059d13c888702e58351469c5d176ecf Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Thu, 28 Jul 2016 12:17:40 -0700 Subject: healthd: Add DASH charger type Change-Id: Ie1ca5018c465f6b2c15cbc00bdf3bb866d98ddef --- healthd/BatteryMonitor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp index a59c779..86a4fc6 100644 --- a/healthd/BatteryMonitor.cpp +++ b/healthd/BatteryMonitor.cpp @@ -147,6 +147,7 @@ BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String { "Wipower", ANDROID_POWER_SUPPLY_TYPE_WIRELESS }, { "DockBattery", ANDROID_POWER_SUPPLY_TYPE_DOCK_BATTERY }, { "DockAC", ANDROID_POWER_SUPPLY_TYPE_DOCK_AC }, + { "DASH", ANDROID_POWER_SUPPLY_TYPE_AC }, { NULL, 0 }, }; -- cgit v1.1 From 4cc6d3d4057ef566a87a2e1db2c4c152b52e0765 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Tue, 9 Aug 2016 15:29:58 -0700 Subject: debuggerd: fix missed use of ptrace(PTRACE_ATTACH). Bug: http://b/29555636 Change-Id: Ibd8a2e2b619b74aac667555b7085d6f28e367c07 --- debuggerd/tombstone.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp index aeffc66..d04b721 100644 --- a/debuggerd/tombstone.cpp +++ b/debuggerd/tombstone.cpp @@ -447,7 +447,7 @@ static bool dump_sibling_thread_report( } // Skip this thread if cannot ptrace it - if (ptrace(PTRACE_ATTACH, new_tid, 0, 0) < 0) { + if (!ptrace_attach_thread(pid, new_tid)) { _LOG(log, logtype::ERROR, "ptrace attach to %d failed: %s\n", new_tid, strerror(errno)); continue; } -- cgit v1.1 From f2059d3fd959ce6f0d8a106ad4483c733aab3f66 Mon Sep 17 00:00:00 2001 From: Sergio Giro Date: Tue, 28 Jun 2016 18:02:29 +0100 Subject: libutils/Unicode.cpp: Correct length computation and add checks for utf16->utf8 Inconsistent behaviour between utf16_to_utf8 and utf16_to_utf8_length is causing a heap overflow. Correcting the length computation and adding bound checks to the conversion functions. Test: ran libutils_tests Bug: 29250543 Change-Id: I6115e3357141ed245c63c6eb25fc0fd0a9a7a2bb (cherry picked from commit c4966a363e46d2e1074d1a365e232af0dcedd6a1) --- include/utils/Unicode.h | 4 ++-- libutils/String8.cpp | 25 +++++++++++++------------ libutils/Unicode.cpp | 15 +++++++++++---- libutils/tests/String8_test.cpp | 19 +++++++++++++++++++ 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/include/utils/Unicode.h b/include/utils/Unicode.h index b76a5e2..4e17cc3 100644 --- a/include/utils/Unicode.h +++ b/include/utils/Unicode.h @@ -87,7 +87,7 @@ ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len); * "dst" becomes \xE3\x81\x82\xE3\x81\x84 * (note that "dst" is NOT null-terminated, like strncpy) */ -void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst); +void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len); /** * Returns the unicode value at "index". @@ -109,7 +109,7 @@ ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len); * enough to fit the UTF-16 as measured by utf16_to_utf8_length with an added * NULL terminator. */ -void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst); +void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len); /** * Returns the length of "src" when "src" is valid UTF-8 string. diff --git a/libutils/String8.cpp b/libutils/String8.cpp index ad65fdb..75dfa29 100644 --- a/libutils/String8.cpp +++ b/libutils/String8.cpp @@ -102,20 +102,21 @@ static char* allocFromUTF16(const char16_t* in, size_t len) { if (len == 0) return getEmptyString(); - const ssize_t bytes = utf16_to_utf8_length(in, len); - if (bytes < 0) { + // Allow for closing '\0' + const ssize_t resultStrLen = utf16_to_utf8_length(in, len) + 1; + if (resultStrLen < 1) { return getEmptyString(); } - SharedBuffer* buf = SharedBuffer::alloc(bytes+1); + SharedBuffer* buf = SharedBuffer::alloc(resultStrLen); ALOG_ASSERT(buf, "Unable to allocate shared buffer"); if (!buf) { return getEmptyString(); } - char* str = (char*)buf->data(); - utf16_to_utf8(in, len, str); - return str; + char* resultStr = (char*)buf->data(); + utf16_to_utf8(in, len, resultStr, resultStrLen); + return resultStr; } static char* allocFromUTF32(const char32_t* in, size_t len) @@ -124,21 +125,21 @@ static char* allocFromUTF32(const char32_t* in, size_t len) return getEmptyString(); } - const ssize_t bytes = utf32_to_utf8_length(in, len); - if (bytes < 0) { + const ssize_t resultStrLen = utf32_to_utf8_length(in, len) + 1; + if (resultStrLen < 1) { return getEmptyString(); } - SharedBuffer* buf = SharedBuffer::alloc(bytes+1); + SharedBuffer* buf = SharedBuffer::alloc(resultStrLen); ALOG_ASSERT(buf, "Unable to allocate shared buffer"); if (!buf) { return getEmptyString(); } - char* str = (char*) buf->data(); - utf32_to_utf8(in, len, str); + char* resultStr = (char*) buf->data(); + utf32_to_utf8(in, len, resultStr, resultStrLen); - return str; + return resultStr; } // --------------------------------------------------------------------------- diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp index fb876c9..2b5293e 100644 --- a/libutils/Unicode.cpp +++ b/libutils/Unicode.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include @@ -182,7 +183,7 @@ ssize_t utf32_to_utf8_length(const char32_t *src, size_t src_len) return ret; } -void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst) +void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst, size_t dst_len) { if (src == NULL || src_len == 0 || dst == NULL) { return; @@ -193,9 +194,12 @@ void utf32_to_utf8(const char32_t* src, size_t src_len, char* dst) char *cur = dst; while (cur_utf32 < end_utf32) { size_t len = utf32_codepoint_utf8_length(*cur_utf32); + LOG_ALWAYS_FATAL_IF(dst_len < len, "%zu < %zu", dst_len, len); utf32_codepoint_to_utf8((uint8_t *)cur, *cur_utf32++, len); cur += len; + dst_len -= len; } + LOG_ALWAYS_FATAL_IF(dst_len < 1, "dst_len < 1: %zu < 1", dst_len); *cur = '\0'; } @@ -324,7 +328,7 @@ int strzcmp16_h_n(const char16_t *s1H, size_t n1, const char16_t *s2N, size_t n2 : 0); } -void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst) +void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst, size_t dst_len) { if (src == NULL || src_len == 0 || dst == NULL) { return; @@ -345,9 +349,12 @@ void utf16_to_utf8(const char16_t* src, size_t src_len, char* dst) utf32 = (char32_t) *cur_utf16++; } const size_t len = utf32_codepoint_utf8_length(utf32); + LOG_ALWAYS_FATAL_IF(dst_len < len, "%zu < %zu", dst_len, len); utf32_codepoint_to_utf8((uint8_t*)cur, utf32, len); cur += len; + dst_len -= len; } + LOG_ALWAYS_FATAL_IF(dst_len < 1, "%zu < 1", dst_len); *cur = '\0'; } @@ -408,10 +415,10 @@ ssize_t utf16_to_utf8_length(const char16_t *src, size_t src_len) const char16_t* const end = src + src_len; while (src < end) { if ((*src & 0xFC00) == 0xD800 && (src + 1) < end - && (*++src & 0xFC00) == 0xDC00) { + && (*(src + 1) & 0xFC00) == 0xDC00) { // surrogate pairs are always 4 bytes. ret += 4; - src++; + src += 2; } else { ret += utf32_codepoint_utf8_length((char32_t) *src++); } diff --git a/libutils/tests/String8_test.cpp b/libutils/tests/String8_test.cpp index c42c68d..7cd67d3 100644 --- a/libutils/tests/String8_test.cpp +++ b/libutils/tests/String8_test.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "String8_test" #include #include +#include #include @@ -72,4 +73,22 @@ TEST_F(String8Test, OperatorPlusEquals) { EXPECT_STREQ(src3, " Verify me."); } +// http://b/29250543 +TEST_F(String8Test, CorrectInvalidSurrogate) { + // d841d8 is an invalid start for a surrogate pair. Make sure this is handled by ignoring the + // first character in the pair and handling the rest correctly. + String16 string16(u"\xd841\xd841\xdc41\x0000"); + String8 string8(string16); + + EXPECT_EQ(4U, string8.length()); +} + +TEST_F(String8Test, CheckUtf32Conversion) { + // Since bound checks were added, check the conversion can be done without fatal errors. + // The utf8 lengths of these are chars are 1 + 2 + 3 + 4 = 10. + const char32_t string32[] = U"\x0000007f\x000007ff\x0000911\x0010fffe"; + String8 string8(string32); + EXPECT_EQ(10U, string8.length()); +} + } -- cgit v1.1 From 11440395e379f35069e8e39a6e3ccfa7a7bfc72f Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Tue, 17 May 2016 19:23:39 -0700 Subject: adb: switch the socket list mutex to a recursive_mutex. sockets.cpp was branching on whether a socket close function was local_socket_close in order to avoid a potential deadlock if the socket list lock was held while closing a peer socket. Bug: http://b/28347842 Change-Id: I5e56f17fa54275284787f0f1dc150d1960256ab3 (functionally a cherrypick of 903b749f + 9b587dec, with windows disabled) --- adb/Android.mk | 3 ++ adb/mutex_list.h | 1 - adb/sockets.cpp | 78 +++++++++++++--------------- adb/sysdeps/mutex.h | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+), 45 deletions(-) create mode 100644 adb/sysdeps/mutex.h diff --git a/adb/Android.mk b/adb/Android.mk index 425bf9b..d4adbfb 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -200,7 +200,10 @@ endif # will violate ODR LOCAL_SHARED_LIBRARIES := +# Don't build the host adb on Windows (this branch should only be used for security updates.) +ifneq ($(HOST_OS),windows) include $(BUILD_HOST_EXECUTABLE) +endif $(call dist-for-goals,dist_files sdk,$(LOCAL_BUILT_MODULE)) diff --git a/adb/mutex_list.h b/adb/mutex_list.h index ff72751..15e383c 100644 --- a/adb/mutex_list.h +++ b/adb/mutex_list.h @@ -6,7 +6,6 @@ #ifndef ADB_MUTEX #error ADB_MUTEX not defined when including this file #endif -ADB_MUTEX(socket_list_lock) ADB_MUTEX(transport_lock) #if ADB_HOST ADB_MUTEX(local_transports_lock) diff --git a/adb/sockets.cpp b/adb/sockets.cpp index 32ca17d..31b5443 100644 --- a/adb/sockets.cpp +++ b/adb/sockets.cpp @@ -25,18 +25,27 @@ #include #include +#include +#include +#include +#include + #if !ADB_HOST #include "cutils/properties.h" #endif #include "adb.h" #include "adb_io.h" +#include "sysdeps/mutex.h" #include "transport.h" -ADB_MUTEX_DEFINE( socket_list_lock ); +#if !defined(__BIONIC__) +using std::recursive_mutex; +#endif -static void local_socket_close_locked(asocket *s); +static void local_socket_close(asocket* s); +static recursive_mutex& local_socket_list_lock = *new recursive_mutex(); static unsigned local_socket_next_id = 1; static asocket local_socket_list = { @@ -61,7 +70,7 @@ asocket *find_local_socket(unsigned local_id, unsigned peer_id) asocket *s; asocket *result = NULL; - adb_mutex_lock(&socket_list_lock); + std::lock_guard lock(local_socket_list_lock); for (s = local_socket_list.next; s != &local_socket_list; s = s->next) { if (s->id != local_id) continue; @@ -70,7 +79,6 @@ asocket *find_local_socket(unsigned local_id, unsigned peer_id) } break; } - adb_mutex_unlock(&socket_list_lock); return result; } @@ -84,20 +92,17 @@ insert_local_socket(asocket* s, asocket* list) s->next->prev = s; } - -void install_local_socket(asocket *s) -{ - adb_mutex_lock(&socket_list_lock); +void install_local_socket(asocket* s) { + std::lock_guard lock(local_socket_list_lock); s->id = local_socket_next_id++; // Socket ids should never be 0. - if (local_socket_next_id == 0) - local_socket_next_id = 1; + if (local_socket_next_id == 0) { + fatal("local socket id overflow"); + } insert_local_socket(s, &local_socket_list); - - adb_mutex_unlock(&socket_list_lock); } void remove_socket(asocket *s) @@ -116,19 +121,17 @@ void remove_socket(asocket *s) void close_all_sockets(atransport *t) { asocket *s; - - /* this is a little gross, but since s->close() *will* modify - ** the list out from under you, your options are limited. - */ - adb_mutex_lock(&socket_list_lock); + /* this is a little gross, but since s->close() *will* modify + ** the list out from under you, your options are limited. + */ + std::lock_guard lock(local_socket_list_lock); restart: - for(s = local_socket_list.next; s != &local_socket_list; s = s->next){ - if(s->transport == t || (s->peer && s->peer->transport == t)) { - local_socket_close_locked(s); + for (s = local_socket_list.next; s != &local_socket_list; s = s->next) { + if (s->transport == t || (s->peer && s->peer->transport == t)) { + local_socket_close(s); goto restart; } } - adb_mutex_unlock(&socket_list_lock); } static int local_socket_enqueue(asocket *s, apacket *p) @@ -191,13 +194,6 @@ static void local_socket_ready(asocket *s) fdevent_add(&s->fde, FDE_READ); } -static void local_socket_close(asocket *s) -{ - adb_mutex_lock(&socket_list_lock); - local_socket_close_locked(s); - adb_mutex_unlock(&socket_list_lock); -} - // be sure to hold the socket list lock when calling this static void local_socket_destroy(asocket *s) { @@ -226,27 +222,21 @@ static void local_socket_destroy(asocket *s) } } - -static void local_socket_close_locked(asocket *s) -{ - D("entered local_socket_close_locked. LS(%d) fd=%d\n", s->id, s->fd); - if(s->peer) { - D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n", - s->id, s->peer->id, s->peer->fd); +static void local_socket_close(asocket* s) { + D("entered local_socket_close. LS(%d) fd=%d", s->id, s->fd); + std::lock_guard lock(local_socket_list_lock); + if (s->peer) { + D("LS(%d): closing peer. peer->id=%d peer->fd=%d", s->id, s->peer->id, s->peer->fd); /* Note: it's important to call shutdown before disconnecting from * the peer, this ensures that remote sockets can still get the id * of the local socket they're connected to, to send a CLOSE() * protocol event. */ - if (s->peer->shutdown) - s->peer->shutdown(s->peer); - s->peer->peer = 0; - // tweak to avoid deadlock - if (s->peer->close == local_socket_close) { - local_socket_close_locked(s->peer); - } else { - s->peer->close(s->peer); + if (s->peer->shutdown) { + s->peer->shutdown(s->peer); } - s->peer = 0; + s->peer->peer = nullptr; + s->peer->close(s->peer); + s->peer = nullptr; } /* If we are already closing, or if there are no diff --git a/adb/sysdeps/mutex.h b/adb/sysdeps/mutex.h new file mode 100644 index 0000000..ef5d9b1 --- /dev/null +++ b/adb/sysdeps/mutex.h @@ -0,0 +1,143 @@ +#pragma once + +/* + * Copyright (C) 2016 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. + */ + +#if defined(_WIN32) + +#include + +#include + +#include "adb.h" + +// The prebuilt version of mingw we use doesn't support mutex or recursive_mutex. +// Therefore, implement our own using the Windows primitives. +// Put them directly into the std namespace, so that when they're actually available, the build +// breaks until they're removed. + +#include +namespace std { + +// CRITICAL_SECTION is recursive, so just wrap it in a Mutex-compatible class. +class recursive_mutex { + public: + recursive_mutex() { + InitializeCriticalSection(&mutex_); + } + + ~recursive_mutex() { + DeleteCriticalSection(&mutex_); + } + + void lock() { + EnterCriticalSection(&mutex_); + } + + bool try_lock() { + return TryEnterCriticalSection(&mutex_); + } + + void unlock() { + LeaveCriticalSection(&mutex_); + } + + private: + CRITICAL_SECTION mutex_; + + DISALLOW_COPY_AND_ASSIGN(recursive_mutex); +}; + +class mutex { + public: + mutex() { + } + + ~mutex() { + } + + void lock() { + mutex_.lock(); + if (++lock_count_ != 1) { + fatal("non-recursive mutex locked reentrantly"); + } + } + + void unlock() { + if (--lock_count_ != 0) { + fatal("non-recursive mutex unlock resulted in unexpected lock count: %d", lock_count_); + } + mutex_.unlock(); + } + + bool try_lock() { + if (!mutex_.try_lock()) { + return false; + } + + if (lock_count_ != 0) { + mutex_.unlock(); + return false; + } + + ++lock_count_; + return true; + } + + private: + recursive_mutex mutex_; + size_t lock_count_ = 0; +}; + +} + +#elif defined(__BIONIC__) + +// On M, the recovery image uses parts of adb that depends on recursive_mutex, and uses libstdc++, +// which lacks it. + +#include +#include + +#include + +class recursive_mutex { + public: + recursive_mutex() { + } + + ~recursive_mutex() { + } + + void lock() { + pthread_mutex_lock(&mutex_); + } + + bool try_lock() { + return pthread_mutex_trylock(&mutex_); + } + + void unlock() { + pthread_mutex_unlock(&mutex_); + } + + private: + pthread_mutex_t mutex_ = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + + DISALLOW_COPY_AND_ASSIGN(recursive_mutex); +}; + +#endif -- cgit v1.1 From 3b268646f802d72f9b53800ac00540201223cf2e Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Wed, 18 May 2016 10:39:48 -0700 Subject: adb: use asocket's close function when closing. close_all_sockets was assuming that all registered local sockets used local_socket_close as their close function. However, this is not true for JDWP sockets. Bug: http://b/28347842 Change-Id: I40a1174845cd33f15f30ce70828a7081cd5a087e (cherry picked from commit 53eb31d87cb84a4212f4850bf745646e1fb12814) (cherry picked from commit 014b01706cc64dc9c2ad94a96f62e07c058d0b5d) --- adb/sockets.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/adb/sockets.cpp b/adb/sockets.cpp index 31b5443..3919147 100644 --- a/adb/sockets.cpp +++ b/adb/sockets.cpp @@ -43,8 +43,6 @@ using std::recursive_mutex; #endif -static void local_socket_close(asocket* s); - static recursive_mutex& local_socket_list_lock = *new recursive_mutex(); static unsigned local_socket_next_id = 1; @@ -128,7 +126,7 @@ void close_all_sockets(atransport *t) restart: for (s = local_socket_list.next; s != &local_socket_list; s = s->next) { if (s->transport == t || (s->peer && s->peer->transport == t)) { - local_socket_close(s); + s->close(s); goto restart; } } -- cgit v1.1 From d2d95688f81fcce492b46b8e260bdf4f6e0b679b Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Thu, 14 Jul 2016 16:43:12 -0700 Subject: DO NOT MERGE: debuggerd: verify that traced threads belong to the right process. Fix two races in debuggerd's PTRACE_ATTACH logic: 1. The target thread in a crash dump request could exit between the /proc//task/ check and the PTRACE_ATTACH. 2. Sibling threads could exit between listing /proc//task and the PTRACE_ATTACH. Backport of NYC change I4dfe1ea30e2c211d2389321bd66e3684dd757591 Bug: http://b/29555636 Change-Id: I6c6efcf82a49bca140d761b2d1de04215ba4d252 --- debuggerd/backtrace.cpp | 10 +++++----- debuggerd/debuggerd.cpp | 33 +++++++++++++++++++++++++++------ debuggerd/utility.cpp | 29 +++++++++++++++++++++++++++++ debuggerd/utility.h | 5 +++++ 4 files changed, 66 insertions(+), 11 deletions(-) diff --git a/debuggerd/backtrace.cpp b/debuggerd/backtrace.cpp index b8084c5..ad6a6ee 100644 --- a/debuggerd/backtrace.cpp +++ b/debuggerd/backtrace.cpp @@ -67,8 +67,8 @@ static void dump_process_footer(log_t* log, pid_t pid) { _LOG(log, logtype::BACKTRACE, "\n----- end %d -----\n", pid); } -static void dump_thread( - log_t* log, pid_t tid, bool attached, bool* detach_failed, int* total_sleep_time_usec) { +static void dump_thread(log_t* log, pid_t pid, pid_t tid, bool attached, + bool* detach_failed, int* total_sleep_time_usec) { char path[PATH_MAX]; char threadnamebuf[1024]; char* threadname = NULL; @@ -88,7 +88,7 @@ static void dump_thread( _LOG(log, logtype::BACKTRACE, "\n\"%s\" sysTid=%d\n", threadname ? threadname : "", tid); - if (!attached && ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) { + if (!attached && !ptrace_attach_thread(pid, tid)) { _LOG(log, logtype::BACKTRACE, "Could not attach to thread: %s\n", strerror(errno)); return; } @@ -117,7 +117,7 @@ void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, log.amfd = amfd; dump_process_header(&log, pid); - dump_thread(&log, tid, true, detach_failed, total_sleep_time_usec); + dump_thread(&log, pid, tid, true, detach_failed, total_sleep_time_usec); char task_path[64]; snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); @@ -135,7 +135,7 @@ void dump_backtrace(int fd, int amfd, pid_t pid, pid_t tid, bool* detach_failed, continue; } - dump_thread(&log, new_tid, false, detach_failed, total_sleep_time_usec); + dump_thread(&log, pid, new_tid, false, detach_failed, total_sleep_time_usec); } closedir(d); } diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 9c8a41e..2ab716d 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -225,12 +225,10 @@ static int read_request(int fd, debugger_request_t* out_request) { if (msg.action == DEBUGGER_ACTION_CRASH) { // Ensure that the tid reported by the crashing process is valid. - char buf[64]; - struct stat s; - snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid); - if (stat(buf, &s)) { + // This check needs to happen again after ptracing the requested thread to prevent a race. + if (!pid_contains_tid(out_request->pid, out_request->tid)) { ALOGE("tid %d does not exist in pid %d. ignoring debug request\n", - out_request->tid, out_request->pid); + out_request->tid, out_request->pid); return -1; } } else if (cr.uid == 0 @@ -380,9 +378,32 @@ static void handle_request(int fd) { // ensure that it can run as soon as we call PTRACE_CONT below. // See details in bionic/libc/linker/debugger.c, in function // debugger_signal_handler(). - if (ptrace(PTRACE_ATTACH, request.tid, 0, 0)) { + if (!ptrace_attach_thread(request.pid, request.tid)) { ALOGE("ptrace attach failed: %s\n", strerror(errno)); } else { + // DEBUGGER_ACTION_CRASH requests can come from arbitrary processes and the tid field in + // the request is sent from the other side. If an attacker can cause a process to be + // spawned with the pid of their process, they could trick debuggerd into dumping that + // process by exiting after sending the request. Validate the trusted request.uid/gid + // to defend against this. + if (request.action == DEBUGGER_ACTION_CRASH) { + pid_t pid; + uid_t uid; + gid_t gid; + if (get_process_info(request.tid, &pid, &uid, &gid) != 0) { + ALOGE("debuggerd: failed to get process info for tid '%d'", request.tid); + exit(1); + } + + if (pid != request.pid || uid != request.uid || gid != request.gid) { + ALOGE( + "debuggerd: attached task %d does not match request: " + "expected pid=%d,uid=%d,gid=%d, actual pid=%d,uid=%d,gid=%d", + request.tid, request.pid, request.uid, request.gid, pid, uid, gid); + exit(1); + } + } + bool detach_failed = false; bool tid_unresponsive = false; bool attach_gdb = should_attach_gdb(&request); diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp index 9f340a8..236d667 100644 --- a/debuggerd/utility.cpp +++ b/debuggerd/utility.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -207,3 +208,31 @@ void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* f _LOG(log, logtype::MEMORY, "%s %s\n", logline.c_str(), ascii.c_str()); } } + +bool pid_contains_tid(pid_t pid, pid_t tid) { + char task_path[PATH_MAX]; + if (snprintf(task_path, PATH_MAX, "/proc/%d/task/%d", pid, tid) >= PATH_MAX) { + ALOGE("debuggerd: task path overflow (pid = %d, tid = %d)\n", pid, tid); + exit(1); + } + + return access(task_path, F_OK) == 0; +} + +// Attach to a thread, and verify that it's still a member of the given process +bool ptrace_attach_thread(pid_t pid, pid_t tid) { + if (ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) { + return false; + } + + // Make sure that the task we attached to is actually part of the pid we're dumping. + if (!pid_contains_tid(pid, tid)) { + if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) { + ALOGE("debuggerd: failed to detach from thread '%d'", tid); + exit(1); + } + return false; + } + + return true; +} diff --git a/debuggerd/utility.h b/debuggerd/utility.h index 263374d..e8ec7ef 100644 --- a/debuggerd/utility.h +++ b/debuggerd/utility.h @@ -79,4 +79,9 @@ int wait_for_sigstop(pid_t, int*, bool*); void dump_memory(log_t* log, Backtrace* backtrace, uintptr_t addr, const char* fmt, ...); +bool pid_contains_tid(pid_t pid, pid_t tid); + +// Attach to a thread, and verify that it's still a member of the given process +bool ptrace_attach_thread(pid_t pid, pid_t tid); + #endif // _DEBUGGERD_UTILITY_H -- cgit v1.1 From e86d0e14970166fa38f16187260679431cdd4119 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Tue, 9 Aug 2016 15:29:58 -0700 Subject: debuggerd: fix missed use of ptrace(PTRACE_ATTACH). Bug: http://b/29555636 Change-Id: Ibd8a2e2b619b74aac667555b7085d6f28e367c07 --- debuggerd/tombstone.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp index aeffc66..d04b721 100644 --- a/debuggerd/tombstone.cpp +++ b/debuggerd/tombstone.cpp @@ -447,7 +447,7 @@ static bool dump_sibling_thread_report( } // Skip this thread if cannot ptrace it - if (ptrace(PTRACE_ATTACH, new_tid, 0, 0) < 0) { + if (!ptrace_attach_thread(pid, new_tid)) { _LOG(log, logtype::ERROR, "ptrace attach to %d failed: %s\n", new_tid, strerror(errno)); continue; } -- cgit v1.1 From b825f1148cc78fa853da964de2e7e2de1b3b03b2 Mon Sep 17 00:00:00 2001 From: Connor O'Brien Date: Fri, 12 Aug 2016 11:52:46 -0700 Subject: Fix vold vulnerability in FrameworkListener Modify FrameworkListener to ignore commands that exceed the maximum buffer length and send an error message. Bug: 29831647 Change-Id: I9e57d1648d55af2ca0191bb47868e375ecc26950 Signed-off-by: Connor O'Brien (cherry picked from commit baa126dc158a40bc83c17c6d428c760e5b93fb1a) (cherry picked from commit 470484d2a25ad432190a01d1c763b4b36db33c7e) --- include/sysutils/FrameworkListener.h | 1 + libsysutils/src/FrameworkListener.cpp | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h index 18049cd..2137069 100644 --- a/include/sysutils/FrameworkListener.h +++ b/include/sysutils/FrameworkListener.h @@ -32,6 +32,7 @@ private: int mCommandCount; bool mWithSeq; FrameworkCommandCollection *mCommands; + bool mSkipToNextNullByte; public: FrameworkListener(const char *socketName); diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index e7b3dd6..579ead9 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -49,6 +49,7 @@ void FrameworkListener::init(const char *socketName UNUSED, bool withSeq) { errorRate = 0; mCommandCount = 0; mWithSeq = withSeq; + mSkipToNextNullByte = false; } bool FrameworkListener::onDataAvailable(SocketClient *c) { @@ -59,10 +60,15 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { if (len < 0) { SLOGE("read() failed (%s)", strerror(errno)); return false; - } else if (!len) + } else if (!len) { return false; - if(buffer[len-1] != '\0') + } else if (buffer[len-1] != '\0') { SLOGW("String is not zero-terminated"); + android_errorWriteLog(0x534e4554, "29831647"); + c->sendMsg(500, "Command too large for buffer", false); + mSkipToNextNullByte = true; + return false; + } int offset = 0; int i; @@ -70,11 +76,16 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { for (i = 0; i < len; i++) { if (buffer[i] == '\0') { /* IMPORTANT: dispatchCommand() expects a zero-terminated string */ - dispatchCommand(c, buffer + offset); + if (mSkipToNextNullByte) { + mSkipToNextNullByte = false; + } else { + dispatchCommand(c, buffer + offset); + } offset = i + 1; } } + mSkipToNextNullByte = false; return true; } -- cgit v1.1 From e30579f3359eba93019171861f32bbf4c72313d1 Mon Sep 17 00:00:00 2001 From: Connor O'Brien Date: Fri, 12 Aug 2016 11:52:46 -0700 Subject: Fix vold vulnerability in FrameworkListener Modify FrameworkListener to ignore commands that exceed the maximum buffer length and send an error message. Bug: 29831647 Change-Id: I9e57d1648d55af2ca0191bb47868e375ecc26950 Signed-off-by: Connor O'Brien (cherry picked from commit baa126dc158a40bc83c17c6d428c760e5b93fb1a) (cherry picked from commit 470484d2a25ad432190a01d1c763b4b36db33c7e) --- include/sysutils/FrameworkListener.h | 1 + libsysutils/src/FrameworkListener.cpp | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h index 18049cd..2137069 100644 --- a/include/sysutils/FrameworkListener.h +++ b/include/sysutils/FrameworkListener.h @@ -32,6 +32,7 @@ private: int mCommandCount; bool mWithSeq; FrameworkCommandCollection *mCommands; + bool mSkipToNextNullByte; public: FrameworkListener(const char *socketName); diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index e7b3dd6..579ead9 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -49,6 +49,7 @@ void FrameworkListener::init(const char *socketName UNUSED, bool withSeq) { errorRate = 0; mCommandCount = 0; mWithSeq = withSeq; + mSkipToNextNullByte = false; } bool FrameworkListener::onDataAvailable(SocketClient *c) { @@ -59,10 +60,15 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { if (len < 0) { SLOGE("read() failed (%s)", strerror(errno)); return false; - } else if (!len) + } else if (!len) { return false; - if(buffer[len-1] != '\0') + } else if (buffer[len-1] != '\0') { SLOGW("String is not zero-terminated"); + android_errorWriteLog(0x534e4554, "29831647"); + c->sendMsg(500, "Command too large for buffer", false); + mSkipToNextNullByte = true; + return false; + } int offset = 0; int i; @@ -70,11 +76,16 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { for (i = 0; i < len; i++) { if (buffer[i] == '\0') { /* IMPORTANT: dispatchCommand() expects a zero-terminated string */ - dispatchCommand(c, buffer + offset); + if (mSkipToNextNullByte) { + mSkipToNextNullByte = false; + } else { + dispatchCommand(c, buffer + offset); + } offset = i + 1; } } + mSkipToNextNullByte = false; return true; } -- cgit v1.1 From c00328f99aad5f1e8e879557f142981f08146fe3 Mon Sep 17 00:00:00 2001 From: Scott Mertz Date: Mon, 29 Aug 2016 11:32:32 -0700 Subject: libutils: fix deadlock in elapsedRealtimeNano If n > 2 threads all lock the mutex awaiting the clock method to be set, the 1st thread will first set the method and unlock. The 2nd thread will then take the mutex, but never unlock because the clock_method has already been updated by the 1st thread. This causes a deadlock for threads 3-n. Solution is to ensure the calling thread always unlocks the mutex if it has previously locked it. Log: "main" prio=5 tid=1 Native | group="main" sCount=1 dsCount=0 obj=0x733313b0 self=0xb4cf6500 | sysTid=12786 nice=0 cgrp=default sched=0/0 handle=0xb6f86b44 | state=S schedstat=( 41990410 32985836 80 ) utm=3 stm=1 core=2 HZ=100 | stack=0xbe5fb000-0xbe5fd000 stackSize=8MB | held mutexes= native: #00 pc 00017638 /system/lib/libc.so (syscall+28) native: #01 pc 0003ffa5 /system/lib/libc.so (_ZL33__pthread_mutex_lock_with_timeoutP24pthread_mutex_internal_tPK8timespeci+504) native: #02 pc 000400a9 /system/lib/libc.so (pthread_mutex_lock+26) native: #03 pc 0000fa01 /system/lib/libutils.so (_ZN7android19elapsedRealtimeNanoEv+16) native: #04 pc 0000fb1f /system/lib/libutils.so (_ZN7android15elapsedRealtimeEv+2) native: #05 pc 00214d1d /data/dalvik-cache/arm/system@framework@boot.oat (Java_android_os_SystemClock_elapsedRealtime__+72) "Thread-6372" prio=5 tid=9 Native | group="main" sCount=1 dsCount=0 obj=0x32c05120 self=0xacb58100 | sysTid=12829 nice=10 cgrp=bg_non_interactive sched=0/0 handle=0xb38c3930 | state=S schedstat=( 869427 8219115 17 ) utm=0 stm=0 core=2 HZ=100 | stack=0xb37c1000-0xb37c3000 stackSize=1038KB | held mutexes= native: #00 pc 00017638 /system/lib/libc.so (syscall+28) native: #01 pc 0003ffa5 /system/lib/libc.so (_ZL33__pthread_mutex_lock_with_timeoutP24pthread_mutex_internal_tPK8timespeci+504) native: #02 pc 000400a9 /system/lib/libc.so (pthread_mutex_lock+26) native: #03 pc 0000fa01 /system/lib/libutils.so (_ZN7android19elapsedRealtimeNanoEv+16) native: #04 pc 0000fb1f /system/lib/libutils.so (_ZN7android15elapsedRealtimeEv+2) native: #05 pc 00214d1d /data/dalvik-cache/arm/system@framework@boot.oat (Java_android_os_SystemClock_elapsedRealtime__+72) HAM-1470 Change-Id: I41874d2b0ea034a35a74da030398231089c15cde --- libutils/SystemClock.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp index c3b5d74..28ea817 100644 --- a/libutils/SystemClock.cpp +++ b/libutils/SystemClock.cpp @@ -121,9 +121,11 @@ int64_t elapsedRealtimeNano() #endif static int s_fd = -1; + bool need_unlock = false; if (clock_method < 0) { pthread_mutex_lock(&clock_lock); + need_unlock = true; } if (clock_method < 0 || clock_method == METHOD_IOCTL) { @@ -143,6 +145,8 @@ int64_t elapsedRealtimeNano() checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_IOCTL); if (clock_method < 0) { clock_method = METHOD_IOCTL; + } + if (need_unlock) { pthread_mutex_unlock(&clock_lock); } return timestamp; @@ -159,6 +163,8 @@ int64_t elapsedRealtimeNano() METHOD_CLOCK_GETTIME); if (clock_method < 0) { clock_method = METHOD_CLOCK_GETTIME; + } + if (need_unlock) { pthread_mutex_unlock(&clock_lock); } return timestamp; @@ -173,6 +179,8 @@ int64_t elapsedRealtimeNano() METHOD_SYSTEMTIME); if (clock_method < 0) { clock_method = METHOD_SYSTEMTIME; + } + if (need_unlock) { pthread_mutex_unlock(&clock_lock); } return timestamp; -- cgit v1.1 From cc607cbac851847af5fdc0f67905b04906954fc4 Mon Sep 17 00:00:00 2001 From: c457 Date: Thu, 22 Sep 2016 18:49:34 -0500 Subject: fastboot: Add Alcatel's USB vendor id Change-Id: Ic4f127c8dcd5db0c039491128862b791197f5c84 --- fastboot/fastboot.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 6a2f10d..91152a4 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -209,7 +209,8 @@ int match_fastboot_with_serial(usb_ifc_info *info, const char *local_serial) (info->dev_vendor != 0x2b4c) && // Zuk (info->dev_vendor != 0x2a96) && // MMX (info->dev_vendor != 0x19d2) && // ZTE - (info->dev_vendor != 0x2c3f)) // Nextbit + (info->dev_vendor != 0x2c3f) && // Nextbit + (info->dev_vendor != 0x1bbb)) // Alcatel return -1; if(info->ifc_class != 0xff) return -1; if(info->ifc_subclass != 0x42) return -1; -- cgit v1.1 From e8ee40302200c1bd1fd6537c80bf5e8aab744d42 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 23 Aug 2016 10:23:36 -0700 Subject: liblog: add __android_log_close() Bug: 30963384 (cherry picked from commit df7a4c6bae5f85532d79a93b7d9197a2aab17825) Change-Id: I2255486e84dd55af0f4e7fbbfb616c2deb1765d0 (cherry picked from commit 2d149691552676968b7de337f543463b920578b0) --- include/android/log.h | 5 +++++ liblog/logd_write.c | 39 +++++++++++++++++++++++++++++++++++++++ liblog/logd_write_kern.c | 35 +++++++++++++++++++++++++++++++++++ liblog/tests/liblog_test.cpp | 10 +++++++++- 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/include/android/log.h b/include/android/log.h index 1c171b7..391c826 100644 --- a/include/android/log.h +++ b/include/android/log.h @@ -89,6 +89,11 @@ typedef enum android_LogPriority { } android_LogPriority; /* + * Release any logger resources (a new log write will immediately re-acquire) + */ +void __android_log_close(); + +/* * Send a simple string to the log. */ int __android_log_write(int prio, const char *tag, const char *text); diff --git a/liblog/logd_write.c b/liblog/logd_write.c index bdee28f..64492f2 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -323,6 +323,45 @@ const char *android_log_id_to_name(log_id_t log_id) } #endif +/* + * Release any logger resources. A new log write will immediately re-acquire. + */ +void __android_log_close() +{ +#if FAKE_LOG_DEVICE + int i; +#endif + +#ifdef HAVE_PTHREADS + pthread_mutex_lock(&log_init_lock); +#endif + + write_to_log = __write_to_log_init; + + /* + * Threads that are actively writing at this point are not held back + * by a lock and are at risk of dropping the messages with a return code + * -EBADF. Prefer to return error code than add the overhead of a lock to + * each log writing call to guarantee delivery. In addition, anyone + * calling this is doing so to release the logging resources and shut down, + * for them to do so with outstanding log requests in other threads is a + * disengenuous use of this function. + */ +#if FAKE_LOG_DEVICE + for (i = 0; i < LOG_ID_MAX; i++) { + fakeLogClose(log_fds[i]); + log_fds[i] = -1; + } +#else + close(logd_fd); + logd_fd = -1; +#endif + +#ifdef HAVE_PTHREADS + pthread_mutex_unlock(&log_init_lock); +#endif +} + static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) { #if !defined(_WIN32) diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c index 8742b34..abdbd03 100644 --- a/liblog/logd_write_kern.c +++ b/liblog/logd_write_kern.c @@ -104,6 +104,41 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) return ret; } +/* + * Release any logger resources. A new log write will immediately re-acquire. + */ +void __android_log_close() +{ +#ifdef HAVE_PTHREADS + pthread_mutex_lock(&log_init_lock); +#endif + + write_to_log = __write_to_log_init; + + /* + * Threads that are actively writing at this point are not held back + * by a lock and are at risk of dropping the messages with a return code + * -EBADF. Prefer to return error code than add the overhead of a lock to + * each log writing call to guarantee delivery. In addition, anyone + * calling this is doing so to release the logging resources and shut down, + * for them to do so with outstanding log requests in other threads is a + * disengenuous use of this function. + */ + + log_close(log_fds[LOG_ID_MAIN]); + log_fds[LOG_ID_MAIN] = -1; + log_close(log_fds[LOG_ID_RADIO]); + log_fds[LOG_ID_RADIO] = -1; + log_close(log_fds[LOG_ID_EVENTS]); + log_fds[LOG_ID_EVENTS] = -1; + log_close(log_fds[LOG_ID_SYSTEM]); + log_fds[LOG_ID_SYSTEM] = -1; + +#ifdef HAVE_PTHREADS + pthread_mutex_unlock(&log_init_lock); +#endif +} + static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) { pthread_mutex_lock(&log_init_lock); diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp index c987041..0e7fec4 100644 --- a/liblog/tests/liblog_test.cpp +++ b/liblog/tests/liblog_test.cpp @@ -127,12 +127,17 @@ TEST(liblog, __android_log_btwrite__android_logger_list_read) { ASSERT_TRUE(NULL != (logger_list = android_logger_list_open( LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid))); + // Check that we can close and reopen the logger log_time ts(CLOCK_MONOTONIC); - ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts))); + __android_log_close(); + + log_time ts1(CLOCK_MONOTONIC); + ASSERT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1))); usleep(1000000); int count = 0; + int second_count = 0; for (;;) { log_msg log_msg; @@ -156,10 +161,13 @@ TEST(liblog, __android_log_btwrite__android_logger_list_read) { log_time tx(eventData + 4 + 1); if (ts == tx) { ++count; + } else if (ts1 == tx) { + ++second_count; } } EXPECT_EQ(1, count); + EXPECT_EQ(1, second_count); android_logger_list_close(logger_list); } -- cgit v1.1 From dc7cf2204e8dbb2c825bad52f8504921e4a0f2b9 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 23 Aug 2016 10:23:36 -0700 Subject: liblog: add __android_log_close() Bug: 30963384 (cherry picked from commit df7a4c6bae5f85532d79a93b7d9197a2aab17825) Change-Id: Ide70df3c04e29301649a1ca234b1b0af687bcbfb (cherry picked from commit b1b5d507cba4b37221016d308dbf9fdd39019108) --- liblog/logd_write.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/liblog/logd_write.c b/liblog/logd_write.c index 64492f2..667fdb3 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -355,6 +355,9 @@ void __android_log_close() #else close(logd_fd); logd_fd = -1; + + close(pstore_fd); + pstore_fd = -1; #endif #ifdef HAVE_PTHREADS -- cgit v1.1 From 656154a5b4127370f7317852e224a9121c6beed3 Mon Sep 17 00:00:00 2001 From: Michael W Date: Sun, 13 Nov 2016 13:03:50 +0100 Subject: init: Fix possible open file pointer In error case the file is not closed properly. Add close() before return Change-Id: Ie1755987859a576045c786105404957d94f0b39d --- init/init.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/init/init.cpp b/init/init.cpp index 58d7d34..8ea42ca 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -1012,8 +1012,10 @@ static int charging_mode_booting(void) { if (f < 0) return 0; - if (1 != read(f, (void *)&cmb,1)) + if (1 != read(f, (void *)&cmb,1)) { + close(f); return 0; + } close(f); return ('1' == cmb); -- cgit v1.1