Merge "lmkd: allow client to use oom score in [-1000, 1000]"
diff --git a/adb/Android.mk b/adb/Android.mk
index 4ee1ced..e10e3ef 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -294,11 +294,15 @@
     libadbd \
     libbase \
     libfs_mgr \
+    libfec \
+    libfec_rs \
     liblog \
     libmincrypt \
     libselinux \
     libext4_utils_static \
+    libsquashfs_utils \
     libcutils \
     libbase \
+    libcrypto_static
 
 include $(BUILD_EXECUTABLE)
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index 84e3db6..6928a90 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -43,7 +43,7 @@
   ASSERT_NE(-1, tf.fd);
 
   ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   // Test reading the whole file.
   char buf[sizeof(expected)] = {};
@@ -57,7 +57,7 @@
   ASSERT_NE(-1, tf.fd);
 
   ASSERT_TRUE(android::base::WriteStringToFd(expected, tf.fd)) << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   // Test that not having enough data will fail.
   char buf[sizeof(expected) + 1] = {};
@@ -71,7 +71,7 @@
   ASSERT_NE(-1, tf.fd);
 
   ASSERT_TRUE(android::base::WriteStringToFd(input, tf.fd)) << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   // Test reading a partial file.
   char buf[sizeof(input) - 1] = {};
@@ -90,7 +90,7 @@
   // Test writing the whole string to the file.
   ASSERT_TRUE(WriteFdExactly(tf.fd, expected, sizeof(expected)))
     << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   std::string s;
   ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
@@ -104,7 +104,7 @@
 
   // Test writing a partial string to the file.
   ASSERT_TRUE(WriteFdExactly(tf.fd, buf, sizeof(buf) - 2)) << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   std::string expected(buf);
   expected.pop_back();
@@ -130,7 +130,7 @@
 
   // Test writing a partial string to the file.
   ASSERT_TRUE(WriteFdExactly(tf.fd, str)) << strerror(errno);
-  ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+  ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
   std::string s;
   ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
@@ -143,7 +143,7 @@
 
     // Test writing a partial string to the file.
     ASSERT_TRUE(WriteFdFmt(tf.fd, "Foo%s%d", "bar", 123)) << strerror(errno);
-    ASSERT_EQ(0, lseek(tf.fd, SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
 
     std::string s;
     ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s));
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index fd1740d..f5188e9 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -28,10 +28,11 @@
 
 #include "adb.h"
 #include "adb_io.h"
-#include "ext4_sb.h"
 #include "fs_mgr.h"
 #include "remount_service.h"
 
+#include "fec/io.h"
+
 #define FSTAB_PREFIX "/fstab."
 struct fstab *fstab;
 
@@ -41,115 +42,50 @@
 static const bool kAllowDisableVerity = false;
 #endif
 
