Merge "crash_sender: Properly handle curl errors"
diff --git a/adb/Android.mk b/adb/Android.mk
index e10e3ef..2538e2e 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -296,9 +296,9 @@
libfs_mgr \
libfec \
libfec_rs \
+ libselinux \
liblog \
libmincrypt \
- libselinux \
libext4_utils_static \
libsquashfs_utils \
libcutils \
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index bc5ba38..2632b1f 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -39,6 +39,7 @@
#include <base/strings.h>
#if !defined(_WIN32)
+#include <signal.h>
#include <termios.h>
#include <unistd.h>
#endif
@@ -440,6 +441,14 @@
adb_thread_setname("stdin reader");
+#ifndef __WIN32
+ // Mask SIGTTIN in case we're in a backgrounded process
+ sigset_t sigset;
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGTTIN);
+ pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
+#endif
+
char raw_buffer[1024];
char* buffer_ptr = raw_buffer;
size_t buffer_size = sizeof(raw_buffer);
@@ -478,7 +487,11 @@
state = 1;
break;
case '~':
- if(state == 1) state++;
+ if(state == 1) {
+ state++;
+ } else {
+ state = 0;
+ }
break;
case '.':
if(state == 2) {
@@ -1342,15 +1355,20 @@
// argv[0] is always "shell".
--argc;
++argv;
- std::string shell_type_arg;
+ int t_arg_count = 0;
while (argc) {
if (!strcmp(argv[0], "-T") || !strcmp(argv[0], "-t")) {
if (!CanUseFeature(features, kFeatureShell2)) {
fprintf(stderr, "error: target doesn't support PTY args -Tt\n");
return 1;
}
- shell_type_arg = (argv[0][1] == 'T') ? kShellServiceArgRaw
- : kShellServiceArgPty;
+ // Like ssh, -t arguments are cumulative so that multiple -t's
+ // are needed to force a PTY.
+ if (argv[0][1] == 't') {
+ ++t_arg_count;
+ } else {
+ t_arg_count = -1;
+ }
--argc;
++argv;
} else if (!strcmp(argv[0], "-x")) {
@@ -1362,6 +1380,33 @@
}
}
+ std::string shell_type_arg;
+ if (CanUseFeature(features, kFeatureShell2)) {
+ if (t_arg_count < 0) {
+ shell_type_arg = kShellServiceArgRaw;
+ } else if (t_arg_count == 0) {
+ // If stdin isn't a TTY, default to a raw shell; this lets
+ // things like `adb shell < my_script.sh` work as expected.
+ // Otherwise leave |shell_type_arg| blank which uses PTY for
+ // interactive shells and raw for non-interactive.
+ if (!isatty(STDIN_FILENO)) {
+ shell_type_arg = kShellServiceArgRaw;
+ }
+ } else if (t_arg_count == 1) {
+ // A single -t arg isn't enough to override implicit -T.
+ if (!isatty(STDIN_FILENO)) {
+ fprintf(stderr,
+ "Remote PTY will not be allocated because stdin is not a terminal.\n"
+ "Use multiple -t options to force remote PTY allocation.\n");
+ shell_type_arg = kShellServiceArgRaw;
+ } else {
+ shell_type_arg = kShellServiceArgPty;
+ }
+ } else {
+ shell_type_arg = kShellServiceArgPty;
+ }
+ }
+
std::string command;
if (argc) {
// We don't escape here, just like ssh(1). http://b/20564385.
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index 5513e8f..5339947 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -77,7 +77,7 @@
std::string error;
fd = adb_connect("sync:", &error);
if (fd < 0) {
- fprintf(stderr, "error: %s\n", error.c_str());
+ fprintf(stderr, "adb: error: %s\n", error.c_str());
}
}
@@ -94,7 +94,7 @@
bool SendRequest(int id, const char* path_and_mode) {
size_t path_length = strlen(path_and_mode);
if (path_length > 1024) {
- fprintf(stderr, "SendRequest failed: path too long: %zu", path_length);
+ fprintf(stderr, "adb: SendRequest failed: path too long: %zu\n", path_length);
errno = ENAMETOOLONG;
return false;
}
@@ -118,7 +118,7 @@
unsigned mtime) {
size_t path_length = strlen(path_and_mode);
if (path_length > 1024) {
- fprintf(stderr, "SendSmallFile failed: path too long: %zu", path_length);
+ fprintf(stderr, "adb: SendSmallFile failed: path too long: %zu\n", path_length);
errno = ENAMETOOLONG;
return false;
}
@@ -156,7 +156,7 @@
bool CopyDone(const char* from, const char* to) {
syncmsg msg;
if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
- fprintf(stderr, "failed to copy '%s' to '%s': no ID_DONE: %s\n",
+ fprintf(stderr, "adb: failed to copy '%s' to '%s': no ID_DONE: %s\n",
from, to, strerror(errno));
return false;
}
@@ -164,17 +164,22 @@
return true;
}
if (msg.status.id != ID_FAIL) {
- fprintf(stderr, "failed to copy '%s' to '%s': unknown reason\n", from, to);
+ fprintf(stderr, "adb: failed to copy '%s' to '%s': unknown reason %d\n",
+ from, to, msg.status.id);
return false;
}
+ return ReportCopyFailure(from, to, msg);
+ }
+
+ bool ReportCopyFailure(const char* from, const char* to, const syncmsg& msg) {
char buffer[msg.status.msglen + 1];
if (!ReadFdExactly(fd, buffer, msg.status.msglen)) {
- fprintf(stderr, "failed to copy '%s' to '%s'; failed to read reason (!): %s\n",
+ fprintf(stderr, "adb: failed to copy '%s' to '%s'; failed to read reason (!): %s\n",
from, to, strerror(errno));
return false;
}
buffer[msg.status.msglen] = 0;
- fprintf(stderr, "failed to copy '%s' to '%s': %s\n", from, to, buffer);
+ fprintf(stderr, "adb: failed to copy '%s' to '%s': %s\n", from, to, buffer);
return false;
}
@@ -246,7 +251,7 @@
static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode, const char* path,
unsigned mtime, bool show_progress) {
if (!sc.SendRequest(ID_SEND, path_and_mode)) {
- fprintf(stderr, "failed to send ID_SEND message '%s': %s\n",
+ fprintf(stderr, "adb: failed to send ID_SEND message '%s': %s\n",
path_and_mode, strerror(errno));
return false;
}
@@ -256,7 +261,7 @@
// Determine local file size.
struct stat st;
if (stat(path, &st) == -1) {
- fprintf(stderr, "cannot stat '%s': %s\n", path, strerror(errno));
+ fprintf(stderr, "adb: cannot stat '%s': %s\n", path, strerror(errno));
return false;
}
@@ -265,7 +270,7 @@
int lfd = adb_open(path, O_RDONLY);
if (lfd < 0) {
- fprintf(stderr, "cannot open '%s': %s\n", path, strerror(errno));
+ fprintf(stderr, "adb: cannot open '%s': %s\n", path, strerror(errno));
return false;
}
@@ -275,7 +280,7 @@
int ret = adb_read(lfd, sbuf.data, sc.max);
if (ret <= 0) {
if (ret < 0) {
- fprintf(stderr, "cannot read '%s': %s\n", path, strerror(errno));
+ fprintf(stderr, "adb: cannot read '%s': %s\n", path, strerror(errno));
adb_close(lfd);
return false;
}
@@ -300,7 +305,8 @@
msg.data.id = ID_DONE;
msg.data.size = mtime;
if (!WriteFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
- fprintf(stderr, "failed to send ID_DONE message for '%s': %s\n", path, strerror(errno));
+ fprintf(stderr, "adb: failed to send ID_DONE message for '%s': %s\n",
+ path, strerror(errno));
return false;
}
@@ -317,7 +323,7 @@
char buf[PATH_MAX];
ssize_t data_length = readlink(lpath, buf, PATH_MAX - 1);
if (data_length == -1) {
- fprintf(stderr, "readlink '%s' failed: %s\n", lpath, strerror(errno));
+ fprintf(stderr, "adb: readlink '%s' failed: %s\n", lpath, strerror(errno));
return false;
}
buf[data_length++] = '\0';
@@ -328,19 +334,19 @@
}
if (!S_ISREG(mode)) {
- fprintf(stderr, "local file '%s' has unsupported mode: 0o%o\n", lpath, mode);
+ fprintf(stderr, "adb: local file '%s' has unsupported mode: 0o%o\n", lpath, mode);
return false;
}
struct stat st;
if (stat(lpath, &st) == -1) {
- fprintf(stderr, "stat '%s' failed: %s\n", lpath, strerror(errno));
+ fprintf(stderr, "adb: failed to stat local file '%s': %s\n", lpath, strerror(errno));
return false;
}
if (st.st_size < SYNC_DATA_MAX) {
std::string data;
if (!android::base::ReadFileToString(lpath, &data)) {
- fprintf(stderr, "failed to read all of '%s': %s\n", lpath, strerror(errno));
+ fprintf(stderr, "adb: failed to read all of '%s': %s\n", lpath, strerror(errno));
return false;
}
if (!sc.SendSmallFile(path_and_mode.c_str(), data.data(), data.size(), mtime)) return false;
@@ -351,66 +357,60 @@
}
static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, bool show_progress) {
- syncmsg msg;
- int lfd = -1;
-
- size_t len = strlen(rpath);
- if (len > 1024) return false;
-
unsigned size = 0;
if (show_progress) {
if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
}
if (!sc.SendRequest(ID_RECV, rpath)) return false;
- if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) return false;
- unsigned id = msg.data.id;
-
- if (id == ID_DATA || id == ID_DONE) {
- adb_unlink(lpath);
- mkdirs(lpath);
- lfd = adb_creat(lpath, 0644);
- if(lfd < 0) {
- fprintf(stderr, "cannot create '%s': %s\n", lpath, strerror(errno));
- return false;
- }
- goto handle_data;
- } else {
- goto remote_error;
+ adb_unlink(lpath);
+ mkdirs(lpath);
+ int lfd = adb_creat(lpath, 0644);
+ if (lfd < 0) {
+ fprintf(stderr, "adb: cannot create '%s': %s\n", lpath, strerror(errno));
+ return false;
}
while (true) {
- char buffer[SYNC_DATA_MAX];
-
+ syncmsg msg;
if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
adb_close(lfd);
+ adb_unlink(lpath);
return false;
}
- id = msg.data.id;
- handle_data:
- len = msg.data.size;
- if (id == ID_DONE) break;
- if (id != ID_DATA) goto remote_error;
- if (len > sc.max) {
- fprintf(stderr, "msg.data.size too large: %zu (max %zu)\n", len, sc.max);
+ if (msg.data.id == ID_DONE) break;
+
+ if (msg.data.id != ID_DATA) {
adb_close(lfd);
+ adb_unlink(lpath);
+ sc.ReportCopyFailure(rpath, lpath, msg);
return false;
}
- if (!ReadFdExactly(sc.fd, buffer, len)) {
+ if (msg.data.size > sc.max) {
+ fprintf(stderr, "adb: msg.data.size too large: %u (max %zu)\n", msg.data.size, sc.max);
adb_close(lfd);
+ adb_unlink(lpath);
return false;
}
- if (!WriteFdExactly(lfd, buffer, len)) {
- fprintf(stderr, "cannot write '%s': %s\n", rpath, strerror(errno));
+ char buffer[SYNC_DATA_MAX];
+ if (!ReadFdExactly(sc.fd, buffer, msg.data.size)) {
adb_close(lfd);
+ adb_unlink(lpath);
return false;
}
- sc.total_bytes += len;
+ if (!WriteFdExactly(lfd, buffer, msg.data.size)) {
+ fprintf(stderr, "adb: cannot write '%s': %s\n", lpath, strerror(errno));
+ adb_close(lfd);
+ adb_unlink(lpath);
+ return false;
+ }
+
+ sc.total_bytes += msg.data.size;
if (show_progress) {
print_transfer_progress(sc.total_bytes, size);
@@ -419,12 +419,6 @@
adb_close(lfd);
return true;
-
-remote_error:
- adb_close(lfd);
- adb_unlink(lpath);
- sc.CopyDone(rpath, lpath);
- return false;
}
static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time,
@@ -486,7 +480,7 @@
std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(lpath), closedir);
if (!dir) {
- fprintf(stderr, "cannot open '%s': %s\n", lpath, strerror(errno));
+ fprintf(stderr, "adb: cannot open '%s': %s\n", lpath, strerror(errno));
return -1;
}
@@ -496,7 +490,7 @@
char stat_path[PATH_MAX];
if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path)) {
- fprintf(stderr, "skipping long path '%s%s'\n", lpath, de->d_name);
+ fprintf(stderr, "adb: skipping long path '%s%s'\n", lpath, de->d_name);
continue;
}
strcpy(stat_path, lpath);
@@ -511,7 +505,7 @@
} else {
ci = mkcopyinfo(lpath, rpath, de->d_name, 0);
if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
- fprintf(stderr, "skipping special file '%s'\n", ci->src);
+ fprintf(stderr, "adb: skipping special file '%s'\n", ci->src);
free(ci);
} else {
ci->time = st.st_mtime;
@@ -522,7 +516,7 @@
}
}
} else {
- fprintf(stderr, "cannot lstat '%s': %s\n",stat_path , strerror(errno));
+ fprintf(stderr, "adb: cannot lstat '%s': %s\n",stat_path , strerror(errno));
}
}
@@ -607,7 +601,7 @@
struct stat st;
if (stat(lpath, &st)) {
- fprintf(stderr, "cannot stat '%s': %s\n", lpath, strerror(errno));
+ fprintf(stderr, "adb: cannot stat '%s': %s\n", lpath, strerror(errno));
return false;
}
@@ -660,7 +654,7 @@
ci->next = *filelist;
*filelist = ci;
} else {
- fprintf(stderr, "skipping special file '%s'\n", name);
+ fprintf(stderr, "adb: skipping special file '%s'\n", name);
}
}
@@ -754,7 +748,7 @@
unsigned mode, time;
if (!sync_stat(sc, rpath, &time, &mode, nullptr)) return false;
if (mode == 0) {
- fprintf(stderr, "remote object '%s' does not exist\n", rpath);
+ fprintf(stderr, "adb: remote object '%s' does not exist\n", rpath);
return false;
}
@@ -781,7 +775,7 @@
return copy_remote_dir_local(sc, rpath, lpath, copy_attrs);
}
- fprintf(stderr, "remote object '%s' not a file or directory\n", rpath);
+ fprintf(stderr, "adb: remote object '%s' not a file or directory\n", rpath);
return false;
}
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 713638d..1287fb9 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -528,7 +528,7 @@
return 1;
fcntl(s, F_SETFD, FD_CLOEXEC);
- ALOGI("debuggerd: " __DATE__ " " __TIME__ "\n");
+ ALOGI("debuggerd: starting\n");
for (;;) {
sockaddr addr;
diff --git a/healthd/Android.mk b/healthd/Android.mk
index 07e1d73..27c985c 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -35,7 +35,7 @@
LOCAL_C_INCLUDES := bootable/recovery
-LOCAL_STATIC_LIBRARIES := libbatteryservice libbinder libminui libpng libz libutils libstdc++ libcutils liblog libm libc
+LOCAL_STATIC_LIBRARIES := libbatteryservice libbinder libminui libpng libz libutils libcutils liblog libm libc
ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
LOCAL_STATIC_LIBRARIES += libsuspend
diff --git a/init/Android.mk b/init/Android.mk
index 8e45a7a..d6cb4e5 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -92,9 +92,9 @@
libbase \
libext4_utils_static \
libutils \
- liblog \
libc \
libselinux \
+ liblog \
libmincrypt \
libcrypto_static \
libc++_static \
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index a768762..e1e0c48 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -89,7 +89,7 @@
if (out == NULL) {
return;
}
- fprintf(out, "version = Android init 0.8 " __TIME__ "\n");
+ fprintf(out, "version = Android init 0.8\n");
fprintf(out, "title = Boot chart for Android (%s)\n", date);
fprintf(out, "system.uname = %s %s %s %s\n", uts.sysname, uts.release, uts.version, uts.machine);
fprintf(out, "system.release = %s\n", fingerprint.c_str());
diff --git a/libpixelflinger/include/private/pixelflinger/ggl_context.h b/libpixelflinger/include/private/pixelflinger/ggl_context.h
index d43655c..a18b2f7 100644
--- a/libpixelflinger/include/private/pixelflinger/ggl_context.h
+++ b/libpixelflinger/include/private/pixelflinger/ggl_context.h
@@ -234,7 +234,7 @@
// ----------------------------------------------------------------------------
-class needs_filter_t;
+struct needs_filter_t;
struct needs_t {
inline int match(const needs_filter_t& filter);
inline bool operator == (const needs_t& rhs) const {
diff --git a/libpixelflinger/trap.cpp b/libpixelflinger/trap.cpp
index 80efeff..ea53625 100644
--- a/libpixelflinger/trap.cpp
+++ b/libpixelflinger/trap.cpp
@@ -563,10 +563,10 @@
c->init_y(c, miny);
for (int32_t y = miny; y < maxy; y++) {
- register int32_t ex0 = ey0;
- register int32_t ex1 = ey1;
- register int32_t ex2 = ey2;
- register int32_t xl, xr;
+ int32_t ex0 = ey0;
+ int32_t ex1 = ey1;
+ int32_t ex2 = ey2;
+ int32_t xl, xr;
for (xl=minx ; xl<maxx ; xl++) {
if (ex0>0 && ex1>0 && ex2>0)
break; // all strictly positive
diff --git a/libutils/LinearTransform.cpp b/libutils/LinearTransform.cpp
index b7d28d4..138ce8b 100644
--- a/libutils/LinearTransform.cpp
+++ b/libutils/LinearTransform.cpp
@@ -21,11 +21,24 @@
#include <utils/LinearTransform.h>
+// disable sanitize as these functions may intentionally overflow (see comments below).
+// the ifdef can be removed when host builds use clang.
+#if defined(__clang__)
+#define ATTRIBUTE_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer")))
+#else
+#define ATTRIBUTE_NO_SANITIZE_INTEGER
+#endif
+
namespace android {
-template<class T> static inline T ABS(T x) { return (x < 0) ? -x : x; }
+// sanitize failure with T = int32_t and x = 0x80000000
+template<class T>
+ATTRIBUTE_NO_SANITIZE_INTEGER
+static inline T ABS(T x) { return (x < 0) ? -x : x; }
// Static math methods involving linear transformations
+// remote sanitize failure on overflow case.
+ATTRIBUTE_NO_SANITIZE_INTEGER
static bool scale_u64_to_u64(
uint64_t val,
uint32_t N,
@@ -109,6 +122,8 @@
return true;
}
+// at least one known sanitize failure (see comment below)
+ATTRIBUTE_NO_SANITIZE_INTEGER
static bool linear_transform_s64_to_s64(
int64_t val,
int64_t basis1,
@@ -172,7 +187,7 @@
// (scaled_signbit XOR res_signbit)
if (is_neg)
- scaled = -scaled;
+ scaled = -scaled; // known sanitize failure
res = scaled + basis2;
if ((scaled ^ basis2 ^ INT64_MIN) & (scaled ^ res) & INT64_MIN)
@@ -250,6 +265,8 @@
template void LinearTransform::reduce<uint64_t>(uint64_t* N, uint64_t* D);
template void LinearTransform::reduce<uint32_t>(uint32_t* N, uint32_t* D);
+// sanitize failure if *N = 0x80000000
+ATTRIBUTE_NO_SANITIZE_INTEGER
void LinearTransform::reduce(int32_t* N, uint32_t* D) {
if (N && D && *D) {
if (*N < 0) {
diff --git a/logd/Android.mk b/logd/Android.mk
index c00061b..feca8d5 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -27,7 +27,8 @@
libsysutils \
liblog \
libcutils \
- libbase
+ libbase \
+ libpackagelistparser
# This is what we want to do:
# event_logtags = $(shell \
diff --git a/logd/main.cpp b/logd/main.cpp
index 60262e9..13dda78 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -33,12 +33,14 @@
#include <syslog.h>
#include <unistd.h>
+#include <cstdbool>
#include <memory>
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
#include <log/event_tag_map.h>
+#include <packagelistparser/packagelistparser.h>
#include <private/android_filesystem_config.h>
#include <utils/threads.h>
@@ -166,6 +168,19 @@
static bool reinit_running = false;
static LogBuffer *logBuf = NULL;
+static bool package_list_parser_cb(pkg_info *info, void * /* userdata */) {
+
+ bool rc = true;
+ if (info->uid == uid) {
+ name = strdup(info->name);
+ // false to stop processing
+ rc = false;
+ }
+
+ packagelist_free(info);
+ return rc;
+}
+
static void *reinit_thread_start(void * /*obj*/) {
prctl(PR_SET_NAME, "logd.daemon");
set_sched_policy(0, SP_BACKGROUND);
@@ -180,31 +195,8 @@
if (uid) {
name = NULL;
- FILE *fp = fopen("/data/system/packages.list", "r");
- if (fp) {
- // This simple parser is sensitive to format changes in
- // frameworks/base/services/core/java/com/android/server/pm/Settings.java
- // A dependency note has been added to that file to correct
- // this parser.
+ packagelist_parse(package_list_parser_cb, NULL);
- char *buffer = NULL;
- size_t len;
- while (getline(&buffer, &len, fp) > 0) {
- char *userId = strchr(buffer, ' ');
- if (!userId) {
- continue;
- }
- *userId = '\0';
- unsigned long value = strtoul(userId + 1, NULL, 10);
- if (value != uid) {
- continue;
- }
- name = strdup(buffer);
- break;
- }
- free(buffer);
- fclose(fp);
- }
uid = 0;
sem_post(&uidName);
continue;
diff --git a/packagelistparser/Android.mk b/packagelistparser/Android.mk
new file mode 100644
index 0000000..802a3cb
--- /dev/null
+++ b/packagelistparser/Android.mk
@@ -0,0 +1,32 @@
+LOCAL_PATH:= $(call my-dir)
+
+#########################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libpackagelistparser
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := packagelistparser.c
+LOCAL_COPY_HEADERS_TO := packagelistparser
+LOCAL_COPY_HEADERS := packagelistparser.h
+LOCAL_SHARED_LIBRARIES := liblog
+
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+
+include $(BUILD_SHARED_LIBRARY)
+
+#########################
+include $(CLEAR_VARS)
+
+
+LOCAL_MODULE := libpackagelistparser
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := packagelistparser.c
+LOCAL_COPY_HEADERS_TO := packagelistparser
+LOCAL_COPY_HEADERS := packagelistparser.h
+LOCAL_STATIC_LIBRARIES := liblog
+
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/packagelistparser/packagelistparser.c b/packagelistparser/packagelistparser.c
new file mode 100644
index 0000000..3e2539c
--- /dev/null
+++ b/packagelistparser/packagelistparser.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2015, Intel Corporation
+ * Copyright (C) 2015 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.
+ *
+ * Written by William Roberts <william.c.roberts@intel.com>
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/limits.h>
+
+#define LOG_TAG "packagelistparser"
+#include <utils/Log.h>
+
+#include "packagelistparser.h"
+
+#define CLOGE(fmt, ...) \
+ do {\
+ IF_ALOGE() {\
+ ALOGE(fmt, ##__VA_ARGS__);\
+ }\
+ } while(0)
+
+static size_t get_gid_cnt(const char *gids)
+{
+ size_t cnt;
+
+ if (*gids == '\0') {
+ return 0;
+ }
+
+ if (!strcmp(gids, "none")) {
+ return 0;
+ }
+
+ for (cnt = 1; gids[cnt]; gids[cnt] == ',' ? cnt++ : *gids++)
+ ;
+
+ return cnt;
+}
+
+static bool parse_gids(char *gids, gid_t *gid_list, size_t *cnt)
+{
+ gid_t gid;
+ char* token;
+ char *endptr;
+ size_t cmp = 0;
+
+ while ((token = strsep(&gids, ",\r\n"))) {
+
+ if (cmp > *cnt) {
+ return false;
+ }
+
+ gid = strtoul(token, &endptr, 10);
+ if (*endptr != '\0') {
+ return false;
+ }
+
+ /*
+ * if unsigned long is greater than size of gid_t,
+ * prevent a truncation based roll-over
+ */
+ if (gid > GID_MAX) {
+ CLOGE("A gid in field \"gid list\" greater than GID_MAX");
+ return false;
+ }
+
+ gid_list[cmp++] = gid;
+ }
+ return true;
+}
+
+extern bool packagelist_parse(pfn_on_package callback, void *userdata)
+{
+
+ FILE *fp;
+ char *cur;
+ char *next;
+ char *endptr;
+ unsigned long tmp;
+ ssize_t bytesread;
+
+ bool rc = false;
+ char *buf = NULL;
+ size_t buflen = 0;
+ unsigned long lineno = 1;
+ const char *errmsg = NULL;
+ struct pkg_info *pkg_info = NULL;
+
+ fp = fopen(PACKAGES_LIST_FILE, "re");
+ if (!fp) {
+ CLOGE("Could not open: \"%s\", error: \"%s\"\n", PACKAGES_LIST_FILE,
+ strerror(errno));
+ return false;
+ }
+
+ while ((bytesread = getline(&buf, &buflen, fp)) > 0) {
+
+ pkg_info = calloc(1, sizeof(*pkg_info));
+ if (!pkg_info) {
+ goto err;
+ }
+
+ next = buf;
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for \"package name\"";
+ goto err;
+ }
+
+ pkg_info->name = strdup(cur);
+ if (!pkg_info->name) {
+ goto err;
+ }
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for field \"uid\"";
+ goto err;
+ }
+
+ tmp = strtoul(cur, &endptr, 10);
+ if (*endptr != '\0') {
+ errmsg = "Could not convert field \"uid\" to integer value";
+ goto err;
+ }
+
+ /*
+ * if unsigned long is greater than size of uid_t,
+ * prevent a truncation based roll-over
+ */
+ if (tmp > UID_MAX) {
+ errmsg = "Field \"uid\" greater than UID_MAX";
+ goto err;
+ }
+
+ pkg_info->uid = (uid_t) tmp;
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for field \"debuggable\"";
+ goto err;
+ }
+
+ tmp = strtoul(cur, &endptr, 10);
+ if (*endptr != '\0') {
+ errmsg = "Could not convert field \"debuggable\" to integer value";
+ goto err;
+ }
+
+ /* should be a valid boolean of 1 or 0 */
+ if (!(tmp == 0 || tmp == 1)) {
+ errmsg = "Field \"debuggable\" is not 0 or 1 boolean value";
+ goto err;
+ }
+
+ pkg_info->debuggable = (bool) tmp;
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for field \"data dir\"";
+ goto err;
+ }
+
+ pkg_info->data_dir = strdup(cur);
+ if (!pkg_info->data_dir) {
+ goto err;
+ }
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for field \"seinfo\"";
+ goto err;
+ }
+
+ pkg_info->seinfo = strdup(cur);
+ if (!pkg_info->seinfo) {
+ goto err;
+ }
+
+ cur = strsep(&next, " \t\r\n");
+ if (!cur) {
+ errmsg = "Could not get next token for field \"gid(s)\"";
+ goto err;
+ }
+
+ /*
+ * Parse the gid list, could be in the form of none, single gid or list:
+ * none
+ * gid
+ * gid, gid ...
+ */
+ pkg_info->gids.cnt = get_gid_cnt(cur);
+ if (pkg_info->gids.cnt > 0) {
+
+ pkg_info->gids.gids = calloc(pkg_info->gids.cnt, sizeof(gid_t));
+ if (!pkg_info->gids.gids) {
+ goto err;
+ }
+
+ rc = parse_gids(cur, pkg_info->gids.gids, &pkg_info->gids.cnt);
+ if (!rc) {
+ errmsg = "Could not parse field \"gid list\"";
+ goto err;
+ }
+ }
+
+ rc = callback(pkg_info, userdata);
+ if (rc == false) {
+ /*
+ * We do not log this as this can be intentional from
+ * callback to abort processing. We go to out to not
+ * free the pkg_info
+ */
+ rc = true;
+ goto out;
+ }
+ lineno++;
+ }
+
+ rc = true;
+
+out:
+ free(buf);
+ fclose(fp);
+ return rc;
+
+err:
+ if (errmsg) {
+ CLOGE("Error Parsing \"%s\" on line: %lu for reason: %s",
+ PACKAGES_LIST_FILE, lineno, errmsg);
+ }
+ rc = false;
+ packagelist_free(pkg_info);
+ goto out;
+}
+
+void packagelist_free(pkg_info *info)
+{
+ if (info) {
+ free(info->name);
+ free(info->data_dir);
+ free(info->seinfo);
+ free(info->gids.gids);
+ free(info);
+ }
+}
diff --git a/packagelistparser/packagelistparser.h b/packagelistparser/packagelistparser.h
new file mode 100644
index 0000000..d602c26
--- /dev/null
+++ b/packagelistparser/packagelistparser.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2015, Intel Corporation
+ * Copyright (C) 2015 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.
+ *
+ * Written by William Roberts <william.c.roberts@intel.com>
+ *
+ * This is a parser library for parsing the packages.list file generated
+ * by PackageManager service.
+ *
+ * This simple parser is sensitive to format changes in
+ * frameworks/base/services/core/java/com/android/server/pm/Settings.java
+ * A dependency note has been added to that file to correct
+ * this parser.
+ */
+
+#ifndef PACKAGELISTPARSER_H_
+#define PACKAGELISTPARSER_H_
+
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+/** The file containing the list of installed packages on the system */
+#define PACKAGES_LIST_FILE "/data/system/packages.list"
+
+typedef struct pkg_info pkg_info;
+typedef struct gid_list gid_list;
+
+struct gid_list {
+ size_t cnt;
+ gid_t *gids;
+};
+
+struct pkg_info {
+ char *name;
+ uid_t uid;
+ bool debuggable;
+ char *data_dir;
+ char *seinfo;
+ gid_list gids;
+ void *private_data;
+};
+
+/**
+ * Callback function to be used by packagelist_parse() routine.
+ * @param info
+ * The parsed package information
+ * @param userdata
+ * The supplied userdata pointer to packagelist_parse()
+ * @return
+ * true to keep processing, false to stop.
+ */
+typedef bool (*pfn_on_package)(pkg_info *info, void *userdata);
+
+/**
+ * Parses the file specified by PACKAGES_LIST_FILE and invokes the callback on
+ * each entry found. Once the callback is invoked, ownership of the pkg_info pointer
+ * is passed to the callback routine, thus they are required to perform any cleanup
+ * desired.
+ * @param callback
+ * The callback function called on each parsed line of the packages list.
+ * @param userdata
+ * An optional userdata supplied pointer to pass to the callback function.
+ * @return
+ * true on success false on failure.
+ */
+extern bool packagelist_parse(pfn_on_package callback, void *userdata);
+
+/**
+ * Frees a pkg_info structure.
+ * @param info
+ * The struct to free
+ */
+extern void packagelist_free(pkg_info *info);
+
+__END_DECLS
+
+#endif /* PACKAGELISTPARSER_H_ */
diff --git a/rootdir/asan.options b/rootdir/asan.options
index 2f12341..43896a1 100644
--- a/rootdir/asan.options
+++ b/rootdir/asan.options
@@ -1 +1,5 @@
-allow_user_segv_handler=1:detect_odr_violation=0:alloc_dealloc_mismatch=0:allocator_may_return_null=1
+allow_user_segv_handler=1
+detect_odr_violation=0
+alloc_dealloc_mismatch=0
+allocator_may_return_null=1
+detect_container_overflow=0
diff --git a/sdcard/Android.mk b/sdcard/Android.mk
index cb3a8fb..c5f3d1d 100644
--- a/sdcard/Android.mk
+++ b/sdcard/Android.mk
@@ -5,7 +5,6 @@
LOCAL_SRC_FILES := sdcard.c
LOCAL_MODULE := sdcard
LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
-
-LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_SHARED_LIBRARIES := libcutils libpackagelistparser
include $(BUILD_EXECUTABLE)
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index d2d2315..b6bbe7e 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -24,6 +24,7 @@
#include <limits.h>
#include <linux/fuse.h>
#include <pthread.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -34,6 +35,7 @@
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/time.h>
+#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
@@ -41,6 +43,7 @@
#include <cutils/hashmap.h>
#include <cutils/log.h>
#include <cutils/multiuser.h>
+#include <packagelistparser/packagelistparser.h>
#include <private/android_filesystem_config.h>
@@ -103,9 +106,6 @@
* or that a reply has already been written. */
#define NO_STATUS 1
-/* Path to system-provided mapping of package name to appIds */
-static const char* const kPackagesListFile = "/data/system/packages.list";
-
/* Supplementary groups to execute with */
static const gid_t kGroups[1] = { AID_PACKAGE_INFO };
@@ -1636,35 +1636,27 @@
return true;
}
-static int read_package_list(struct fuse_global* global) {
+static bool package_parse_callback(pkg_info *info, void *userdata) {
+ struct fuse_global *global = (struct fuse_global *)userdata;
+
+ char* name = strdup(info->name);
+ hashmapPut(global->package_to_appid, name, (void*) (uintptr_t) info->uid);
+ packagelist_free(info);
+ return true;
+}
+
+static bool read_package_list(struct fuse_global* global) {
pthread_mutex_lock(&global->lock);
hashmapForEach(global->package_to_appid, remove_str_to_int, global->package_to_appid);
- FILE* file = fopen(kPackagesListFile, "r");
- if (!file) {
- ERROR("failed to open package list: %s\n", strerror(errno));
- pthread_mutex_unlock(&global->lock);
- return -1;
- }
-
- char buf[512];
- while (fgets(buf, sizeof(buf), file) != NULL) {
- char package_name[512];
- int appid;
- char gids[512];
-
- if (sscanf(buf, "%s %d %*d %*s %*s %s", package_name, &appid, gids) == 3) {
- char* package_name_dup = strdup(package_name);
- hashmapPut(global->package_to_appid, package_name_dup, (void*) (uintptr_t) appid);
- }
- }
-
+ bool rc = packagelist_parse(package_parse_callback, global);
TRACE("read_package_list: found %zu packages\n",
hashmapSize(global->package_to_appid));
- fclose(file);
+
pthread_mutex_unlock(&global->lock);
- return 0;
+
+ return rc;
}
static void watch_package_list(struct fuse_global* global) {
@@ -1680,11 +1672,11 @@
bool active = false;
while (1) {
if (!active) {
- int res = inotify_add_watch(nfd, kPackagesListFile, IN_DELETE_SELF);
+ int res = inotify_add_watch(nfd, PACKAGES_LIST_FILE, IN_DELETE_SELF);
if (res == -1) {
if (errno == ENOENT || errno == EACCES) {
/* Framework may not have created yet, sleep and retry */
- ERROR("missing packages.list; retrying\n");
+ ERROR("missing \"%s\"; retrying\n", PACKAGES_LIST_FILE);
sleep(3);
continue;
} else {
@@ -1695,8 +1687,8 @@
/* Watch above will tell us about any future changes, so
* read the current state. */
- if (read_package_list(global) == -1) {
- ERROR("read_package_list failed: %s\n", strerror(errno));
+ if (read_package_list(global) == false) {
+ ERROR("read_package_list failed\n");
return;
}
active = true;
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 579d26e..52716e9 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -31,7 +31,6 @@
dd \
OUR_TOOLS := \
- df \
getevent \
iftop \
ioctl \
diff --git a/toolbox/df.c b/toolbox/df.c
deleted file mode 100644
index 9cd0743..0000000
--- a/toolbox/df.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/statfs.h>
-
-static int ok = EXIT_SUCCESS;
-
-static void printsize(long long n)
-{
- char unit = 'K';
- long long t;
-
- n *= 10;
-
- if (n > 1024*1024*10) {
- n /= 1024;
- unit = 'M';
- }
-
- if (n > 1024*1024*10) {
- n /= 1024;
- unit = 'G';
- }
-
- t = (n + 512) / 1024;
- printf("%4lld.%1lld%c", t/10, t%10, unit);
-}
-
-static void df(char *s, int always) {
- struct statfs st;
-
- if (statfs(s, &st) < 0) {
- fprintf(stderr, "%s: %s\n", s, strerror(errno));
- ok = EXIT_FAILURE;
- } else {
- if (st.f_blocks == 0 && !always)
- return;
- printf("%-20s ", s);
- printsize((long long)st.f_blocks * (long long)st.f_bsize);
- printf(" ");
- printsize((long long)(st.f_blocks - (long long)st.f_bfree) * st.f_bsize);
- printf(" ");
- printsize((long long)st.f_bfree * (long long)st.f_bsize);
- printf(" %d\n", (int) st.f_bsize);
- }
-}
-
-int df_main(int argc, char *argv[]) {
- printf("Filesystem Size Used Free Blksize\n");
- if (argc == 1) {
- char s[2000];
- FILE *f = fopen("/proc/mounts", "r");
-
- while (fgets(s, 2000, f)) {
- char *c, *e = s;
-
- for (c = s; *c; c++) {
- if (*c == ' ') {
- e = c + 1;
- break;
- }
- }
-
- for (c = e; *c; c++) {
- if (*c == ' ') {
- *c = '\0';
- break;
- }
- }
-
- df(e, 0);
- }
-
- fclose(f);
- } else {
- int i;
-
- for (i = 1; i < argc; i++) {
- df(argv[i], 1);
- }
- }
-
- exit(ok);
-}