Merge "Add StartsWithIgnoreCase/EndsWithIgnoreCase." am: 61131fc92f am: 35f85910ee am: d380061dc3
am: bcc102c5c3
Change-Id: I89763fb5c35655dc04bc1ac471f3aacd24eb246e
diff --git a/include/utils/SortedVector.h b/include/utils/SortedVector.h
index 86f3496..d57465d 100644
--- a/include/utils/SortedVector.h
+++ b/include/utils/SortedVector.h
@@ -37,18 +37,18 @@
public:
typedef TYPE value_type;
-
- /*!
+
+ /*!
* Constructors and destructors
*/
-
+
SortedVector();
SortedVector(const SortedVector<TYPE>& rhs);
virtual ~SortedVector();
/*! copy operator */
- const SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
- SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
+ const SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
+ SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
/*
* empty the vector
@@ -56,7 +56,7 @@
inline void clear() { VectorImpl::clear(); }
- /*!
+ /*!
* vector stats
*/
@@ -69,11 +69,11 @@
//! sets the capacity. capacity can never be reduced less than size()
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
- /*!
+ /*!
* C-style array access
*/
-
- //! read-only C-style access
+
+ //! read-only C-style access
inline const TYPE* array() const;
//! read-write C-style access. BE VERY CAREFUL when modifying the array
@@ -82,12 +82,12 @@
//! finds the index of an item
ssize_t indexOf(const TYPE& item) const;
-
+
//! finds where this item should be inserted
size_t orderOf(const TYPE& item) const;
-
-
- /*!
+
+
+ /*!
* accessors
*/
@@ -104,7 +104,7 @@
//! add an item in the right place (and replace the one that is there)
ssize_t add(const TYPE& item);
-
+
//! editItemAt() MUST NOT change the order of this item
TYPE& editItemAt(size_t index) {
return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
@@ -113,7 +113,7 @@
//! merges a vector into this one
ssize_t merge(const Vector<TYPE>& vector);
ssize_t merge(const SortedVector<TYPE>& vector);
-
+
//! removes an item
ssize_t remove(const TYPE&);
@@ -121,7 +121,24 @@
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
//! remove one item
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
-
+
+ /*
+ * these inlines add some level of compatibility with STL.
+ */
+ typedef TYPE* iterator;
+ typedef TYPE const* const_iterator;
+
+ inline iterator begin() { return editArray(); }
+ inline iterator end() { return editArray() + size(); }
+ inline const_iterator begin() const { return array(); }
+ inline const_iterator end() const { return array() + size(); }
+ inline void reserve(size_t n) { setCapacity(n); }
+ inline bool empty() const{ return isEmpty(); }
+ inline iterator erase(iterator pos) {
+ ssize_t index = removeItemsAt(pos-array());
+ return begin() + index;
+ }
+
protected:
virtual void do_construct(void* storage, size_t num) const;
virtual void do_destroy(void* storage, size_t num) const;
@@ -159,13 +176,13 @@
template<class TYPE> inline
SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
SortedVectorImpl::operator = (rhs);
- return *this;
+ return *this;
}
template<class TYPE> inline
const SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
SortedVectorImpl::operator = (rhs);
- return *this;
+ return *this;
}
template<class TYPE> inline
diff --git a/init/init.cpp b/init/init.cpp
index 957527b..7a0e114 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -18,6 +18,7 @@
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <fstream>
#include <libgen.h>
#include <paths.h>
#include <signal.h>
@@ -248,6 +249,113 @@
return result;
}
+static void security_failure() {
+ LOG(ERROR) << "Security failure; rebooting into recovery mode...";
+ android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
+ while (true) { pause(); } // never reached
+}
+
+#define MMAP_RND_PATH "/proc/sys/vm/mmap_rnd_bits"
+#define MMAP_RND_COMPAT_PATH "/proc/sys/vm/mmap_rnd_compat_bits"
+
+/* __attribute__((unused)) due to lack of mips support: see mips block
+ * in set_mmap_rnd_bits_action */
+static bool __attribute__((unused)) set_mmap_rnd_bits_min(int start, int min, bool compat) {
+ std::string path;
+ if (compat) {
+ path = MMAP_RND_COMPAT_PATH;
+ } else {
+ path = MMAP_RND_PATH;
+ }
+ std::ifstream inf(path, std::fstream::in);
+ if (!inf) {
+ LOG(ERROR) << "Cannot open for reading: " << path;
+ return false;
+ }
+ while (start >= min) {
+ // try to write out new value
+ std::string str_val = std::to_string(start);
+ std::ofstream of(path, std::fstream::out);
+ if (!of) {
+ LOG(ERROR) << "Cannot open for writing: " << path;
+ return false;
+ }
+ of << str_val << std::endl;
+ of.close();
+
+ // check to make sure it was recorded
+ inf.seekg(0);
+ std::string str_rec;
+ inf >> str_rec;
+ if (str_val.compare(str_rec) == 0) {
+ break;
+ }
+ start--;
+ }
+ inf.close();
+ if (start < min) {
+ LOG(ERROR) << "Unable to set minimum required entropy " << min << " in " << path;
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Set /proc/sys/vm/mmap_rnd_bits and potentially
+ * /proc/sys/vm/mmap_rnd_compat_bits to the maximum supported values.
+ * Returns -1 if unable to set these to an acceptable value.
+ *
+ * To support this sysctl, the following upstream commits are needed:
+ *
+ * d07e22597d1d mm: mmap: add new /proc tunable for mmap_base ASLR
+ * e0c25d958f78 arm: mm: support ARCH_MMAP_RND_BITS
+ * 8f0d3aa9de57 arm64: mm: support ARCH_MMAP_RND_BITS
+ * 9e08f57d684a x86: mm: support ARCH_MMAP_RND_BITS
+ * ec9ee4acd97c drivers: char: random: add get_random_long()
+ * 5ef11c35ce86 mm: ASLR: use get_random_long()
+ */
+static int set_mmap_rnd_bits_action(const std::vector<std::string>& args)
+{
+ int ret = -1;
+
+ /* values are arch-dependent */
+#if defined(__aarch64__)
+ /* arm64 supports 18 - 33 bits depending on pagesize and VA_SIZE */
+ if (set_mmap_rnd_bits_min(33, 24, false)
+ && set_mmap_rnd_bits_min(16, 16, true)) {
+ ret = 0;
+ }
+#elif defined(__x86_64__)
+ /* x86_64 supports 28 - 32 bits */
+ if (set_mmap_rnd_bits_min(32, 32, false)
+ && set_mmap_rnd_bits_min(16, 16, true)) {
+ ret = 0;
+ }
+#elif defined(__arm__) || defined(__i386__)
+ /* check to see if we're running on 64-bit kernel */
+ bool h64 = !access(MMAP_RND_COMPAT_PATH, F_OK);
+ /* supported 32-bit architecture must have 16 bits set */
+ if (set_mmap_rnd_bits_min(16, 16, h64)) {
+ ret = 0;
+ }
+#elif defined(__mips__) || defined(__mips64__)
+ // TODO: add mips support b/27788820
+ ret = 0;
+#else
+ ERROR("Unknown architecture\n");
+#endif
+
+#ifdef __BRILLO__
+ // TODO: b/27794137
+ ret = 0;
+#endif
+ if (ret == -1) {
+ LOG(ERROR) << "Unable to set adequate mmap entropy value!";
+ security_failure();
+ }
+ return ret;
+}
+
static int keychord_init_action(const std::vector<std::string>& args)
{
keychord_init();
@@ -401,12 +509,6 @@
return 0;
}
-static void security_failure() {
- LOG(ERROR) << "Security failure; rebooting into recovery mode...";
- android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
- while (true) { pause(); } // never reached
-}
-
static void selinux_initialize(bool in_kernel_domain) {
Timer t;
@@ -674,6 +776,7 @@
am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
// ... so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
+ am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
am.QueueBuiltinAction(keychord_init_action, "keychord_init");
am.QueueBuiltinAction(console_init_action, "console_init");
diff --git a/libmemtrack/Android.bp b/libmemtrack/Android.bp
index 98413dd..9310b24 100644
--- a/libmemtrack/Android.bp
+++ b/libmemtrack/Android.bp
@@ -2,13 +2,18 @@
cc_library_shared {
name: "libmemtrack",
- srcs: ["memtrack.c"],
+ srcs: ["memtrack.cpp"],
export_include_dirs: ["include"],
local_include_dirs: ["include"],
include_dirs: ["hardware/libhardware/include"],
shared_libs: [
"libhardware",
"liblog",
+ "libbase",
+ "libhidl",
+ "libhwbinder",
+ "libutils",
+ "android.hardware.memtrack@1.0",
],
cflags: [
"-Wall",
diff --git a/libmemtrack/include/memtrack/memtrack.h b/libmemtrack/include/memtrack/memtrack.h
index 8c0ab89..2134a6f 100644
--- a/libmemtrack/include/memtrack/memtrack.h
+++ b/libmemtrack/include/memtrack/memtrack.h
@@ -35,16 +35,6 @@
struct memtrack_proc;
/**
- * memtrack_init
- *
- * Must be called once before calling any other functions. After this function
- * is called, everything else is thread-safe.
- *
- * Returns 0 on success, -errno on error.
- */
-int memtrack_init(void);
-
-/**
* memtrack_proc_new
*
* Return a new handle to hold process memory stats.
diff --git a/libmemtrack/memtrack.c b/libmemtrack/memtrack.c
deleted file mode 100644
index 29cc92c..0000000
--- a/libmemtrack/memtrack.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#define LOG_TAG "memtrack"
-
-#include <memtrack/memtrack.h>
-
-#include <errno.h>
-#include <malloc.h>
-#include <string.h>
-
-#include <android/log.h>
-#include <hardware/memtrack.h>
-
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
-
-static const memtrack_module_t *module;
-
-struct memtrack_proc {
- pid_t pid;
- struct memtrack_proc_type {
- enum memtrack_type type;
- size_t num_records;
- size_t allocated_records;
- struct memtrack_record *records;
- } types[MEMTRACK_NUM_TYPES];
-};
-
-int memtrack_init(void)
-{
- int err;
-
- if (module) {
- return 0;
- }
-
- err = hw_get_module(MEMTRACK_HARDWARE_MODULE_ID,
- (hw_module_t const**)&module);
- if (err) {
- ALOGE("Couldn't load %s module (%s)", MEMTRACK_HARDWARE_MODULE_ID,
- strerror(-err));
- return err;
- }
-
- return module->init(module);
-}
-
-struct memtrack_proc *memtrack_proc_new(void)
-{
- if (!module) {
- return NULL;
- }
-
- return calloc(sizeof(struct memtrack_proc), 1);
-}
-
-void memtrack_proc_destroy(struct memtrack_proc *p)
-{
- enum memtrack_type i;
-
- if (p) {
- for (i = 0; i < MEMTRACK_NUM_TYPES; i++) {
- free(p->types[i].records);
- }
- }
- free(p);
-}
-
-static int memtrack_proc_get_type(struct memtrack_proc_type *t,
- pid_t pid, enum memtrack_type type)
-{
- size_t num_records = t->num_records;
- int ret;
-
-retry:
- ret = module->getMemory(module, pid, type, t->records, &num_records);
- if (ret) {
- t->num_records = 0;
- return ret;
- }
- if (num_records > t->allocated_records) {
- /* Need more records than allocated */
- free(t->records);
- t->records = calloc(sizeof(*t->records), num_records);
- if (!t->records) {
- return -ENOMEM;
- }
- t->allocated_records = num_records;
- goto retry;
- }
- t->num_records = num_records;
-
- return 0;
-}
-
-/* TODO: sanity checks on return values from HALs:
- * make sure no records have invalid flags set
- * - unknown flags
- * - too many flags of a single category
- * - missing ACCOUNTED/UNACCOUNTED
- * make sure there are not overlapping SHARED and SHARED_PSS records
- */
-static int memtrack_proc_sanity_check(struct memtrack_proc *p)
-{
- (void)p;
- return 0;
-}
-
-int memtrack_proc_get(struct memtrack_proc *p, pid_t pid)
-{
- enum memtrack_type i;
-
- if (!module) {
- return -EINVAL;
- }
-
- if (!p) {
- return -EINVAL;
- }
-
- p->pid = pid;
- for (i = 0; i < MEMTRACK_NUM_TYPES; i++) {
- memtrack_proc_get_type(&p->types[i], pid, i);
- }
-
- return memtrack_proc_sanity_check(p);
-}
-
-static ssize_t memtrack_proc_sum(struct memtrack_proc *p,
- enum memtrack_type types[], size_t num_types,
- unsigned int flags)
-{
- ssize_t sum = 0;
- size_t i;
- size_t j;
-
- for (i = 0; i < num_types; i++) {
- enum memtrack_type type = types[i];
- for (j = 0; j < p->types[type].num_records; j++) {
- if ((p->types[type].records[j].flags & flags) == flags) {
- sum += p->types[type].records[j].size_in_bytes;
- }
- }
- }
-
- return sum;
-}
-
-ssize_t memtrack_proc_graphics_total(struct memtrack_proc *p)
-{
- enum memtrack_type types[] = { MEMTRACK_TYPE_GRAPHICS };
- return memtrack_proc_sum(p, types, ARRAY_SIZE(types), 0);
-}
-
-ssize_t memtrack_proc_graphics_pss(struct memtrack_proc *p)
-{
- enum memtrack_type types[] = { MEMTRACK_TYPE_GRAPHICS };
- return memtrack_proc_sum(p, types, ARRAY_SIZE(types),
- MEMTRACK_FLAG_SMAPS_UNACCOUNTED);
-}
-
-ssize_t memtrack_proc_gl_total(struct memtrack_proc *p)
-{
- enum memtrack_type types[] = { MEMTRACK_TYPE_GL };
- return memtrack_proc_sum(p, types, ARRAY_SIZE(types), 0);
-}
-
-ssize_t memtrack_proc_gl_pss(struct memtrack_proc *p)
-{
- enum memtrack_type types[] = { MEMTRACK_TYPE_GL };
- return memtrack_proc_sum(p, types, ARRAY_SIZE(types),
- MEMTRACK_FLAG_SMAPS_UNACCOUNTED);
-}
-
-ssize_t memtrack_proc_other_total(struct memtrack_proc *p)
-{
- enum memtrack_type types[] = { MEMTRACK_TYPE_MULTIMEDIA,
- MEMTRACK_TYPE_CAMERA,
- MEMTRACK_TYPE_OTHER };
- return memtrack_proc_sum(p, types, ARRAY_SIZE(types), 0);
-}
-
-ssize_t memtrack_proc_other_pss(struct memtrack_proc *p)
-{
- enum memtrack_type types[] = { MEMTRACK_TYPE_MULTIMEDIA,
- MEMTRACK_TYPE_CAMERA,
- MEMTRACK_TYPE_OTHER };
- return memtrack_proc_sum(p, types, ARRAY_SIZE(types),
- MEMTRACK_FLAG_SMAPS_UNACCOUNTED);
-}
diff --git a/libmemtrack/memtrack.cpp b/libmemtrack/memtrack.cpp
new file mode 100644
index 0000000..9b874da
--- /dev/null
+++ b/libmemtrack/memtrack.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+#define LOG_TAG "memtrack"
+#include <android/hardware/memtrack/1.0/IMemtrack.h>
+#include <memtrack/memtrack.h>
+
+#include <errno.h>
+#include <malloc.h>
+#include <vector>
+#include <string.h>
+#include <mutex>
+
+using android::hardware::memtrack::V1_0::IMemtrack;
+using android::hardware::memtrack::V1_0::MemtrackType;
+using android::hardware::memtrack::V1_0::MemtrackRecord;
+using android::hardware::memtrack::V1_0::MemtrackFlag;
+using android::hardware::memtrack::V1_0::MemtrackStatus;
+using android::hardware::hidl_vec;
+
+struct memtrack_proc_type {
+ MemtrackType type;
+ std::vector<MemtrackRecord> records;
+};
+
+struct memtrack_proc {
+ pid_t pid;
+ memtrack_proc_type types[static_cast<int>(MemtrackType::NUM_TYPES)];
+};
+
+//TODO(b/31632518)
+static android::sp<IMemtrack> get_instance() {
+ static android::sp<IMemtrack> module = IMemtrack::getService("memtrack");
+ if (module == nullptr) {
+ ALOGE("Couldn't load memtrack module");
+ }
+ return module;
+}
+
+memtrack_proc *memtrack_proc_new(void)
+{
+ return new memtrack_proc();
+}
+
+void memtrack_proc_destroy(memtrack_proc *p)
+{
+ delete(p);
+}
+
+static int memtrack_proc_get_type(memtrack_proc_type *t,
+ pid_t pid, MemtrackType type)
+{
+ int err = 0;
+ android::sp<IMemtrack> memtrack = get_instance();
+ if (memtrack == nullptr)
+ return -1;
+
+ memtrack->getMemory(pid, type,
+ [&t, &err](MemtrackStatus status, hidl_vec<MemtrackRecord> records) {
+ if (status != MemtrackStatus::SUCCESS) {
+ err = -1;
+ t->records.resize(0);
+ }
+ t->records.resize(records.size());
+ for (size_t i = 0; i < records.size(); i++) {
+ t->records[i].sizeInBytes = records[i].sizeInBytes;
+ t->records[i].flags = records[i].flags;
+ }
+ });
+ return err;
+}
+
+/* TODO: sanity checks on return values from HALs:
+ * make sure no records have invalid flags set
+ * - unknown flags
+ * - too many flags of a single category
+ * - missing ACCOUNTED/UNACCOUNTED
+ * make sure there are not overlapping SHARED and SHARED_PSS records
+ */
+static int memtrack_proc_sanity_check(memtrack_proc* /*p*/)
+{
+ return 0;
+}
+
+int memtrack_proc_get(memtrack_proc *p, pid_t pid)
+{
+ if (!p) {
+ return -EINVAL;
+ }
+
+ p->pid = pid;
+ for (uint32_t i = 0; i < (uint32_t)MemtrackType::NUM_TYPES; i++) {
+ int ret = memtrack_proc_get_type(&p->types[i], pid, (MemtrackType)i);
+ if (ret != 0)
+ return ret;
+ }
+
+ return memtrack_proc_sanity_check(p);
+}
+
+static ssize_t memtrack_proc_sum(memtrack_proc *p,
+ const std::vector<MemtrackType>& types, uint32_t flags)
+{
+ ssize_t sum = 0;
+
+ for (size_t i = 0; i < types.size(); i++) {
+ memtrack_proc_type type = p->types[static_cast<int>(types[i])];
+ std::vector<MemtrackRecord> records = type.records;
+ for (size_t j = 0; j < records.size(); j++) {
+ if ((records[j].flags & flags) == flags) {
+ sum += records[j].sizeInBytes;
+ }
+ }
+ }
+
+ return sum;
+}
+
+ssize_t memtrack_proc_graphics_total(memtrack_proc *p)
+{
+ std::vector<MemtrackType> types = {MemtrackType::GRAPHICS};
+ return memtrack_proc_sum(p, types, 0);
+}
+
+ssize_t memtrack_proc_graphics_pss(memtrack_proc *p)
+{
+ std::vector<MemtrackType> types = { MemtrackType::GRAPHICS };
+ return memtrack_proc_sum(p, types,
+ (uint32_t)MemtrackFlag::SMAPS_UNACCOUNTED);
+}
+
+ssize_t memtrack_proc_gl_total(memtrack_proc *p)
+{
+ std::vector<MemtrackType> types = { MemtrackType::GL };
+ return memtrack_proc_sum(p, types, 0);
+}
+
+ssize_t memtrack_proc_gl_pss(memtrack_proc *p)
+{
+ std::vector<MemtrackType> types = { MemtrackType::GL };
+ return memtrack_proc_sum(p, types,
+ (uint32_t)MemtrackFlag::SMAPS_UNACCOUNTED);
+}
+
+ssize_t memtrack_proc_other_total(memtrack_proc *p)
+{
+ std::vector<MemtrackType> types = { MemtrackType::MULTIMEDIA,
+ MemtrackType::CAMERA, MemtrackType::OTHER };
+ return memtrack_proc_sum(p, types, 0);
+}
+
+ssize_t memtrack_proc_other_pss(memtrack_proc *p)
+{
+ std::vector<MemtrackType> types = { MemtrackType::MULTIMEDIA,
+ MemtrackType::CAMERA, MemtrackType::OTHER };
+ return memtrack_proc_sum(p, types,
+ (uint32_t)MemtrackFlag::SMAPS_UNACCOUNTED);
+}
diff --git a/libmemtrack/memtrack_test.c b/libmemtrack/memtrack_test.c
index eaadfa7..77c935e 100644
--- a/libmemtrack/memtrack_test.c
+++ b/libmemtrack/memtrack_test.c
@@ -82,12 +82,6 @@
(void)argc;
(void)argv;
- ret = memtrack_init();
- if (ret < 0) {
- fprintf(stderr, "failed to initialize HAL: %s (%d)\n", strerror(-ret), ret);
- exit(EXIT_FAILURE);
- }
-
ret = pm_kernel_create(&ker);
if (ret) {
fprintf(stderr, "Error creating kernel interface -- "
diff --git a/libsparse/simg_dump.py b/libsparse/simg_dump.py
index c70d45f..82a03ad 100755
--- a/libsparse/simg_dump.py
+++ b/libsparse/simg_dump.py
@@ -15,43 +15,64 @@
# limitations under the License.
from __future__ import print_function
-import getopt, posixpath, signal, struct, sys
+import csv
+import getopt
+import hashlib
+import posixpath
+import signal
+import struct
+import sys
+
def usage(argv0):
print("""
-Usage: %s [-v] sparse_image_file ...
+Usage: %s [-v] [-s] [-c <filename>] sparse_image_file ...
-v verbose output
-""" % ( argv0 ))
+ -s show sha1sum of data blocks
+ -c <filename> save .csv file of blocks
+""" % (argv0))
sys.exit(2)
-def main():
+def main():
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
me = posixpath.basename(sys.argv[0])
# Parse the command line
- verbose = 0 # -v
+ verbose = 0 # -v
+ showhash = 0 # -s
+ csvfilename = None # -c
try:
opts, args = getopt.getopt(sys.argv[1:],
- "v",
- ["verbose"])
+ "vsc:",
+ ["verbose", "showhash", "csvfile"])
except getopt.GetoptError, e:
print(e)
usage(me)
for o, a in opts:
if o in ("-v", "--verbose"):
verbose += 1
+ elif o in ("-s", "--showhash"):
+ showhash = True
+ elif o in ("-c", "--csvfile"):
+ csvfilename = a
else:
print("Unrecognized option \"%s\"" % (o))
usage(me)
- if len(args) == 0:
+ if not args:
print("No sparse_image_file specified")
usage(me)
+ if csvfilename:
+ csvfile = open(csvfilename, "wb")
+ csvwriter = csv.writer(csvfile)
+
+ output = verbose or csvfilename or showhash
+
for path in args:
- FH = open(path, 'rb')
+ FH = open(path, "rb")
header_bin = FH.read(28)
header = struct.unpack("<I4H4I", header_bin)
@@ -88,71 +109,99 @@
if image_checksum != 0:
print("checksum=0x%08X" % (image_checksum))
- if not verbose:
+ if not output:
continue
- print(" input_bytes output_blocks")
- print("chunk offset number offset number")
+
+ if verbose > 0:
+ print(" input_bytes output_blocks")
+ print("chunk offset number offset number")
+
+ if csvfilename:
+ csvwriter.writerow(["chunk", "input offset", "input bytes",
+ "output offset", "output blocks", "type", "hash"])
+
offset = 0
- for i in xrange(1,total_chunks+1):
+ for i in xrange(1, total_chunks + 1):
header_bin = FH.read(12)
header = struct.unpack("<2H2I", header_bin)
chunk_type = header[0]
- reserved1 = header[1]
chunk_sz = header[2]
total_sz = header[3]
data_sz = total_sz - 12
+ curhash = ""
+ curtype = ""
+ curpos = FH.tell()
- print("%4u %10u %10u %7u %7u" % (i, FH.tell(), data_sz, offset, chunk_sz),
- end=" ")
+ if verbose > 0:
+ print("%4u %10u %10u %7u %7u" % (i, curpos, data_sz, offset, chunk_sz),
+ end=" ")
if chunk_type == 0xCAC1:
if data_sz != (chunk_sz * blk_sz):
print("Raw chunk input size (%u) does not match output size (%u)"
% (data_sz, chunk_sz * blk_sz))
- break;
+ break
else:
- print("Raw data", end="")
- FH.read(data_sz)
+ curtype = "Raw data"
+ data = FH.read(data_sz)
+ if showhash:
+ h = hashlib.sha1()
+ h.update(data)
+ curhash = h.hexdigest()
elif chunk_type == 0xCAC2:
if data_sz != 4:
print("Fill chunk should have 4 bytes of fill, but this has %u"
- % (data_sz), end="")
- break;
+ % (data_sz))
+ break
else:
fill_bin = FH.read(4)
fill = struct.unpack("<I", fill_bin)
- print("Fill with 0x%08X" % (fill))
+ curtype = format("Fill with 0x%08X" % (fill))
+ if showhash:
+ h = hashlib.sha1()
+ data = fill_bin * (blk_sz / 4);
+ for block in xrange(chunk_sz):
+ h.update(data)
+ curhash = h.hexdigest()
elif chunk_type == 0xCAC3:
if data_sz != 0:
print("Don't care chunk input size is non-zero (%u)" % (data_sz))
- break;
+ break
else:
- print("Don't care", end="")
+ curtype = "Don't care"
elif chunk_type == 0xCAC4:
if data_sz != 4:
print("CRC32 chunk should have 4 bytes of CRC, but this has %u"
- % (data_sz), end="")
- break;
+ % (data_sz))
+ break
else:
crc_bin = FH.read(4)
crc = struct.unpack("<I", crc_bin)
- print("Unverified CRC32 0x%08X" % (crc))
+ curtype = format("Unverified CRC32 0x%08X" % (crc))
else:
- print("Unknown chunk type 0x%04X" % (chunk_type), end="")
- break;
+ print("Unknown chunk type 0x%04X" % (chunk_type))
+ break
- if verbose > 1:
- header = struct.unpack("<12B", header_bin)
- print(" (%02X%02X %02X%02X %02X%02X%02X%02X %02X%02X%02X%02X)"
- % (header[0], header[1], header[2], header[3],
- header[4], header[5], header[6], header[7],
- header[8], header[9], header[10], header[11]))
- else:
- print()
+ if verbose > 0:
+ print("%-18s" % (curtype), end=" ")
+
+ if verbose > 1:
+ header = struct.unpack("<12B", header_bin)
+ print(" (%02X%02X %02X%02X %02X%02X%02X%02X %02X%02X%02X%02X)"
+ % (header[0], header[1], header[2], header[3],
+ header[4], header[5], header[6], header[7],
+ header[8], header[9], header[10], header[11]), end=" ")
+
+ print(curhash)
+
+ if csvfilename:
+ csvwriter.writerow([i, curpos, data_sz, offset, chunk_sz, curtype,
+ curhash])
offset += chunk_sz
- print(" %10u %7u End" % (FH.tell(), offset))
+ if verbose > 0:
+ print(" %10u %7u End" % (FH.tell(), offset))
if total_blks != offset:
print("The header said we should have %u output blocks, but we saw %u"
@@ -163,6 +212,9 @@
print("There were %u bytes of extra data at the end of the file."
% (junk_len))
+ if csvfilename:
+ csvfile.close()
+
sys.exit(0)
if __name__ == "__main__":
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 26e27cf..3edc536 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -83,6 +83,7 @@
Looper::~Looper() {
close(mWakeEventFd);
+ mWakeEventFd = -1;
if (mEpollFd >= 0) {
close(mEpollFd);
}
@@ -412,7 +413,8 @@
ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
if (nWrite != sizeof(uint64_t)) {
if (errno != EAGAIN) {
- ALOGW("Could not write wake signal: %s", strerror(errno));
+ LOG_ALWAYS_FATAL("Could not write wake signal to fd %d: %s",
+ mWakeEventFd, strerror(errno));
}
}
}
diff --git a/libutils/SharedBuffer.cpp b/libutils/SharedBuffer.cpp
index 269326a..229e3f2 100644
--- a/libutils/SharedBuffer.cpp
+++ b/libutils/SharedBuffer.cpp
@@ -113,16 +113,26 @@
int32_t SharedBuffer::release(uint32_t flags) const
{
- int32_t prev = 1;
- if (onlyOwner()
- || (((prev = mRefs.fetch_sub(1, std::memory_order_release)) == 1)
- && (atomic_thread_fence(std::memory_order_acquire), true))) {
+ const bool useDealloc = ((flags & eKeepStorage) == 0);
+ if (onlyOwner()) {
+ // Since we're the only owner, our reference count goes to zero.
mRefs.store(0, std::memory_order_relaxed);
- if ((flags & eKeepStorage) == 0) {
- free(const_cast<SharedBuffer*>(this));
+ if (useDealloc) {
+ dealloc(this);
+ }
+ // As the only owner, our previous reference count was 1.
+ return 1;
+ }
+ // There's multiple owners, we need to use an atomic decrement.
+ int32_t prevRefCount = mRefs.fetch_sub(1, std::memory_order_release);
+ if (prevRefCount == 1) {
+ // We're the last reference, we need the acquire fence.
+ atomic_thread_fence(std::memory_order_acquire);
+ if (useDealloc) {
+ dealloc(this);
}
}
- return prev;
+ return prevRefCount;
}
diff --git a/libziparchive/testdata/bad_filename.zip b/libziparchive/testdata/bad_filename.zip
new file mode 100644
index 0000000..294eaf5
--- /dev/null
+++ b/libziparchive/testdata/bad_filename.zip
Binary files differ
diff --git a/libziparchive/testdata/crash.apk b/libziparchive/testdata/crash.apk
new file mode 100644
index 0000000..d6dd52d
--- /dev/null
+++ b/libziparchive/testdata/crash.apk
Binary files differ
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index a07df30..23cbff3 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -373,6 +373,11 @@
archive->hash_table_size = RoundUpPower2(1 + (num_entries * 4) / 3);
archive->hash_table = reinterpret_cast<ZipString*>(calloc(archive->hash_table_size,
sizeof(ZipString)));
+ if (archive->hash_table == nullptr) {
+ ALOGW("Zip: unable to allocate the %u-entry hash_table, entry size: %zu",
+ archive->hash_table_size, sizeof(ZipString));
+ return -1;
+ }
/*
* Walk through the central directory, adding entries to the hash
@@ -405,6 +410,11 @@
const uint16_t comment_length = cdr->comment_length;
const uint8_t* file_name = ptr + sizeof(CentralDirectoryRecord);
+ if (file_name + file_name_length > cd_end) {
+ ALOGW("Zip: file name boundary exceeds the central directory range, file_name_length: "
+ "%" PRIx16 ", cd_length: %zu", file_name_length, cd_length);
+ return -1;
+ }
/* check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters */
if (!IsValidEntryName(file_name, file_name_length)) {
return -1;
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 9dd6cc0..493a0ce 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -38,6 +38,8 @@
static const std::string kValidZip = "valid.zip";
static const std::string kLargeZip = "large.zip";
static const std::string kBadCrcZip = "bad_crc.zip";
+static const std::string kCrashApk = "crash.apk";
+static const std::string kBadFilenameZip = "bad_filename.zip";
static const std::string kUpdateZip = "dummy-update.zip";
static const std::vector<uint8_t> kATxtContents {
@@ -83,7 +85,15 @@
TEST(ziparchive, Open) {
ZipArchiveHandle handle;
ASSERT_EQ(0, OpenArchiveWrapper(kValidZip, &handle));
+ CloseArchive(handle);
+ ASSERT_EQ(-1, OpenArchiveWrapper(kBadFilenameZip, &handle));
+ CloseArchive(handle);
+}
+
+TEST(ziparchive, OutOfBound) {
+ ZipArchiveHandle handle;
+ ASSERT_EQ(-8, OpenArchiveWrapper(kCrashApk, &handle));
CloseArchive(handle);
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 64151b7..31b1821 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -302,7 +302,8 @@
# Mount shared so changes propagate into child namespaces
mount rootfs rootfs / shared rec
# Mount default storage into root namespace
- mount none /mnt/runtime/default /storage slave bind rec
+ mount none /mnt/runtime/default /storage bind rec
+ mount none none /storage slave rec
# Make sure /sys/kernel/debug (if present) is labeled properly
restorecon_recursive /sys/kernel/debug
diff --git a/sdcard/fuse.cpp b/sdcard/fuse.cpp
index 4f1ca0d..28b191a 100644
--- a/sdcard/fuse.cpp
+++ b/sdcard/fuse.cpp
@@ -997,7 +997,7 @@
{
struct node* node;
char path[PATH_MAX];
- struct fuse_open_out out;
+ struct fuse_open_out out = {};
struct handle *h;
pthread_mutex_lock(&fuse->global->lock);
@@ -1026,13 +1026,6 @@
}
out.fh = ptr_to_id(h);
out.open_flags = 0;
-
-#ifdef FUSE_SHORTCIRCUIT
- out.lower_fd = h->fd;
-#else
- out.padding = 0;
-#endif
-
fuse_reply(fuse, hdr->unique, &out, sizeof(out));
return NO_STATUS;
}
@@ -1169,7 +1162,7 @@
{
struct node* node;
char path[PATH_MAX];
- struct fuse_open_out out;
+ struct fuse_open_out out = {};
struct dirhandle *h;
pthread_mutex_lock(&fuse->global->lock);
@@ -1196,13 +1189,6 @@
}
out.fh = ptr_to_id(h);
out.open_flags = 0;
-
-#ifdef FUSE_SHORTCIRCUIT
- out.lower_fd = -1;
-#else
- out.padding = 0;
-#endif
-
fuse_reply(fuse, hdr->unique, &out, sizeof(out));
return NO_STATUS;
}
@@ -1285,11 +1271,6 @@
out.major = FUSE_KERNEL_VERSION;
out.max_readahead = req->max_readahead;
out.flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES;
-
-#ifdef FUSE_SHORTCIRCUIT
- out.flags |= FUSE_SHORTCIRCUIT;
-#endif
-
out.max_background = 32;
out.congestion_threshold = 32;
out.max_write = MAX_WRITE;