-static int get_target_device_size(int fd, const char *blk_device,
-                                  uint64_t *device_size)
-{
-    int data_device;
-    struct ext4_super_block sb;
-    struct fs_info info;
-
-    info.len = 0;  /* Only len is set to 0 to ask the device for real size. */
-
-    data_device = adb_open(blk_device, O_RDONLY | O_CLOEXEC);
-    if (data_device < 0) {
-        WriteFdFmt(fd, "Error opening block device (%s)\n", strerror(errno));
-        return -1;
-    }
-
-    if (lseek64(data_device, 1024, SEEK_SET) < 0) {
-        WriteFdFmt(fd, "Error seeking to superblock\n");
-        adb_close(data_device);
-        return -1;
-    }
-
-    if (adb_read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
-        WriteFdFmt(fd, "Error reading superblock\n");
-        adb_close(data_device);
-        return -1;
-    }
-
-    ext4_parse_sb(&sb, &info);
-    *device_size = info.len;
-
-    adb_close(data_device);
-    return 0;
-}
-
 /* Turn verity on/off */
 static int set_verity_enabled_state(int fd, const char *block_device,
                                     const char* mount_point, bool enable)
 {
-    uint32_t magic_number;
-    const uint32_t new_magic = enable ? VERITY_METADATA_MAGIC_NUMBER
-                                      : VERITY_METADATA_MAGIC_DISABLE;
-    uint64_t device_length = 0;
-    int device = -1;
-    int retval = -1;
-
     if (!make_block_device_writable(block_device)) {
         WriteFdFmt(fd, "Could not make block device %s writable (%s).\n",
                    block_device, strerror(errno));
-        goto errout;
+        return -1;
     }
 
-    device = adb_open(block_device, O_RDWR | O_CLOEXEC);
-    if (device == -1) {
+    fec::io fh(block_device, O_RDWR);
+
+    if (!fh) {
         WriteFdFmt(fd, "Could not open block device %s (%s).\n", block_device, strerror(errno));
-        WriteFdFmt(fd, "Maybe run adb remount?\n");
-        goto errout;
+        WriteFdFmt(fd, "Maybe run adb root?\n");
+        return -1;
     }
 
-    // find the start of the verity metadata
-    if (get_target_device_size(fd, (char*)block_device, &device_length) < 0) {
-        WriteFdFmt(fd, "Could not get target device size.\n");
-        goto errout;
+    fec_verity_metadata metadata;
+
+    if (!fh.get_verity_metadata(metadata)) {
+        WriteFdFmt(fd, "Couldn't find verity metadata!\n");
+        return -1;
     }
 
-    if (lseek64(device, device_length, SEEK_SET) < 0) {
-        WriteFdFmt(fd, "Could not seek to start of verity metadata block.\n");
-        goto errout;
-    }
-
-    // check the magic number
-    if (adb_read(device, &magic_number, sizeof(magic_number)) != sizeof(magic_number)) {
-        WriteFdFmt(fd, "Couldn't read magic number!\n");
-        goto errout;
-    }
-
-    if (!enable && magic_number == VERITY_METADATA_MAGIC_DISABLE) {
+    if (!enable && metadata.disabled) {
         WriteFdFmt(fd, "Verity already disabled on %s\n", mount_point);
-        goto errout;
+        return -1;
     }
 
-    if (enable && magic_number == VERITY_METADATA_MAGIC_NUMBER) {
+    if (enable && !metadata.disabled) {
         WriteFdFmt(fd, "Verity already enabled on %s\n", mount_point);
-        goto errout;
+        return -1;
     }
 
-    if (magic_number != VERITY_METADATA_MAGIC_NUMBER
-            && magic_number != VERITY_METADATA_MAGIC_DISABLE) {
-        WriteFdFmt(fd, "Couldn't find verity metadata at offset %" PRIu64 "!\n", device_length);
-        goto errout;
-    }
-
-    if (lseek64(device, device_length, SEEK_SET) < 0) {
-        WriteFdFmt(fd, "Could not seek to start of verity metadata block.\n");
-        goto errout;
-    }
-
-    if (adb_write(device, &new_magic, sizeof(new_magic)) != sizeof(new_magic)) {
+    if (!fh.set_verity_status(enable)) {
         WriteFdFmt(fd, "Could not set verity %s flag on device %s with error %s\n",
                    enable ? "enabled" : "disabled",
                    block_device, strerror(errno));
-        goto errout;
+        return -1;
     }
 
     WriteFdFmt(fd, "Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point);
-    retval = 0;
-errout:
-    if (device != -1)
-        adb_close(device);
-    return retval;
+    return 0;
 }
 
 void set_verity_enabled_state_service(int fd, void* cookie)
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 501a75a..51d09a6 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -319,6 +319,9 @@
 
 #define getcwd adb_getcwd
 
+char* adb_strerror(int err);
+#define strerror adb_strerror
+
 // Convert from UTF-8 to UTF-16, typically used to convert char strings into
 // wchar_t strings that can be passed to wchar_t-based OS and C Runtime APIs
 // on Windows.
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 994b851..fd75320 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -556,6 +556,82 @@
     return 0;
 }
 
+// Overrides strerror() to handle error codes not supported by the Windows C
+// Runtime (MSVCRT.DLL).
+char* adb_strerror(int err) {
+    // sysdeps.h defines strerror to adb_strerror, but in this function, we
+    // want to call the real C Runtime strerror().
+#pragma push_macro("strerror")
+#undef strerror
+    const int saved_err = errno;      // Save because we overwrite it later.
+
+    // Lookup the string for an unknown error.
+    char* errmsg = strerror(-1);
+    char unknown_error[(errmsg == nullptr ? 0 : strlen(errmsg)) + 1];
+    strcpy(unknown_error, errmsg == nullptr ? "" : errmsg);
+
+    // Lookup the string for this error to see if the C Runtime has it.
+    errmsg = strerror(err);
+    if ((errmsg != nullptr) && strcmp(errmsg, unknown_error)) {
+        // The CRT returned an error message and it is different than the error
+        // message for an unknown error, so it is probably valid, so use it.
+    } else {
+        // Check if we have a string for this error code.
+        const char* custom_msg = nullptr;
+        switch (err) {
+#pragma push_macro("ERR")
+#undef ERR
+#define ERR(errnum, desc) case errnum: custom_msg = desc; break
+            // These error strings are from AOSP bionic/libc/include/sys/_errdefs.h.
+            // Note that these cannot be longer than 94 characters because we
+            // pass this to _strerror() which has that requirement.
+            ERR(ECONNRESET,    "Connection reset by peer");
+            ERR(EHOSTUNREACH,  "No route to host");
+            ERR(ENETDOWN,      "Network is down");
+            ERR(ENETRESET,     "Network dropped connection because of reset");
+            ERR(ENOBUFS,       "No buffer space available");
+            ERR(ENOPROTOOPT,   "Protocol not available");
+            ERR(ENOTCONN,      "Transport endpoint is not connected");
+            ERR(ENOTSOCK,      "Socket operation on non-socket");
+            ERR(EOPNOTSUPP,    "Operation not supported on transport endpoint");
+#pragma pop_macro("ERR")
+        }
+
+        if (custom_msg != nullptr) {
+            // Use _strerror() to write our string into the writable per-thread
+            // buffer used by strerror()/_strerror(). _strerror() appends the
+            // msg for the current value of errno, so set errno to a consistent
+            // value for every call so that our code-path is always the same.
+            errno = 0;
+            errmsg = _strerror(custom_msg);
+            const size_t custom_msg_len = strlen(custom_msg);
+            // Just in case _strerror() returned a read-only string, check if
+            // the returned string starts with our custom message because that
+            // implies that the string is not read-only.
+            if ((errmsg != nullptr) &&
+                !strncmp(custom_msg, errmsg, custom_msg_len)) {
+                // _strerror() puts other text after our custom message, so
+                // remove that by terminating after our message.
+                errmsg[custom_msg_len] = '\0';
+            } else {
+                // For some reason nullptr was returned or a pointer to a
+                // read-only string was returned, so fallback to whatever
+                // strerror() can muster (probably "Unknown error" or some
+                // generic CRT error string).
+                errmsg = strerror(err);
+            }
+        } else {
+            // We don't have a custom message, so use whatever strerror(err)
+            // returned earlier.
+        }
+    }
+
+    errno = saved_err;  // restore
+
+    return errmsg;
+#pragma pop_macro("strerror")
+}
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -567,18 +643,38 @@
 #undef setsockopt
 
 static void _socket_set_errno( const DWORD err ) {
-    // The Windows C Runtime (MSVCRT.DLL) strerror() does not support a lot of
-    // POSIX and socket error codes, so this can only meaningfully map so much.
+    // Because the Windows C Runtime (MSVCRT.DLL) strerror() does not support a
+    // lot of POSIX and socket error codes, some of the resulting error codes
+    // are mapped to strings by adb_strerror() above.
     switch ( err ) {
     case 0:              errno = 0; break;
+    // Don't map WSAEINTR since that is only for Winsock 1.1 which we don't use.
+    // case WSAEINTR:    errno = EINTR; break;
+    case WSAEFAULT:      errno = EFAULT; break;
+    case WSAEINVAL:      errno = EINVAL; break;
+    case WSAEMFILE:      errno = EMFILE; break;
     // Mapping WSAEWOULDBLOCK to EAGAIN is absolutely critical because
     // non-blocking sockets can cause an error code of WSAEWOULDBLOCK and
     // callers check specifically for EAGAIN.
     case WSAEWOULDBLOCK: errno = EAGAIN; break;
-    case WSAEINTR:       errno = EINTR; break;
-    case WSAEFAULT:      errno = EFAULT; break;
-    case WSAEINVAL:      errno = EINVAL; break;
-    case WSAEMFILE:      errno = EMFILE; break;
+    case WSAENOTSOCK:    errno = ENOTSOCK; break;
+    case WSAENOPROTOOPT: errno = ENOPROTOOPT; break;
+    case WSAEOPNOTSUPP:  errno = EOPNOTSUPP; break;
+    case WSAENETDOWN:    errno = ENETDOWN; break;
+    case WSAENETRESET:   errno = ENETRESET; break;
+    // Map WSAECONNABORTED to EPIPE instead of ECONNABORTED because POSIX seems
+    // to use EPIPE for these situations and there are some callers that look
+    // for EPIPE.
+    case WSAECONNABORTED: errno = EPIPE; break;
+    case WSAECONNRESET:  errno = ECONNRESET; break;
+    case WSAENOBUFS:     errno = ENOBUFS; break;
+    case WSAENOTCONN:    errno = ENOTCONN; break;
+    // Don't map WSAETIMEDOUT because we don't currently use SO_RCVTIMEO or
+    // SO_SNDTIMEO which would cause WSAETIMEDOUT to be returned. Future
+    // considerations: Reportedly send() can return zero on timeout, and POSIX
+    // code may expect EAGAIN instead of ETIMEDOUT on timeout.
+    // case WSAETIMEDOUT: errno = ETIMEDOUT; break;
+    case WSAEHOSTUNREACH: errno = EHOSTUNREACH; break;
     default:
         errno = EINVAL;
         D( "_socket_set_errno: mapping Windows error code %lu to errno %d",
@@ -655,8 +751,12 @@
     int  result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
     if (result == SOCKET_ERROR) {
         const DWORD err = WSAGetLastError();
-        D("send fd %d failed: %s", _fh_to_int(f),
-          SystemErrorCodeToString(err).c_str());
+        // WSAEWOULDBLOCK is normal with a non-blocking socket, so don't trace
+        // that to reduce spam and confusion.
+        if (err != WSAEWOULDBLOCK) {
+            D("send fd %d failed: %s", _fh_to_int(f),
+              SystemErrorCodeToString(err).c_str());
+        }
         _socket_set_errno(err);
         result = -1;
     } else {
diff --git a/adb/sysdeps_win32_test.cpp b/adb/sysdeps_win32_test.cpp
index cc3ac5c..66d1ba8 100755
--- a/adb/sysdeps_win32_test.cpp
+++ b/adb/sysdeps_win32_test.cpp
@@ -67,3 +67,29 @@
         EXPECT_GT(strlen(path_val), 0);
     }
 }
+
+void TestAdbStrError(int err, const char* expected) {
+    errno = 12345;
+    const char* result = adb_strerror(err);
+    // Check that errno is not overwritten.
+    EXPECT_EQ(12345, errno);
+    EXPECT_STREQ(expected, result);
+}
+
+TEST(sysdeps_win32, adb_strerror) {
+    // Test an error code that should not have a mapped string. Use an error
+    // code that is not used by the internal implementation of adb_strerror().
+    TestAdbStrError(-2, "Unknown error");
+    // adb_strerror() uses -1 internally, so test that it can still be passed
+    // as a parameter.
+    TestAdbStrError(-1, "Unknown error");
+    // Test very big, positive unknown error.
+    TestAdbStrError(1000000, "Unknown error");
+    // Test success case.
+    TestAdbStrError(0, "No error");
+    // Test error that regular strerror() should have a string for.
+    TestAdbStrError(EPERM, "Operation not permitted");
+    // Test error that regular strerror() doesn't have a string for, but that
+    // adb_strerror() returns.
+    TestAdbStrError(ECONNRESET, "Connection reset by peer");
+}
diff --git a/base/logging_test.cpp b/base/logging_test.cpp
index 9cf1aad..70f9952 100644
--- a/base/logging_test.cpp
+++ b/base/logging_test.cpp
@@ -139,7 +139,7 @@
   {
     CapturedStderr cap;
     LOG(WARNING) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -155,7 +155,7 @@
   {
     CapturedStderr cap;
     LOG(INFO) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -171,7 +171,7 @@
   {
     CapturedStderr cap;
     LOG(DEBUG) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -182,7 +182,7 @@
     android::base::ScopedLogSeverity severity(android::base::DEBUG);
     CapturedStderr cap;
     LOG(DEBUG) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -202,7 +202,7 @@
     LOG(INFO) << (errno = 67890);
     EXPECT_EQ(12345, errno) << "errno was not restored";
 
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -245,7 +245,7 @@
     CapturedStderr cap;
     errno = ENOENT;
     PLOG(INFO) << "foobar";
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
@@ -264,7 +264,7 @@
     CapturedStderr cap;
     errno = ENOENT;
     UNIMPLEMENTED(ERROR);
-    ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
+    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
 
     std::string output;
     android::base::ReadFdToString(cap.fd(), &output);
diff --git a/crash_reporter/Android.mk b/crash_reporter/Android.mk
index 8756956..5dd9418 100644
--- a/crash_reporter/Android.mk
+++ b/crash_reporter/Android.mk
@@ -60,6 +60,7 @@
 LOCAL_REQUIRED_MODULES := core2md \
     crash_reporter_logs.conf \
     crash_sender \
+    crash_server \
     dbus-send
 LOCAL_INIT_RC := crash_reporter.rc
 LOCAL_RTTI_FLAG := -frtti
@@ -92,6 +93,23 @@
 LOCAL_SRC_FILES := $(warn_collector_src)
 include $(BUILD_EXECUTABLE)
 
+# /etc/os-release.d/crash_server configuration file.
+# ========================================================
+ifdef OSRELEASED_DIRECTORY
+include $(CLEAR_VARS)
+LOCAL_MODULE := crash_server
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/$(OSRELEASED_DIRECTORY)
+include $(BUILD_SYSTEM)/base_rules.mk
+
+# If the crash server isn't set, use a blank value.  crash_sender
+# will log it as a configuration error.
+$(LOCAL_BUILT_MODULE): BRILLO_CRASH_SERVER ?= ""
+$(LOCAL_BUILT_MODULE):
+	$(hide)mkdir -p $(dir $@)
+	echo $(BRILLO_CRASH_SERVER) > $@
+endif
+
 # Crash reporter logs conf file.
 # ========================================================
 include $(CLEAR_VARS)
diff --git a/crash_reporter/crash_sender b/crash_reporter/crash_sender
index 1f58792..5b859a8 100755
--- a/crash_reporter/crash_sender
+++ b/crash_reporter/crash_sender
@@ -78,6 +78,9 @@
 # The weave configuration file.
 WEAVE_CONF_FILE="/etc/weaved/weaved.conf"
 
+# The os-release.d folder.
+OSRELEASED_FOLDER="/etc/os-release.d"
+
 # The syslog tag for all logging we emit.
 TAG="$(basename $0)[$$]"
 
@@ -256,7 +259,12 @@
 get_key_value() {
   local file="$1" key="$2" value
 
-  if [ -f "${file}" ]; then
+  if [ -f "${file}/${key}" ]; then
+    # Get the value from a folder where each key is its own file.  The key
+    # file's entire contents is the value.
+    value=$(cat "${file}/${key}")
+  elif [ -f "${file}" ]; then
+    # Get the value from a file that has multiple key=value combinations.
     # Return the first entry.  There shouldn't be more than one anyways.
     # Substr at length($1) + 2 skips past the key and following = sign (awk
     # uses 1-based indexes), but preserves embedded = characters.
@@ -291,7 +299,7 @@
   local report_payload="$(get_key_value "${meta_path}" "payload")"
   local kind="$(get_kind "${meta_path}")"
   local exec_name="$(get_key_value "${meta_path}" "exec_name")"
-  local url="$(getprop crash_reporter.server)"
+  local url="$(get_key_value "${OSRELEASED_FOLDER}" "crash_server")"
   local bdk_version="$(get_key_value "${meta_path}" "bdk_version")"
   local hwclass="$(get_hardware_class)"
   local write_payload_size="$(get_key_value "${meta_path}" "payload_size")"
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index b47199f..28fff3f 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -1,49 +1,59 @@
 # Copyright 2011 The Android Open Source Project
 
 LOCAL_PATH:= $(call my-dir)
+
+common_static_libraries := \
+    liblogwrap \
+    libfec \
+    libfec_rs \
+    libbase \
+    libmincrypt \
+    libcrypto_static \
+    libext4_utils_static \
+    libsquashfs_utils
+
 include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.cpp fs_mgr_fstab.c
-LOCAL_SRC_FILES += fs_mgr_format.c fs_mgr_slotselect.c
-
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include \
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+LOCAL_SRC_FILES:= \
+    fs_mgr.c \
+    fs_mgr_format.c \
+    fs_mgr_fstab.c \
+    fs_mgr_slotselect.c \
+    fs_mgr_verity.cpp
+LOCAL_C_INCLUDES := \
+    $(LOCAL_PATH)/include \
     system/vold \
     system/extras/ext4_utils \
-    external/openssl/include
-
+    external/openssl/include \
+    bootable/recovery
 LOCAL_MODULE:= libfs_mgr
-LOCAL_STATIC_LIBRARIES := liblogwrap libmincrypt libext4_utils_static libsquashfs_utils libbase
-LOCAL_C_INCLUDES += system/extras/ext4_utils system/extras/squashfs_utils \
-	bootable/recovery
+LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
 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_STATIC_LIBRARY)
 
-
-
 include $(CLEAR_VARS)
-
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
 LOCAL_SRC_FILES:= fs_mgr_main.c
-
 LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-
 LOCAL_MODULE:= fs_mgr
-
 LOCAL_MODULE_TAGS := optional
 LOCAL_FORCE_STATIC_EXECUTABLE := true
 LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin
 LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
-
-LOCAL_STATIC_LIBRARIES := libfs_mgr liblogwrap libcutils liblog libc libmincrypt libext4_utils_static libsquashfs_utils libbase
-LOCAL_STATIC_LIBRARIES += libsparse_static libz libselinux
+LOCAL_STATIC_LIBRARIES := libfs_mgr \
+    $(common_static_libraries) \
+    libcutils \
+    liblog \
+    libc \
+    libsparse_static \
+    libz \
+    libselinux
 LOCAL_CXX_STL := libc++_static
-
 LOCAL_CFLAGS := -Werror
-
 include $(BUILD_EXECUTABLE)
-
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 8f7c6a2..c358982 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -38,8 +38,7 @@
 #include "mincrypt/sha.h"
 #include "mincrypt/sha256.h"
 
-#include "ext4_sb.h"
-#include "squashfs_utils.h"
+#include "fec/io.h"
 
 #include "fs_mgr.h"
 #include "fs_mgr_priv.h"
@@ -47,11 +46,19 @@
 
 #define FSTAB_PREFIX "/fstab."
 
-#define VERITY_METADATA_SIZE 32768
 #define VERITY_TABLE_RSA_KEY "/verity_key"
 #define VERITY_TABLE_HASH_IDX 8
 #define VERITY_TABLE_SALT_IDX 9
 
+#define VERITY_TABLE_OPT_RESTART "restart_on_corruption"
+#define VERITY_TABLE_OPT_LOGGING "ignore_corruption"
+#define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks"
+
+#define VERITY_TABLE_OPT_FEC_FORMAT \
+    "use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 \
+    " fec_roots %u " VERITY_TABLE_OPT_IGNZERO
+#define VERITY_TABLE_OPT_FEC_ARGS 9
+
 #define METADATA_MAGIC 0x01564c54
 #define METADATA_TAG_MAX_LENGTH 63
 #define METADATA_EOD "eod"
@@ -92,7 +99,7 @@
     }
 
     if (!fread(key, sizeof(*key), 1, f)) {
-        ERROR("Could not read key!");
+        ERROR("Could not read key!\n");
         fclose(f);
         free(key);
         return NULL;
@@ -109,7 +116,8 @@
     return key;
 }
 
-static int verify_table(char *signature, char *table, int table_length)
+static int verify_table(const uint8_t *signature, const char *table,
+        uint32_t table_length)
 {
     RSAPublicKey *key;
     uint8_t hash_buf[SHA256_DIGEST_SIZE];
@@ -121,17 +129,17 @@
     // Now get the public key from the keyfile
     key = load_key(VERITY_TABLE_RSA_KEY);
     if (!key) {
-        ERROR("Couldn't load verity keys");
+        ERROR("Couldn't load verity keys\n");
         goto out;
     }
 
     // verify the result
     if (!RSA_verify(key,
-                    (uint8_t*) signature,
+                    signature,
                     RSANUMBYTES,
                     (uint8_t*) hash_buf,
                     SHA256_DIGEST_SIZE)) {
-        ERROR("Couldn't verify table.");
+        ERROR("Couldn't verify table\n");
         goto out;
     }
 
@@ -142,11 +150,11 @@
     return retval;
 }
 
-static int invalidate_table(char *table, int table_length)
+static int invalidate_table(char *table, size_t table_length)
 {
-    int n = 0;
-    int idx = 0;
-    int cleared = 0;
+    size_t n = 0;
+    size_t idx = 0;
+    size_t cleared = 0;
 
     while (n < table_length) {
         if (table[n++] == ' ') {
@@ -169,177 +177,6 @@
     return -1;
 }
 
-static int squashfs_get_target_device_size(char *blk_device, uint64_t *device_size)
-{
-    struct squashfs_info sq_info;
-
-    if (squashfs_parse_sb(blk_device, &sq_info) >= 0) {
-        *device_size = sq_info.bytes_used_4K_padded;
-        return 0;
-    } else {
-        return -1;
-    }
-}
-
-static int ext4_get_target_device_size(char *blk_device, uint64_t *device_size)
-{
-    int data_device;
-    struct ext4_super_block sb;
-    struct fs_info info;
-
-    info.len = 0;  /* Only len is set to 0 to ask the device for real size. */
-
-    data_device = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC));
-    if (data_device == -1) {
-        ERROR("Error opening block device (%s)", strerror(errno));
-        return -1;
-    }
-
-    if (TEMP_FAILURE_RETRY(lseek64(data_device, 1024, SEEK_SET)) < 0) {
-        ERROR("Error seeking to superblock");
-        close(data_device);
-        return -1;
-    }
-
-    if (!android::base::ReadFully(data_device, &sb, sizeof(sb))) {
-        ERROR("Error reading superblock");
-        close(data_device);
-        return -1;
-    }
-
-    ext4_parse_sb(&sb, &info);
-    *device_size = info.len;
-
-    close(data_device);
-    return 0;
-}
-
-static int get_fs_size(char *fs_type, char *blk_device, uint64_t *device_size) {
-    if (!strcmp(fs_type, "ext4")) {
-        if (ext4_get_target_device_size(blk_device, device_size) < 0) {
-            ERROR("Failed to get ext4 fs size on %s.", blk_device);
-            return -1;
-        }
-    } else if (!strcmp(fs_type, "squashfs")) {
-        if (squashfs_get_target_device_size(blk_device, device_size) < 0) {
-            ERROR("Failed to get squashfs fs size on %s.", blk_device);
-            return -1;
-        }
-    } else {
-        ERROR("%s: Unsupported filesystem for verity.", fs_type);
-        return -1;
-    }
-    return 0;
-}
-
-static int read_verity_metadata(uint64_t device_size, char *block_device, char **signature,
-        char **table)
-{
-    unsigned magic_number;
-    unsigned table_length;
-    int protocol_version;
-    int device;
-    int retval = FS_MGR_SETUP_VERITY_FAIL;
-
-    *signature = NULL;
-
-    if (table) {
-        *table = NULL;
-    }
-
-    device = TEMP_FAILURE_RETRY(open(block_device, O_RDONLY | O_CLOEXEC));
-    if (device == -1) {
-        ERROR("Could not open block device %s (%s).\n", block_device, strerror(errno));
-        goto out;
-    }
-
-    if (TEMP_FAILURE_RETRY(lseek64(device, device_size, SEEK_SET)) < 0) {
-        ERROR("Could not seek to start of verity metadata block.\n");
-        goto out;
-    }
-    // check the magic number
-    if (!android::base::ReadFully(device, &magic_number, sizeof(magic_number))) {
-        ERROR("Couldn't read magic number!\n");
-        goto out;
-    }
-
-#ifdef ALLOW_ADBD_DISABLE_VERITY
-    if (magic_number == VERITY_METADATA_MAGIC_DISABLE) {
-        retval = FS_MGR_SETUP_VERITY_DISABLED;
-        INFO("Attempt to cleanly disable verity - only works in USERDEBUG");
-        goto out;
-    }
-#endif
-
-    if (magic_number != VERITY_METADATA_MAGIC_NUMBER) {
-        ERROR("Couldn't find verity metadata at offset %" PRIu64 "!\n", device_size);
-        goto out;
-    }
-
-    // check the protocol version
-    if (!android::base::ReadFully(device, &protocol_version,
-            sizeof(protocol_version))) {
-        ERROR("Couldn't read verity metadata protocol version!\n");
-        goto out;
-    }
-    if (protocol_version != 0) {
-        ERROR("Got unknown verity metadata protocol version %d!\n", protocol_version);
-        goto out;
-    }
-
-    // get the signature
-    *signature = (char*) malloc(RSANUMBYTES);
-    if (!*signature) {
-        ERROR("Couldn't allocate memory for signature!\n");
-        goto out;
-    }
-    if (!android::base::ReadFully(device, *signature, RSANUMBYTES)) {
-        ERROR("Couldn't read signature from verity metadata!\n");
-        goto out;
-    }
-
-    if (!table) {
-        retval = FS_MGR_SETUP_VERITY_SUCCESS;
-        goto out;
-    }
-
-    // get the size of the table
-    if (!android::base::ReadFully(device, &table_length, sizeof(table_length))) {
-        ERROR("Couldn't get the size of the verity table from metadata!\n");
-        goto out;
-    }
-
-    // get the table + null terminator
-    *table = static_cast<char*>(malloc(table_length + 1));
-    if (!*table) {
-        ERROR("Couldn't allocate memory for verity table!\n");
-        goto out;
-    }
-    if (!android::base::ReadFully(device, *table, table_length)) {
-        ERROR("Couldn't read the verity table from metadata!\n");
-        goto out;
-    }
-
-    (*table)[table_length] = 0;
-    retval = FS_MGR_SETUP_VERITY_SUCCESS;
-
-out:
-    if (device != -1)
-        close(device);
-
-    if (retval != FS_MGR_SETUP_VERITY_SUCCESS) {
-        free(*signature);
-        *signature = NULL;
-
-        if (table) {
-            free(*table);
-            *table = NULL;
-        }
-    }
-
-    return retval;
-}
-
 static void verity_ioctl_init(struct dm_ioctl *io, char *name, unsigned flags)
 {
     memset(io, 0, DM_BUF_SIZE);
@@ -379,8 +216,76 @@
     return 0;
 }
 
-static int load_verity_table(struct dm_ioctl *io, char *name, uint64_t device_size, int fd, char *table,
-        int mode)
+struct verity_table_params {
+    const char *table;
+    int mode;
+    struct fec_ecc_metadata ecc;
+    const char *ecc_dev;
+};
+
+typedef bool (*format_verity_table_func)(char *buf, const size_t bufsize,
+        const struct verity_table_params *params);
+
+static bool format_verity_table(char *buf, const size_t bufsize,
+        const struct verity_table_params *params)
+{
+    const char *mode_flag = NULL;
+    int res = -1;
+
+    if (params->mode == VERITY_MODE_RESTART) {
+        mode_flag = VERITY_TABLE_OPT_RESTART;
+    } else if (params->mode == VERITY_MODE_LOGGING) {
+        mode_flag = VERITY_TABLE_OPT_LOGGING;
+    }
+
+    if (params->ecc.valid) {
+        if (mode_flag) {
+            res = snprintf(buf, bufsize,
+                    "%s %u %s " VERITY_TABLE_OPT_FEC_FORMAT,
+                    params->table, 1 + VERITY_TABLE_OPT_FEC_ARGS, mode_flag, params->ecc_dev,
+                    params->ecc.start / FEC_BLOCKSIZE, params->ecc.blocks, params->ecc.roots);
+        } else {
+            res = snprintf(buf, bufsize,
+                    "%s %u " VERITY_TABLE_OPT_FEC_FORMAT,
+                    params->table, VERITY_TABLE_OPT_FEC_ARGS, params->ecc_dev,
+                    params->ecc.start / FEC_BLOCKSIZE, params->ecc.blocks, params->ecc.roots);
+        }
+    } else if (mode_flag) {
+        res = snprintf(buf, bufsize, "%s 2 " VERITY_TABLE_OPT_IGNZERO " %s", params->table,
+                    mode_flag);
+    } else {
+        res = strlcpy(buf, params->table, bufsize);
+    }
+
+    if (res < 0 || (size_t)res >= bufsize) {
+        ERROR("Error building verity table; insufficient buffer size?\n");
+        return false;
+    }
+
+    return true;
+}
+
+static bool format_legacy_verity_table(char *buf, const size_t bufsize,
+        const struct verity_table_params *params)
+{
+    int res;
+
+    if (params->mode == VERITY_MODE_EIO) {
+        res = strlcpy(buf, params->table, bufsize);
+    } else {
+        res = snprintf(buf, bufsize, "%s %d", params->table, params->mode);
+    }
+
+    if (res < 0 || (size_t)res >= bufsize) {
+        ERROR("Error building verity table; insufficient buffer size?\n");
+        return false;
+    }
+
+    return true;
+}
+
+static int load_verity_table(struct dm_ioctl *io, char *name, uint64_t device_size, int fd,
+        const struct verity_table_params *params, format_verity_table_func format)
 {
     char *verity_params;
     char *buffer = (char*) io;
@@ -390,35 +295,32 @@
 
     struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
 
-    // set tgt arguments here
+    // set tgt arguments
     io->target_count = 1;
-    tgt->status=0;
-    tgt->sector_start=0;
-    tgt->length=device_size/512;
+    tgt->status = 0;
+    tgt->sector_start = 0;
+    tgt->length = device_size / 512;
     strcpy(tgt->target_type, "verity");
 
-    // build the verity params here
+    // build the verity params
     verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
     bufsize = DM_BUF_SIZE - (verity_params - buffer);
 
-    if (mode == VERITY_MODE_EIO) {
-        // allow operation with older dm-verity drivers that are unaware
-        // of the mode parameter by omitting it; this also means that we
-        // cannot use logging mode with these drivers, they always cause
-        // an I/O error for corrupted blocks
-        strcpy(verity_params, table);
-    } else if (snprintf(verity_params, bufsize, "%s %d", table, mode) < 0) {
+    if (!format(verity_params, bufsize, params)) {
+        ERROR("Failed to format verity parameters\n");
         return -1;
     }
 
+    INFO("loading verity table: '%s'", verity_params);
+
     // set next target boundary
     verity_params += strlen(verity_params) + 1;
-    verity_params = (char*) (((unsigned long)verity_params + 7) & ~8);
+    verity_params = (char*)(((unsigned long)verity_params + 7) & ~8);
     tgt->next = verity_params - buffer;
 
     // send the ioctl to load the verity table
     if (ioctl(fd, DM_TABLE_LOAD, io)) {
-        ERROR("Error loading verity table (%s)", strerror(errno));
+        ERROR("Error loading verity table (%s)\n", strerror(errno));
         return -1;
     }
 
@@ -703,28 +605,31 @@
 static int compare_last_signature(struct fstab_rec *fstab, int *match)
 {
     char tag[METADATA_TAG_MAX_LENGTH + 1];
-    char *signature = NULL;
     int fd = -1;
     int rc = -1;
+    off64_t offset = 0;
+    struct fec_handle *f = NULL;
+    struct fec_verity_metadata verity;
     uint8_t curr[SHA256_DIGEST_SIZE];
     uint8_t prev[SHA256_DIGEST_SIZE];
-    off64_t offset = 0;
-    uint64_t device_size;
 
     *match = 1;
 
-    // get verity filesystem size
-    if (get_fs_size(fstab->fs_type, fstab->blk_device, &device_size) < 0) {
-        ERROR("Failed to get filesystem size\n");
+    if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
+            FEC_DEFAULT_ROOTS) == -1) {
+        ERROR("Failed to open '%s' (%s)\n", fstab->blk_device,
+            strerror(errno));
+        return rc;
+    }
+
+    // read verity metadata
+    if (fec_verity_get_metadata(f, &verity) == -1) {
+        ERROR("Failed to get verity metadata '%s' (%s)\n", fstab->blk_device,
+            strerror(errno));
         goto out;
     }
 
-    if (read_verity_metadata(device_size, fstab->blk_device, &signature, NULL) < 0) {
-        ERROR("Failed to read verity signature from %s\n", fstab->mount_point);
-        goto out;
-    }
-
-    SHA256_hash(signature, RSANUMBYTES, curr);
+    SHA256_hash(verity.signature, RSANUMBYTES, curr);
 
     if (snprintf(tag, sizeof(tag), VERITY_LASTSIG_TAG "_%s",
             basename(fstab->mount_point)) >= (int)sizeof(tag)) {
@@ -766,12 +671,7 @@
     rc = 0;
 
 out:
-    free(signature);
-
-    if (fd != -1) {
-        close(fd);
-    }
-
+    fec_close(f);
     return rc;
 }
 
@@ -884,6 +784,7 @@
 {
     alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
     bool use_state = true;
+    bool use_state_for_device = true;
     char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
     char *mount_point;
     char propbuf[PROPERTY_VALUE_MAX];
@@ -928,10 +829,12 @@
             continue;
         }
 
+        use_state_for_device = use_state;
+
         if (use_state) {
             if (get_verity_state_offset(&fstab->recs[i], &offset) < 0 ||
                 read_verity_state(fstab->recs[i].verity_loc, offset, &mode) < 0) {
-                continue;
+                use_state_for_device = false;
             }
         }
 
@@ -946,7 +849,7 @@
 
         status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
 
-        if (use_state && *status == 'C') {
+        if (use_state_for_device && *status == 'C') {
             if (write_verity_state(fstab->recs[i].verity_loc, offset,
                     VERITY_MODE_LOGGING) < 0) {
                 continue;
@@ -972,87 +875,105 @@
     return rc;
 }
 
-int fs_mgr_setup_verity(struct fstab_rec *fstab) {
-
+int fs_mgr_setup_verity(struct fstab_rec *fstab)
+{
     int retval = FS_MGR_SETUP_VERITY_FAIL;
     int fd = -1;
-    int mode;
-
-    char *verity_blk_name = 0;
-    char *verity_table = 0;
-    char *verity_table_signature = 0;
-    int verity_table_length = 0;
-    uint64_t device_size = 0;
+    char *invalid_table = NULL;
+    char *verity_blk_name = NULL;
+    struct fec_handle *f = NULL;
+    struct fec_verity_metadata verity;
+    struct verity_table_params params;
 
     alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
     struct dm_ioctl *io = (struct dm_ioctl *) buffer;
     char *mount_point = basename(fstab->mount_point);
 
-    // get verity filesystem size
-    if (get_fs_size(fstab->fs_type, fstab->blk_device, &device_size) < 0) {
+    if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
+            FEC_DEFAULT_ROOTS) < 0) {
+        ERROR("Failed to open '%s' (%s)\n", fstab->blk_device,
+            strerror(errno));
         return retval;
     }
 
-    // read the verity block at the end of the block device
-    // send error code up the chain so we can detect attempts to disable verity
-    retval = read_verity_metadata(device_size,
-                                  fstab->blk_device,
-                                  &verity_table_signature,
-                                  &verity_table);
-    if (retval < 0) {
+    // read verity metadata
+    if (fec_verity_get_metadata(f, &verity) < 0) {
+        ERROR("Failed to get verity metadata '%s' (%s)\n", fstab->blk_device,
+            strerror(errno));
         goto out;
     }
 
-    retval = FS_MGR_SETUP_VERITY_FAIL;
-    verity_table_length = strlen(verity_table);
+#ifdef ALLOW_ADBD_DISABLE_VERITY
+    if (verity.disabled) {
+        retval = FS_MGR_SETUP_VERITY_DISABLED;
+        INFO("Attempt to cleanly disable verity - only works in USERDEBUG\n");
+        goto out;
+    }
+#endif
+
+    // read ecc metadata
+    if (fec_ecc_get_metadata(f, &params.ecc) < 0) {
+        params.ecc.valid = false;
+    }
+
+    params.ecc_dev = fstab->blk_device;
 
     // get the device mapper fd
     if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
-        ERROR("Error opening device mapper (%s)", strerror(errno));
+        ERROR("Error opening device mapper (%s)\n", strerror(errno));
         goto out;
     }
 
     // create the device
     if (create_verity_device(io, mount_point, fd) < 0) {
-        ERROR("Couldn't create verity device!");
+        ERROR("Couldn't create verity device!\n");
         goto out;
     }
 
     // get the name of the device file
     if (get_verity_device_name(io, mount_point, fd, &verity_blk_name) < 0) {
-        ERROR("Couldn't get verity device number!");
+        ERROR("Couldn't get verity device number!\n");
         goto out;
     }
 
-    if (load_verity_state(fstab, &mode) < 0) {
+    if (load_verity_state(fstab, &params.mode) < 0) {
         /* if accessing or updating the state failed, switch to the default
          * safe mode. This makes sure the device won't end up in an endless
          * restart loop, and no corrupted data will be exposed to userspace
          * without a warning. */
-        mode = VERITY_MODE_EIO;
+        params.mode = VERITY_MODE_EIO;
     }
 
     // verify the signature on the table
-    if (verify_table(verity_table_signature,
-                            verity_table,
-                            verity_table_length) < 0) {
-        if (mode == VERITY_MODE_LOGGING) {
+    if (verify_table(verity.signature, verity.table,
+            verity.table_length) < 0) {
+        if (params.mode == VERITY_MODE_LOGGING) {
             // the user has been warned, allow mounting without dm-verity
             retval = FS_MGR_SETUP_VERITY_SUCCESS;
             goto out;
         }
 
         // invalidate root hash and salt to trigger device-specific recovery
-        if (invalidate_table(verity_table, verity_table_length) < 0) {
+        invalid_table = strdup(verity.table);
+
+        if (!invalid_table ||
+                invalidate_table(invalid_table, verity.table_length) < 0) {
             goto out;
         }
+
+        params.table = invalid_table;
+    } else {
+        params.table = verity.table;
     }
 
-    INFO("Enabling dm-verity for %s (mode %d)\n",  mount_point, mode);
+    INFO("Enabling dm-verity for %s (mode %d)\n", mount_point, params.mode);
 
     // load the verity mapping table
-    if (load_verity_table(io, mount_point, device_size, fd, verity_table,
-            mode) < 0) {
+    if (load_verity_table(io, mount_point, verity.data_size, fd, &params,
+            format_verity_table) < 0 &&
+        // try the legacy format for backwards compatibility
+        load_verity_table(io, mount_point, verity.data_size, fd, &params,
+            format_legacy_verity_table) < 0) {
         goto out;
     }
 
@@ -1081,8 +1002,8 @@
         close(fd);
     }
 
-    free(verity_table);
-    free(verity_table_signature);
+    fec_close(f);
+    free(invalid_table);
     free(verity_blk_name);
 
     return retval;
diff --git a/include/binderwrapper/binder_wrapper.h b/include/binderwrapper/binder_wrapper.h
index e57cf83..921c4ed 100644
--- a/include/binderwrapper/binder_wrapper.h
+++ b/include/binderwrapper/binder_wrapper.h
@@ -17,6 +17,8 @@
 #ifndef SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_WRAPPER_H_
 #define SYSTEM_CORE_INCLUDE_BINDERWRAPPER_BINDER_WRAPPER_H_
 
+#include <sys/types.h>
+
 #include <string>
 
 #include <base/callback.h>
@@ -68,6 +70,10 @@
   // Unregisters the callback, if any, for |binder|.
   virtual bool UnregisterForDeathNotifications(const sp<IBinder>& binder) = 0;
 
+  // When called while in a transaction, returns the caller's UID or PID.
+  virtual uid_t GetCallingUid() = 0;
+  virtual pid_t GetCallingPid() = 0;
+
  private:
   static BinderWrapper* instance_;
 };
diff --git a/include/binderwrapper/stub_binder_wrapper.h b/include/binderwrapper/stub_binder_wrapper.h
index 6e198ae..01c9648 100644
--- a/include/binderwrapper/stub_binder_wrapper.h
+++ b/include/binderwrapper/stub_binder_wrapper.h
@@ -77,6 +77,9 @@
   }
   void clear_local_binders() { local_binders_.clear(); }
 
+  void set_calling_uid(uid_t uid) { calling_uid_ = uid; }
+  void set_calling_pid(pid_t pid) { calling_pid_ = pid; }
+
   // Sets the binder to return when |service_name| is passed to GetService() or
   // WaitForService().
   void SetBinderForService(const std::string& service_name,
@@ -97,6 +100,8 @@
   bool RegisterForDeathNotifications(const sp<IBinder>& binder,
                                      const base::Closure& callback) override;
   bool UnregisterForDeathNotifications(const sp<IBinder>& binder) override;
+  uid_t GetCallingUid() override;
+  pid_t GetCallingPid() override;
 
  private:
   using ServiceMap = std::map<std::string, sp<IBinder>>;
@@ -116,6 +121,10 @@
   // death.
   std::map<sp<IBinder>, base::Closure> death_callbacks_;
 
+  // Values to return from GetCallingUid() and GetCallingPid();
+  uid_t calling_uid_;
+  pid_t calling_pid_;
+
   DISALLOW_COPY_AND_ASSIGN(StubBinderWrapper);
 };
 
diff --git a/init/Android.mk b/init/Android.mk
index c1cdc1a..8e45a7a 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -84,6 +84,8 @@
 LOCAL_STATIC_LIBRARIES := \
     libinit \
     libfs_mgr \
+    libfec \
+    libfec_rs \
     libsquashfs_utils \
     liblogwrap \
     libcutils \
@@ -94,6 +96,7 @@
     libc \
     libselinux \
     libmincrypt \
+    libcrypto_static \
     libc++_static \
     libdl \
     libsparse_static \
diff --git a/libbinderwrapper/real_binder_wrapper.cc b/libbinderwrapper/real_binder_wrapper.cc
index adff19b..1c51822 100644
--- a/libbinderwrapper/real_binder_wrapper.cc
+++ b/libbinderwrapper/real_binder_wrapper.cc
@@ -19,6 +19,7 @@
 #include <base/logging.h>
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
 namespace android {
@@ -111,4 +112,12 @@
   return true;
 }
 
+uid_t RealBinderWrapper::GetCallingUid() {
+  return IPCThreadState::self()->getCallingUid();
+}
+
+pid_t RealBinderWrapper::GetCallingPid() {
+  return IPCThreadState::self()->getCallingPid();
+}
+
 }  // namespace android
diff --git a/libbinderwrapper/real_binder_wrapper.h b/libbinderwrapper/real_binder_wrapper.h
index 8e281f2..ea08371 100644
--- a/libbinderwrapper/real_binder_wrapper.h
+++ b/libbinderwrapper/real_binder_wrapper.h
@@ -38,6 +38,8 @@
   bool RegisterForDeathNotifications(const sp<IBinder>& binder,
                                      const base::Closure& callback) override;
   bool UnregisterForDeathNotifications(const sp<IBinder>& binder) override;
+  uid_t GetCallingUid() override;
+  pid_t GetCallingPid() override;
 
  private:
   class DeathRecipient;
diff --git a/libbinderwrapper/stub_binder_wrapper.cc b/libbinderwrapper/stub_binder_wrapper.cc
index 1d24681..87c6ab7 100644
--- a/libbinderwrapper/stub_binder_wrapper.cc
+++ b/libbinderwrapper/stub_binder_wrapper.cc
@@ -22,7 +22,9 @@
 
 namespace android {
 
-StubBinderWrapper::StubBinderWrapper() = default;
+StubBinderWrapper::StubBinderWrapper()
+    : calling_uid_(-1),
+      calling_pid_(-1) {}
 
 StubBinderWrapper::~StubBinderWrapper() = default;
 
@@ -73,4 +75,12 @@
   return true;
 }
 
+uid_t StubBinderWrapper::GetCallingUid() {
+  return calling_uid_;
+}
+
+pid_t StubBinderWrapper::GetCallingPid() {
+  return calling_pid_;
+}
+
 }  // namespace android
diff --git a/libsparse/simg2img.c b/libsparse/simg2img.c
index 95e9b5b..b9b438e 100644
--- a/libsparse/simg2img.c
+++ b/libsparse/simg2img.c
@@ -40,7 +40,6 @@
 	int in;
 	int out;
 	int i;
-	int ret;
 	struct sparse_file *s;
 
 	if (argc < 3) {
@@ -71,10 +70,12 @@
 			exit(-1);
 		}
 
-		lseek(out, SEEK_SET, 0);
+		if (lseek(out, 0, SEEK_SET) == -1) {
+			perror("lseek failed");
+			exit(EXIT_FAILURE);
+		}
 
-		ret = sparse_file_write(s, out, false, false, false);
-		if (ret < 0) {
+		if (sparse_file_write(s, out, false, false, false) < 0) {
 			fprintf(stderr, "Cannot write output file\n");
 			exit(-1);
 		}
diff --git a/libsparse/sparse_read.c b/libsparse/sparse_read.c
index 9b10293..ec63850 100644
--- a/libsparse/sparse_read.c
+++ b/libsparse/sparse_read.c
@@ -18,6 +18,7 @@
 #define _FILE_OFFSET_BITS 64
 #define _LARGEFILE64_SOURCE 1
 
+#include <inttypes.h>
 #include <fcntl.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -233,7 +234,7 @@
 			ret = process_raw_chunk(s, chunk_data_size, fd, offset,
 					chunk_header->chunk_sz, cur_block, crc_ptr);
 			if (ret < 0) {
-				verbose_error(s->verbose, ret, "data block at %lld", offset);
+				verbose_error(s->verbose, ret, "data block at %" PRId64, offset);
 				return ret;
 			}
 			return chunk_header->chunk_sz;
@@ -241,7 +242,7 @@
 			ret = process_fill_chunk(s, chunk_data_size, fd,
 					chunk_header->chunk_sz, cur_block, crc_ptr);
 			if (ret < 0) {
-				verbose_error(s->verbose, ret, "fill block at %lld", offset);
+				verbose_error(s->verbose, ret, "fill block at %" PRId64, offset);
 				return ret;
 			}
 			return chunk_header->chunk_sz;
@@ -250,7 +251,7 @@
 					chunk_header->chunk_sz, cur_block, crc_ptr);
 			if (chunk_data_size != 0) {
 				if (ret < 0) {
-					verbose_error(s->verbose, ret, "skip block at %lld", offset);
+					verbose_error(s->verbose, ret, "skip block at %" PRId64, offset);
 					return ret;
 				}
 			}
@@ -258,13 +259,13 @@
 		case CHUNK_TYPE_CRC32:
 			ret = process_crc32_chunk(fd, chunk_data_size, *crc_ptr);
 			if (ret < 0) {
-				verbose_error(s->verbose, -EINVAL, "crc block at %lld",
+				verbose_error(s->verbose, -EINVAL, "crc block at %" PRId64,
 						offset);
 				return ret;
 			}
 			return 0;
 		default:
-			verbose_error(s->verbose, -EINVAL, "unknown block %04X at %lld",
+			verbose_error(s->verbose, -EINVAL, "unknown block %04X at %" PRId64,
 					chunk_header->chunk_type, offset);
 	}
 
diff --git a/libziparchive/Android.mk b/libziparchive/Android.mk
index 53c1b3b..8ff94d4 100644
--- a/libziparchive/Android.mk
+++ b/libziparchive/Android.mk
@@ -18,6 +18,10 @@
 source_files := zip_archive.cc zip_writer.cc
 test_files := zip_archive_test.cc zip_writer_test.cc entry_name_utils_test.cc
 
+# Incorrectly warns when C++11 empty brace {} initializer is used.
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61489
+common_cpp_flags := -Wno-missing-field-initializers
+
 include $(CLEAR_VARS)
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_SRC_FILES := ${source_files}
@@ -25,7 +29,7 @@
 LOCAL_SHARED_LIBRARIES := libutils libbase
 LOCAL_MODULE:= libziparchive
 LOCAL_CFLAGS := -Werror -Wall
-LOCAL_CPPFLAGS := -Wold-style-cast
+LOCAL_CPPFLAGS := -Wold-style-cast $(common_cpp_flags)
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -35,10 +39,7 @@
 LOCAL_MODULE:= libziparchive-host
 LOCAL_CFLAGS := -Werror
 LOCAL_CFLAGS_windows := -mno-ms-bitfields
-
-# Incorrectly warns when C++11 empty brace {} initializer is used.
-# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61489
-LOCAL_CFLAGS_windows += -Wno-missing-field-initializers
+LOCAL_CPPFLAGS := $(common_cpp_flags)
 
 LOCAL_MULTILIB := both
 LOCAL_MODULE_HOST_OS := darwin linux windows
@@ -51,6 +52,7 @@
 LOCAL_SHARED_LIBRARIES := libz-host liblog libbase
 LOCAL_MODULE:= libziparchive-host
 LOCAL_CFLAGS := -Werror
+LOCAL_CPPFLAGS := $(common_cpp_flags)
 LOCAL_MULTILIB := both
 include $(BUILD_HOST_SHARED_LIBRARY)
 
@@ -59,6 +61,7 @@
 LOCAL_MODULE := ziparchive-tests
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_CFLAGS := -Werror
+LOCAL_CPPFLAGS := $(common_cpp_flags)
 LOCAL_SRC_FILES := $(test_files)
 LOCAL_SHARED_LIBRARIES := liblog libbase
 LOCAL_STATIC_LIBRARIES := libziparchive libz libutils
@@ -67,9 +70,8 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := ziparchive-tests-host
 LOCAL_CPP_EXTENSION := .cc
-LOCAL_CFLAGS += \
-    -Werror \
-    -Wno-unnamed-type-template-args
+LOCAL_CFLAGS := -Werror
+LOCAL_CPPFLAGS := -Wno-unnamed-type-template-args $(common_cpp_flags)
 LOCAL_SRC_FILES := $(test_files)
 LOCAL_SHARED_LIBRARIES := libziparchive-host liblog libbase
 LOCAL_STATIC_LIBRARIES := \
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a204eab..bdc4567 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -138,23 +138,27 @@
     # sets up initial cpusets for ActivityManager
     mkdir /dev/cpuset
     mount cpuset none /dev/cpuset
-    mkdir /dev/cpuset/foreground
-    mkdir /dev/cpuset/foreground/boost
-    mkdir /dev/cpuset/background
-    # system-background is for system tasks that should only run on
-    # little cores, not on bigs
-    # to be used only by init, so don't change the permissions
-    mkdir /dev/cpuset/system-background
+
     # this ensures that the cpusets are present and usable, but the device's
     # init.rc must actually set the correct cpus
+    mkdir /dev/cpuset/foreground
     write /dev/cpuset/foreground/cpus 0
-    write /dev/cpuset/foreground/boost/cpus 0
-    write /dev/cpuset/background/cpus 0
-    write /dev/cpuset/system-background/cpus 0
     write /dev/cpuset/foreground/mems 0
+    mkdir /dev/cpuset/foreground/boost
+    write /dev/cpuset/foreground/boost/cpus 0
     write /dev/cpuset/foreground/boost/mems 0
+    mkdir /dev/cpuset/background
+    write /dev/cpuset/background/cpus 0
     write /dev/cpuset/background/mems 0
+
+    # system-background is for system tasks that should only run on
+    # little cores, not on bigs
+    # to be used only by init, so don't change system-bg permissions
+    mkdir /dev/cpuset/system-background
+    write /dev/cpuset/system-background/cpus 0
     write /dev/cpuset/system-background/mems 0
+
+    # change permissions for all cpusets we'll touch at runtime
     chown system system /dev/cpuset
     chown system system /dev/cpuset/foreground
     chown system system /dev/cpuset/foreground/boost