Merge "liblp: convert more functions to use string_view (#5)"
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index 5d10238..703eb2f 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -849,6 +849,16 @@
     return true;
 }
 
+// dirname("//foo") returns "//", so we can't do the obvious `path == "/"`.
+static bool is_root_dir(std::string_view path) {
+    for (char c : path) {
+        if (c != '/') {
+            return false;
+        }
+    }
+    return true;
+}
+
 static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath,
                                   std::string rpath, bool check_timestamps,
                                   bool list_only) {
@@ -862,8 +872,8 @@
     std::vector<copyinfo> file_list;
     std::vector<std::string> directory_list;
 
-    for (std::string dirpath = rpath; dirpath != "/"; dirpath = android::base::Dirname(dirpath)) {
-        directory_list.push_back(dirpath);
+    for (std::string path = rpath; !is_root_dir(path); path = android::base::Dirname(path)) {
+        directory_list.push_back(path);
     }
     std::reverse(directory_list.begin(), directory_list.end());
 
diff --git a/adb/test_device.py b/adb/test_device.py
index dbd80ed..32d797e 100755
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -903,6 +903,18 @@
             remote_path += '/filename'
             self.device.push(local=tmp_file.name, remote=remote_path)
 
+    def test_push_multiple_slash_root(self):
+        """Regression test for pushing to //data/local/tmp.
+
+        Bug: http://b/141311284
+        """
+        with tempfile.NamedTemporaryFile() as tmp_file:
+            tmp_file.write('\0' * 1024 * 1024)
+            tmp_file.flush()
+            remote_path = '/' + self.DEVICE_TEMP_DIR + '/test_push_multiple_slash_root'
+            self.device.shell(['rm', '-rf', remote_path])
+            self.device.push(local=tmp_file.name, remote=remote_path)
+
     def _test_pull(self, remote_file, checksum):
         tmp_write = tempfile.NamedTemporaryFile(mode='wb', delete=False)
         tmp_write.close()
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 546bce2..f452a64 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -189,7 +189,11 @@
     // will violate ODR.
     shared_libs: [],
 
-    header_libs: ["bootimg_headers"],
+    header_libs: [
+        "avb_headers",
+        "bootimg_headers",
+    ],
+
     static_libs: [
         "libziparchive",
         "libsparse",
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index a7fc628..2fe3b1a 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -51,6 +51,7 @@
 #include <utility>
 #include <vector>
 
+#include <android-base/endian.h>
 #include <android-base/file.h>
 #include <android-base/macros.h>
 #include <android-base/parseint.h>
@@ -59,6 +60,7 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <build/version.h>
+#include <libavb/libavb.h>
 #include <liblp/liblp.h>
 #include <platform_tools_version.h>
 #include <sparse/sparse.h>
@@ -919,33 +921,50 @@
     return load_buf_fd(fd.release(), buf);
 }
 
-static void rewrite_vbmeta_buffer(struct fastboot_buffer* buf) {
+static void rewrite_vbmeta_buffer(struct fastboot_buffer* buf, bool vbmeta_in_boot) {
     // Buffer needs to be at least the size of the VBMeta struct which
     // is 256 bytes.
     if (buf->sz < 256) {
         return;
     }
 
-    int fd = make_temporary_fd("vbmeta rewriting");
-
     std::string data;
     if (!android::base::ReadFdToString(buf->fd, &data)) {
         die("Failed reading from vbmeta");
     }
 
+    uint64_t vbmeta_offset = 0;
+    if (vbmeta_in_boot) {
+        // Tries to locate top-level vbmeta from boot.img footer.
+        uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE;
+        if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) {
+            die("Failed to find AVB_FOOTER at offset: %" PRId64, footer_offset);
+        }
+        const AvbFooter* footer = reinterpret_cast<const AvbFooter*>(data.c_str() + footer_offset);
+        vbmeta_offset = be64toh(footer->vbmeta_offset);
+    }
+    // Ensures there is AVB_MAGIC at vbmeta_offset.
+    if (0 != data.compare(vbmeta_offset, AVB_MAGIC_LEN, AVB_MAGIC)) {
+        die("Failed to find AVB_MAGIC at offset: %" PRId64, vbmeta_offset);
+    }
+
+    fprintf(stderr, "Rewriting vbmeta struct at offset: %" PRId64 "\n", vbmeta_offset);
+
     // There's a 32-bit big endian |flags| field at offset 120 where
     // bit 0 corresponds to disable-verity and bit 1 corresponds to
     // disable-verification.
     //
     // See external/avb/libavb/avb_vbmeta_image.h for the layout of
     // the VBMeta struct.
+    uint64_t flags_offset = 123 + vbmeta_offset;
     if (g_disable_verity) {
-        data[123] |= 0x01;
+        data[flags_offset] |= 0x01;
     }
     if (g_disable_verification) {
-        data[123] |= 0x02;
+        data[flags_offset] |= 0x02;
     }
 
+    int fd = make_temporary_fd("vbmeta rewriting");
     if (!android::base::WriteStringToFd(data, fd)) {
         die("Failed writing to modified vbmeta");
     }
@@ -954,14 +973,25 @@
     lseek(fd, 0, SEEK_SET);
 }
 
+static bool has_vbmeta_partition() {
+    std::string partition_type;
+    return fb->GetVar("partition-type:vbmeta", &partition_type) == fastboot::SUCCESS ||
+           fb->GetVar("partition-type:vbmeta_a", &partition_type) == fastboot::SUCCESS ||
+           fb->GetVar("partition-type:vbmeta_b", &partition_type) == fastboot::SUCCESS;
+}
+
 static void flash_buf(const std::string& partition, struct fastboot_buffer *buf)
 {
     sparse_file** s;
 
     // Rewrite vbmeta if that's what we're flashing and modification has been requested.
-    if ((g_disable_verity || g_disable_verification) &&
-        (partition == "vbmeta" || partition == "vbmeta_a" || partition == "vbmeta_b")) {
-        rewrite_vbmeta_buffer(buf);
+    if (g_disable_verity || g_disable_verification) {
+        if (partition == "vbmeta" || partition == "vbmeta_a" || partition == "vbmeta_b") {
+            rewrite_vbmeta_buffer(buf, false /* vbmeta_in_boot */);
+        } else if (!has_vbmeta_partition() &&
+                   (partition == "boot" || partition == "boot_a" || partition == "boot_b")) {
+            rewrite_vbmeta_buffer(buf, true /* vbmeta_in_boot */ );
+        }
     }
 
     switch (buf->type) {
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 4cdea71..449a170 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -44,9 +44,24 @@
     },
 }
 
-cc_test {
-    name: "libdm_test",
-    defaults: ["fs_mgr_defaults"],
+filegroup {
+    name: "libdm_test_srcs",
+    srcs: [
+        "dm_test.cpp",
+        "loop_control_test.cpp",
+        "test_util.cpp",
+    ],
+}
+
+cc_defaults {
+    name: "libdm_defaults",
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
     static_libs: [
         "libdm",
         "libbase",
@@ -54,9 +69,10 @@
         "libfs_mgr",
         "liblog",
     ],
-    srcs: [
-        "dm_test.cpp",
-        "loop_control_test.cpp",
-        "test_util.cpp",
-    ]
+    srcs: [":libdm_test_srcs"],
+}
+
+cc_test {
+    name: "libdm_test",
+    defaults: ["libdm_defaults"],
 }
diff --git a/fs_mgr/libdm/vts_core/Android.bp b/fs_mgr/libdm/vts_core/Android.bp
new file mode 100644
index 0000000..2eceb28
--- /dev/null
+++ b/fs_mgr/libdm/vts_core/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_test {
+    name: "vts_libdm_test",
+    defaults: ["libdm_defaults"],
+    test_suites: ["vts-core"],
+    require_root: true,
+    test_min_api_level: 29,
+}
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index b2572f6..7fee83c 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -55,9 +55,26 @@
     export_include_dirs: ["include"],
 }
 
+filegroup {
+    name: "liblp_test_srcs",
+    srcs: [
+        "builder_test.cpp",
+        "device_test.cpp",
+        "io_test.cpp",
+        "test_partition_opener.cpp",
+        "utility_test.cpp",
+    ],
+}
+
 cc_defaults {
     name: "liblp_test_defaults",
-    defaults: ["fs_mgr_defaults"],
+    sanitize: {
+        misc_undefined: ["integer"],
+    },
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
     cppflags: [
         "-Wno-unused-parameter",
     ],
@@ -71,23 +88,14 @@
         "libstorage_literals_headers",
     ],
     stl: "libc++_static",
-    srcs: [
-        "builder_test.cpp",
-        "device_test.cpp",
-        "io_test.cpp",
-        "test_partition_opener.cpp",
-        "utility_test.cpp",
-    ],
+    srcs: [":liblp_test_srcs"],
 }
 
 cc_test {
     name: "liblp_test",
     defaults: ["liblp_test_defaults"],
     test_config: "liblp_test.xml",
-    test_suites: [
-        "device-tests",
-        "vts-core",
-    ],
+    test_suites: ["device-tests"],
 }
 
 cc_test {
diff --git a/fs_mgr/liblp/vts_core/Android.bp b/fs_mgr/liblp/vts_core/Android.bp
new file mode 100644
index 0000000..7af0b9e
--- /dev/null
+++ b/fs_mgr/liblp/vts_core/Android.bp
@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_test {
+    name: "vts_core_liblp_test",
+    defaults: ["liblp_test_defaults"],
+    test_suites: ["vts-core"],
+    test_min_api_level: 29,
+}
diff --git a/init/README.md b/init/README.md
index 423c6d1..29b972d 100644
--- a/init/README.md
+++ b/init/README.md
@@ -170,6 +170,8 @@
   be changed by setting the "androidboot.console" kernel parameter. In
   all cases the leading "/dev/" should be omitted, so "/dev/tty0" would be
   specified as just "console tty0".
+  This option connects stdin, stdout, and stderr to the console. It is mutually exclusive with the
+  stdio_to_kmsg option, which only connects stdout and stderr to kmsg.
 
 `critical`
 > This is a device-critical service. If it exits more than four times in
@@ -313,6 +315,13 @@
   seclabel or computed based on the service executable file security context.
   For native executables see libcutils android\_get\_control\_socket().
 
+`stdio_to_kmsg`
+> Redirect stdout and stderr to /dev/kmsg_debug. This is useful for services that do not use native
+  Android logging during early boot and whose logs messages we want to capture. This is only enabled
+  when /dev/kmsg_debug is enabled, which is only enabled on userdebug and eng builds.
+  This is mutually exclusive with the console option, which additionally connects stdin to the
+  given console.
+
 `timeout_period <seconds>`
 > Provide a timeout after which point the service will be killed. The oneshot keyword is respected
   here, so oneshot services do not automatically restart, however all other services will.
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 45d1852..e7808a9 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -83,6 +83,9 @@
 }
 
 Result<void> ServiceParser::ParseConsole(std::vector<std::string>&& args) {
+    if (service_->proc_attr_.stdio_to_kmsg) {
+        return Error() << "'console' and 'stdio_to_kmsg' are mutually exclusive";
+    }
     service_->flags_ |= SVC_CONSOLE;
     service_->proc_attr_.console = args.size() > 1 ? "/dev/" + args[1] : "";
     return {};
@@ -429,6 +432,14 @@
     return {};
 }
 
+Result<void> ServiceParser::ParseStdioToKmsg(std::vector<std::string>&& args) {
+    if (service_->flags_ & SVC_CONSOLE) {
+        return Error() << "'stdio_to_kmsg' and 'console' are mutually exclusive";
+    }
+    service_->proc_attr_.stdio_to_kmsg = true;
+    return {};
+}
+
 // name type
 Result<void> ServiceParser::ParseFile(std::vector<std::string>&& args) {
     if (args[2] != "r" && args[2] != "w" && args[2] != "rw") {
@@ -514,6 +525,7 @@
         {"shutdown",                {1,     1,    &ServiceParser::ParseShutdown}},
         {"sigstop",                 {0,     0,    &ServiceParser::ParseSigstop}},
         {"socket",                  {3,     6,    &ServiceParser::ParseSocket}},
+        {"stdio_to_kmsg",           {0,     0,    &ServiceParser::ParseStdioToKmsg}},
         {"timeout_period",          {1,     1,    &ServiceParser::ParseTimeoutPeriod}},
         {"updatable",               {0,     0,    &ServiceParser::ParseUpdatable}},
         {"user",                    {1,     1,    &ServiceParser::ParseUser}},
diff --git a/init/service_parser.h b/init/service_parser.h
index f063102..b1281f5 100644
--- a/init/service_parser.h
+++ b/init/service_parser.h
@@ -75,6 +75,7 @@
     Result<void> ParseShutdown(std::vector<std::string>&& args);
     Result<void> ParseSigstop(std::vector<std::string>&& args);
     Result<void> ParseSocket(std::vector<std::string>&& args);
+    Result<void> ParseStdioToKmsg(std::vector<std::string>&& args);
     Result<void> ParseTimeoutPeriod(std::vector<std::string>&& args);
     Result<void> ParseFile(std::vector<std::string>&& args);
     Result<void> ParseUser(std::vector<std::string>&& args);
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index 35f2acf..93cffd8 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -16,10 +16,12 @@
 
 #include "service_utils.h"
 
+#include <fcntl.h>
 #include <grp.h>
 #include <sys/mount.h>
 #include <sys/prctl.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
@@ -121,11 +123,15 @@
     return {};
 }
 
-void ZapStdio() {
+void SetupStdio(bool stdio_to_kmsg) {
     auto fd = unique_fd{open("/dev/null", O_RDWR | O_CLOEXEC)};
-    dup2(fd, 0);
-    dup2(fd, 1);
-    dup2(fd, 2);
+    dup2(fd, STDIN_FILENO);
+    if (stdio_to_kmsg) {
+        fd.reset(open("/dev/kmsg_debug", O_WRONLY | O_CLOEXEC));
+        if (fd == -1) fd.reset(open("/dev/null", O_WRONLY | O_CLOEXEC));
+    }
+    dup2(fd, STDOUT_FILENO);
+    dup2(fd, STDERR_FILENO);
 }
 
 void OpenConsole(const std::string& console) {
@@ -238,7 +244,7 @@
         if (setpgid(0, getpid()) == -1) {
             return ErrnoError() << "setpgid failed";
         }
-        ZapStdio();
+        SetupStdio(attr.stdio_to_kmsg);
     }
 
     for (const auto& rlimit : attr.rlimits) {
diff --git a/init/service_utils.h b/init/service_utils.h
index d2e69d9..3f1071e 100644
--- a/init/service_utils.h
+++ b/init/service_utils.h
@@ -77,6 +77,7 @@
     gid_t gid;
     std::vector<gid_t> supp_gids;
     int priority;
+    bool stdio_to_kmsg;
 };
 Result<void> SetProcessAttributes(const ProcessAttributes& attr);
 
diff --git a/rootdir/avb/Android.bp b/rootdir/avb/Android.bp
new file mode 100644
index 0000000..85d2786
--- /dev/null
+++ b/rootdir/avb/Android.bp
@@ -0,0 +1,20 @@
+filegroup {
+    name: "q-gsi_avbpubkey",
+    srcs: [
+        "q-gsi.avbpubkey",
+    ],
+}
+
+filegroup {
+    name: "r-gsi_avbpubkey",
+    srcs: [
+        "r-gsi.avbpubkey",
+    ],
+}
+
+filegroup {
+    name: "s-gsi_avbpubkey",
+    srcs: [
+        "s-gsi.avbpubkey",
+    ],
+}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 0fa6efc..c61fd90 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -69,18 +69,22 @@
 service boringssl_self_test32 /system/bin/boringssl_self_test32
     setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
     reboot_on_failure reboot,boringssl-self-check-failed
+    stdio_to_kmsg
 
 service boringssl_self_test64 /system/bin/boringssl_self_test64
     setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
     reboot_on_failure reboot,boringssl-self-check-failed
+    stdio_to_kmsg
 
 service boringssl_self_test_apex32 /apex/com.android.conscrypt/bin/boringssl_self_test32
     setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
     reboot_on_failure reboot,boringssl-self-check-failed
+    stdio_to_kmsg
 
 service boringssl_self_test_apex64 /apex/com.android.conscrypt/bin/boringssl_self_test64
     setenv BORINGSSL_SELF_TEST_CREATE_FLAG true # Any nonempty value counts as true
     reboot_on_failure reboot,boringssl-self-check-failed
+    stdio_to_kmsg
 
 on init
     sysclktz 0