Merge "libsnapshot:snapuserd: Fix memory leak"
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 6bfb5f2..530e0e8 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -96,7 +96,7 @@
 
   if (std::string str = data.str(); !str.empty()) {
     buffer << "\n----- Waiting Channels: pid " << pid << " at " << get_timestamp() << " -----\n"
-           << "Cmd line: " << get_process_name(pid) << "\n";
+           << "Cmd line: " << android::base::Join(get_command_line(pid), " ") << "\n";
     buffer << "\n" << str << "\n";
     buffer << "----- end " << std::to_string(pid) << " -----\n";
     buffer << "\n";
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 04e1e4e..a152740 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -450,9 +450,6 @@
   //       unwind, do not make this too small. b/62828735
   alarm(30 * android::base::HwTimeoutMultiplier());
 
-  // Get the process name (aka cmdline).
-  std::string process_name = get_process_name(g_target_thread);
-
   // Collect the list of open files.
   OpenFilesList open_files;
   {
@@ -489,7 +486,6 @@
       info.pid = target_process;
       info.tid = thread;
       info.uid = getuid();
-      info.process_name = process_name;
       info.thread_name = get_thread_name(thread);
 
       unique_fd attr_fd(openat(target_proc_fd, "attr/current", O_RDONLY | O_CLOEXEC));
@@ -517,6 +513,8 @@
         ReadCrashInfo(input_pipe, &siginfo, &info.registers, &process_info);
         info.siginfo = &siginfo;
         info.signo = info.siginfo->si_signo;
+
+        info.command_line = get_command_line(g_target_thread);
       } else {
         info.registers.reset(unwindstack::Regs::RemoteGet(thread));
         if (!info.registers) {
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index c543a83..fd91038 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -34,6 +34,7 @@
 #include <memory>
 #include <string>
 
+#include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <log/log.h>
 #include <unwindstack/Unwinder.h>
@@ -42,11 +43,12 @@
 #include "libdebuggerd/utility.h"
 #include "util.h"
 
-static void dump_process_header(log_t* log, pid_t pid, const char* process_name) {
+static void dump_process_header(log_t* log, pid_t pid,
+                                const std::vector<std::string>& command_line) {
   _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, get_timestamp().c_str());
 
-  if (process_name) {
-    _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", process_name);
+  if (!command_line.empty()) {
+    _LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", android::base::Join(command_line, " ").c_str());
   }
   _LOG(log, logtype::BACKTRACE, "ABI: '%s'\n", ABI_STRING);
 }
@@ -89,7 +91,7 @@
     return;
   }
 
-  dump_process_header(&log, target->second.pid, target->second.process_name.c_str());
+  dump_process_header(&log, target->second.pid, target->second.command_line);
 
   dump_backtrace_thread(output_fd.get(), unwinder, target->second);
   for (const auto& [tid, info] : thread_info) {
@@ -107,7 +109,7 @@
   log.amfd_data = nullptr;
 
   pid_t pid = getpid();
-  dump_process_header(&log, pid, get_process_name(pid).c_str());
+  dump_process_header(&log, pid, get_command_line(pid));
 }
 
 void dump_backtrace_footer(int output_fd) {
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index dcb52f9..086dc97 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -18,6 +18,7 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include <unwindstack/Regs.h>
 
@@ -32,13 +33,14 @@
 
   pid_t pid;
 
-  std::string process_name;
+  std::vector<std::string> command_line;
   std::string selinux_label;
 
   int signo = 0;
   siginfo_t* siginfo = nullptr;
 };
 
+// This struct is written into a pipe from inside the crashing process.
 struct ProcessInfo {
   uintptr_t abort_msg_address = 0;
   uintptr_t fdsan_table_address = 0;
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 79ac122..a14dcb0 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -350,11 +350,11 @@
 }
 
 TEST_F(TombstoneTest, dump_thread_info_uid) {
-  dump_thread_info(&log_, ThreadInfo{.uid = 1,
-                                     .tid = 3,
-                                     .thread_name = "some_thread",
-                                     .pid = 2,
-                                     .process_name = "some_process"});
+  std::vector<std::string> cmdline = {"some_process"};
+  dump_thread_info(
+      &log_,
+      ThreadInfo{
+          .uid = 1, .tid = 3, .thread_name = "some_thread", .pid = 2, .command_line = cmdline});
   std::string expected = "pid: 2, tid: 3, name: some_thread  >>> some_process <<<\nuid: 1\n";
   ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
 }
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 4f75ff1..e0cc662 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -182,8 +182,13 @@
   // Don't try to collect logs from the threads that implement the logging system itself.
   if (thread_info.uid == AID_LOGD) log->should_retrieve_logcat = false;
 
+  const char* process_name = "<unknown>";
+  if (!thread_info.command_line.empty()) {
+    process_name = thread_info.command_line[0].c_str();
+  }
+
   _LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s  >>> %s <<<\n", thread_info.pid,
-       thread_info.tid, thread_info.thread_name.c_str(), thread_info.process_name.c_str());
+       thread_info.tid, thread_info.thread_name.c_str(), process_name);
   _LOG(log, logtype::HEADER, "uid: %d\n", thread_info.uid);
   if (thread_info.tagged_addr_ctrl != -1) {
     _LOG(log, logtype::HEADER, "tagged_addr_ctrl: %016lx\n", thread_info.tagged_addr_ctrl);
@@ -567,7 +572,7 @@
   log.amfd_data = nullptr;
 
   std::string thread_name = get_thread_name(tid);
-  std::string process_name = get_process_name(pid);
+  std::vector<std::string> command_line = get_command_line(pid);
 
   std::unique_ptr<unwindstack::Regs> regs(
       unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
@@ -582,7 +587,7 @@
       .tid = tid,
       .thread_name = std::move(thread_name),
       .pid = pid,
-      .process_name = std::move(process_name),
+      .command_line = std::move(command_line),
       .selinux_label = std::move(selinux_label),
       .siginfo = siginfo,
   };
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 3444e29..7657001 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -562,7 +562,11 @@
   result.set_uid(main_thread.uid);
   result.set_selinux_label(main_thread.selinux_label);
 
-  result.set_process_name(main_thread.process_name);
+  auto cmd_line = result.mutable_command_line();
+  for (const auto& arg : main_thread.command_line) {
+    *cmd_line->Add() = arg;
+  }
+
   if (!main_thread.siginfo) {
     async_safe_fatal("siginfo missing");
   }
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index 00ca7c1..020b0a5 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -26,6 +26,7 @@
 #include <vector>
 
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 #include <async_safe/log.h>
 
@@ -71,8 +72,13 @@
 
 static void print_thread_header(CallbackType callback, const Tombstone& tombstone,
                                 const Thread& thread, bool should_log) {
+  const char* process_name = "<unknown>";
+  if (!tombstone.command_line().empty()) {
+    process_name = tombstone.command_line()[0].c_str();
+    CB(should_log, "Cmdline: %s", android::base::Join(tombstone.command_line(), " ").c_str());
+  }
   CB(should_log, "pid: %d, tid: %d, name: %s  >>> %s <<<", tombstone.pid(), thread.id(),
-     thread.name().c_str(), tombstone.process_name().c_str());
+     thread.name().c_str(), process_name);
   CB(should_log, "uid: %d", tombstone.uid());
   if (thread.tagged_addr_ctrl() != -1) {
     CB(should_log, "tagged_addr_ctrl: %016" PRIx64, thread.tagged_addr_ctrl());
diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto
index dd15ff6..294e4e5 100644
--- a/debuggerd/proto/tombstone.proto
+++ b/debuggerd/proto/tombstone.proto
@@ -17,7 +17,7 @@
   uint32 uid = 7;
   string selinux_label = 8;
 
-  string process_name = 9;
+  repeated string command_line = 9;
 
   // Process uptime in seconds.
   uint32 process_uptime = 20;
diff --git a/debuggerd/util.cpp b/debuggerd/util.cpp
index f3bff8c..ce0fd30 100644
--- a/debuggerd/util.cpp
+++ b/debuggerd/util.cpp
@@ -26,10 +26,31 @@
 #include <android-base/strings.h>
 #include "protocol.h"
 
+std::vector<std::string> get_command_line(pid_t pid) {
+  std::vector<std::string> result;
+
+  std::string cmdline;
+  android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid), &cmdline);
+
+  auto it = cmdline.cbegin();
+  while (it != cmdline.cend()) {
+    // string::iterator is a wrapped type, not a raw char*.
+    auto terminator = std::find(it, cmdline.cend(), '\0');
+    result.emplace_back(it, terminator);
+    it = std::find_if(terminator, cmdline.cend(), [](char c) { return c != '\0'; });
+  }
+  if (result.empty()) {
+    result.emplace_back("<unknown>");
+  }
+
+  return result;
+}
+
 std::string get_process_name(pid_t pid) {
   std::string result = "<unknown>";
   android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid), &result);
-  return result;
+  // We only want the name, not the whole command line, so truncate at the first NUL.
+  return result.c_str();
 }
 
 std::string get_thread_name(pid_t tid) {
diff --git a/debuggerd/util.h b/debuggerd/util.h
index 07e7e99..ec2862a 100644
--- a/debuggerd/util.h
+++ b/debuggerd/util.h
@@ -17,10 +17,12 @@
 #pragma once
 
 #include <string>
+#include <vector>
 
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
+std::vector<std::string> get_command_line(pid_t pid);
 std::string get_process_name(pid_t pid);
 std::string get_thread_name(pid_t tid);
 
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index bd1e284..2c5bf75 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -1619,6 +1619,18 @@
         //    as dm-snapshot (for example, after merge completes).
         bool should_unmap = current_slot != Slot::Target;
         bool should_delete = ShouldDeleteSnapshot(flashing_status, current_slot, name);
+        if (should_unmap && android::base::EndsWith(name, device_->GetSlotSuffix())) {
+            // Something very unexpected has happened - we want to unmap this
+            // snapshot, but it's on the wrong slot. We can't unmap an active
+            // partition. If this is not really a snapshot, skip the unmap
+            // step.
+            auto& dm = DeviceMapper::Instance();
+            if (dm.GetState(name) == DmDeviceState::INVALID || !IsSnapshotDevice(name)) {
+                LOG(ERROR) << "Detected snapshot " << name << " on " << current_slot << " slot"
+                           << " for source partition; removing without unmap.";
+                should_unmap = false;
+            }
+        }
 
         bool partition_ok = true;
         if (should_unmap && !UnmapPartitionWithSnapshot(lock, name)) {
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 25500b5..6ed0129 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -2021,6 +2021,34 @@
     ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
 }
 
+TEST_F(SnapshotUpdateTest, CancelOnTargetSlot) {
+    AddOperationForPartitions();
+
+    // Execute the update from B->A.
+    test_device->set_slot_suffix("_b");
+    ASSERT_TRUE(sm->BeginUpdate());
+    ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
+
+    std::string path;
+    ASSERT_TRUE(CreateLogicalPartition(
+            CreateLogicalPartitionParams{
+                    .block_device = fake_super,
+                    .metadata_slot = 0,
+                    .partition_name = "sys_a",
+                    .timeout_ms = 1s,
+                    .partition_opener = opener_.get(),
+            },
+            &path));
+
+    // Hold sys_a open so it can't be unmapped.
+    unique_fd fd(open(path.c_str(), O_RDONLY));
+
+    // Switch back to "A", make sure we can cancel. Instead of unmapping sys_a
+    // we should simply delete the old snapshots.
+    test_device->set_slot_suffix("_a");
+    ASSERT_TRUE(sm->BeginUpdate());
+}
+
 class FlashAfterUpdateTest : public SnapshotUpdateTest,
                              public WithParamInterface<std::tuple<uint32_t, bool>> {
   public:
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 73ef97a..0dc8159 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1176,7 +1176,7 @@
     } else if (qemu_key == "media.ccodec"sv) {
         return "debug.stagefright.ccodec"s;
     } else {
-        return ""s;  // TBD
+        return "qemu."s + std::string(qemu_key);
     }
 }
 
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
index baee4f9..c934860 100644
--- a/libmodprobe/include/modprobe/modprobe.h
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -24,7 +24,8 @@
 
 class Modprobe {
   public:
-    Modprobe(const std::vector<std::string>&, const std::string load_file = "modules.load");
+    Modprobe(const std::vector<std::string>&, const std::string load_file = "modules.load",
+             bool use_blocklist = true);
 
     bool LoadListedModules(bool strict = true);
     bool LoadWithAliases(const std::string& module_name, bool strict,
@@ -36,7 +37,6 @@
                             std::vector<std::string>* post_dependencies);
     void ResetModuleCount() { module_count_ = 0; }
     int GetModuleCount() { return module_count_; }
-    void EnableBlocklist(bool enable);
 
   private:
     std::string MakeCanonical(const std::string& module_path);
@@ -48,6 +48,7 @@
     void AddOption(const std::string& module_name, const std::string& option_name,
                    const std::string& value);
     std::string GetKernelCmdline();
+    bool IsBlocklisted(const std::string& module_name);
 
     bool ParseDepCallback(const std::string& base_path, const std::vector<std::string>& args);
     bool ParseAliasCallback(const std::vector<std::string>& args);
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index b3ae937..1a9d364 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -313,7 +313,9 @@
     }
 }
 
-Modprobe::Modprobe(const std::vector<std::string>& base_paths, const std::string load_file) {
+Modprobe::Modprobe(const std::vector<std::string>& base_paths, const std::string load_file,
+                   bool use_blocklist)
+    : blocklist_enabled(use_blocklist) {
     using namespace std::placeholders;
 
     for (const auto& base_path : base_paths) {
@@ -339,10 +341,6 @@
     ParseKernelCmdlineOptions();
 }
 
-void Modprobe::EnableBlocklist(bool enable) {
-    blocklist_enabled = enable;
-}
-
 std::vector<std::string> Modprobe::GetDependencies(const std::string& module) {
     auto it = module_deps_.find(module);
     if (it == module_deps_.end()) {
@@ -427,10 +425,23 @@
     return true;
 }
 
+bool Modprobe::IsBlocklisted(const std::string& module_name) {
+    if (!blocklist_enabled) return false;
+
+    auto canonical_name = MakeCanonical(module_name);
+    auto dependencies = GetDependencies(canonical_name);
+    for (auto dep = dependencies.begin(); dep != dependencies.end(); ++dep) {
+        if (module_blocklist_.count(MakeCanonical(*dep))) return true;
+    }
+
+    return module_blocklist_.count(canonical_name) > 0;
+}
+
 bool Modprobe::LoadListedModules(bool strict) {
     auto ret = true;
     for (const auto& module : module_load_) {
         if (!LoadWithAliases(module, true)) {
+            if (IsBlocklisted(module)) continue;
             ret = false;
             if (strict) break;
         }
@@ -440,16 +451,10 @@
 
 bool Modprobe::Remove(const std::string& module_name) {
     auto dependencies = GetDependencies(MakeCanonical(module_name));
-    if (dependencies.empty()) {
-        LOG(ERROR) << "Empty dependencies for module " << module_name;
-        return false;
-    }
-    if (!Rmmod(dependencies[0])) {
-        return false;
-    }
-    for (auto dep = dependencies.begin() + 1; dep != dependencies.end(); ++dep) {
+    for (auto dep = dependencies.begin(); dep != dependencies.end(); ++dep) {
         Rmmod(*dep);
     }
+    Rmmod(module_name);
     return true;
 }
 
diff --git a/libmodprobe/libmodprobe_test.cpp b/libmodprobe/libmodprobe_test.cpp
index d50c10d..f960b61 100644
--- a/libmodprobe/libmodprobe_test.cpp
+++ b/libmodprobe/libmodprobe_test.cpp
@@ -78,6 +78,18 @@
             "/test13.ko",
     };
 
+    std::vector<std::string> expected_modules_blocklist_enabled = {
+            "/test1.ko option1=50 option2=60",
+            "/test6.ko",
+            "/test2.ko",
+            "/test5.ko option1=",
+            "/test8.ko",
+            "/test7.ko param1=4",
+            "/test12.ko",
+            "/test11.ko",
+            "/test13.ko",
+    };
+
     const std::string modules_dep =
             "test1.ko:\n"
             "test2.ko:\n"
@@ -146,7 +158,7 @@
         *i = dir.path + *i;
     }
 
-    Modprobe m({dir.path});
+    Modprobe m({dir.path}, "modules.load", false);
     EXPECT_TRUE(m.LoadListedModules());
 
     GTEST_LOG_(INFO) << "Expected modules loaded (in order):";
@@ -176,8 +188,22 @@
 
     EXPECT_TRUE(modules_loaded == expected_after_remove);
 
-    m.EnableBlocklist(true);
+    m = Modprobe({dir.path});
     EXPECT_FALSE(m.LoadWithAliases("test4", true));
+    while (modules_loaded.size() > 0) EXPECT_TRUE(m.Remove(modules_loaded.front()));
+    EXPECT_TRUE(m.LoadListedModules());
+
+    GTEST_LOG_(INFO) << "Expected modules loaded after enabling blocklist (in order):";
+    for (auto i = expected_modules_blocklist_enabled.begin();
+         i != expected_modules_blocklist_enabled.end(); ++i) {
+        *i = dir.path + *i;
+        GTEST_LOG_(INFO) << "\"" << *i << "\"";
+    }
+    GTEST_LOG_(INFO) << "Actual modules loaded with blocklist enabled (in order):";
+    for (auto i = modules_loaded.begin(); i != modules_loaded.end(); ++i) {
+        GTEST_LOG_(INFO) << "\"" << *i << "\"";
+    }
+    EXPECT_TRUE(modules_loaded == expected_modules_blocklist_enabled);
 }
 
 TEST(libmodprobe, ModuleDepLineWithoutColonIsSkipped) {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a04ae9f..9a30ead 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -821,6 +821,9 @@
     mkdir /data/ss 0700 system system encryption=Require
 
     mkdir /data/system 0775 system system encryption=Require
+    mkdir /data/system/environ 0700 system system
+    # b/183861600 attempt to fix selinux label before running derive_classpath service
+    restorecon /data/system/environ
     mkdir /data/system/dropbox 0700 system system
     mkdir /data/system/heapdump 0700 system system
     mkdir /data/system/users 0775 system system
@@ -884,13 +887,6 @@
     wait_for_prop apexd.status activated
     perform_apex_config
 
-    # Define and export *CLASSPATH variables
-    mkdir /data/system/environ 0700 system system
-    # Must start before 'odsign', as odsign depends on *CLASSPATH variables
-    exec_start derive_classpath
-    load_exports /data/system/environ/classpath
-    rm /data/system/environ/classpath
-
     # Special-case /data/media/obb per b/64566063
     mkdir /data/media 0770 media_rw media_rw encryption=None
     exec - media_rw media_rw -- /system/bin/chattr +F /data/media
@@ -903,6 +899,12 @@
     # Set SELinux security contexts on upgrade or policy update.
     restorecon --recursive --skip-ce /data
 
+    # Define and export *CLASSPATH variables
+    # Must start before 'odsign', as odsign depends on *CLASSPATH variables
+    exec_start derive_classpath
+    load_exports /data/system/environ/classpath
+    rm /data/system/environ/classpath
+
     # Start the on-device signing daemon, and wait for it to finish, to ensure
     # ART artifacts are generated if needed.
     # Must start after 'derive_classpath' to have *CLASSPATH variables set.
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index 27b05ec..0730cce 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -19,6 +19,9 @@
     updatable
     seclabel u:r:adbd:s0
 
+on property:vendor.sys.usb.adb.disabled=*
+    setprop sys.usb.adb.disabled ${vendor.sys.usb.adb.disabled}
+
 # Set default value on sys.usb.configfs early in boot sequence. It will be
 # overridden in `on boot` action of init.hardware.rc.
 on init
diff --git a/toolbox/OWNERS b/toolbox/OWNERS
index 7529cb9..5e2c581 100644
--- a/toolbox/OWNERS
+++ b/toolbox/OWNERS
@@ -1 +1,2 @@
 include platform/system/core:/janitors/OWNERS
+per-file modprobe.c=willmcvicker@google.com,dvander@google.com
diff --git a/toolbox/modprobe.cpp b/toolbox/modprobe.cpp
index 7df7b71..711586a 100644
--- a/toolbox/modprobe.cpp
+++ b/toolbox/modprobe.cpp
@@ -215,10 +215,7 @@
         return EXIT_FAILURE;
     }
 
-    Modprobe m(mod_dirs);
-    if (blocklist) {
-        m.EnableBlocklist(true);
-    }
+    Modprobe m(mod_dirs, "modules.load", blocklist);
 
     for (const auto& module : modules) {
         switch (mode) {
diff --git a/trusty/apploader/apploader.cpp b/trusty/apploader/apploader.cpp
index 8ab6303..4aca375 100644
--- a/trusty/apploader/apploader.cpp
+++ b/trusty/apploader/apploader.cpp
@@ -96,13 +96,13 @@
 
     unique_fd file_fd(TEMP_FAILURE_RETRY(open(file_name, O_RDONLY)));
     if (!file_fd.ok()) {
-        fprintf(stderr, "Error opening file '%s': %s\n", file_name, strerror(errno));
+        PLOG(ERROR) << "Error opening file " << file_name;
         return {};
     }
 
     rc = fstat64(file_fd, &st);
     if (rc < 0) {
-        fprintf(stderr, "Error calling stat on file '%s': %s\n", file_name, strerror(errno));
+        PLOG(ERROR) << "Error calling stat on file '" << file_name << "'";
         return {};
     }
 
@@ -115,14 +115,14 @@
         file_page_offset = page_size - file_page_offset;
     }
     if (__builtin_add_overflow(file_size, file_page_offset, &file_page_size)) {
-        fprintf(stderr, "Failed to page-align file size\n");
+        LOG(ERROR) << "Failed to page-align file size";
         return {};
     }
 
     BufferAllocator alloc;
     unique_fd dmabuf_fd(alloc.Alloc(kDmabufSystemHeapName, file_page_size));
     if (!dmabuf_fd.ok()) {
-        fprintf(stderr, "Error creating dmabuf: %d\n", dmabuf_fd.get());
+        LOG(ERROR) << "Error creating dmabuf: " << dmabuf_fd.get();
         return dmabuf_fd;
     }
 
@@ -137,12 +137,12 @@
                 pread(file_fd, (char*)shm + file_offset, file_size - file_offset, file_offset));
 
         if (num_read < 0) {
-            fprintf(stderr, "Error reading package file '%s': %s\n", file_name, strerror(errno));
+            PLOG(ERROR) << "Error reading package file '" << file_name << "'";
             break;
         }
 
         if (num_read == 0) {
-            fprintf(stderr, "Unexpected end of file '%s'\n", file_name);
+            LOG(ERROR) << "Unexpected end of file '" << file_name << "'";
             break;
         }
 
@@ -182,17 +182,17 @@
     struct apploader_resp resp;
     ssize_t rc = read(tipc_fd, &resp, sizeof(resp));
     if (rc < 0) {
-        fprintf(stderr, "Failed to read response: %zd\n", rc);
+        PLOG(ERROR) << "Failed to read response";
         return rc;
     }
 
     if (rc < sizeof(resp)) {
-        fprintf(stderr, "Not enough data in response: %zd\n", rc);
+        LOG(ERROR) << "Not enough data in response: " << rc;
         return -EIO;
     }
 
     if (resp.hdr.cmd != (APPLOADER_CMD_LOAD_APPLICATION | APPLOADER_RESP_BIT)) {
-        fprintf(stderr, "Invalid command in response: %u\n", resp.hdr.cmd);
+        LOG(ERROR) << "Invalid command in response: " << resp.hdr.cmd;
         return -EINVAL;
     }
 
@@ -200,28 +200,28 @@
         case APPLOADER_NO_ERROR:
             break;
         case APPLOADER_ERR_UNKNOWN_CMD:
-            fprintf(stderr, "Error: unknown command\n");
+            LOG(ERROR) << "Error: unknown command";
             break;
         case APPLOADER_ERR_INVALID_CMD:
-            fprintf(stderr, "Error: invalid command arguments\n");
+            LOG(ERROR) << "Error: invalid command arguments";
             break;
         case APPLOADER_ERR_NO_MEMORY:
-            fprintf(stderr, "Error: out of Trusty memory\n");
+            LOG(ERROR) << "Error: out of Trusty memory";
             break;
         case APPLOADER_ERR_VERIFICATION_FAILED:
-            fprintf(stderr, "Error: failed to verify the package\n");
+            LOG(ERROR) << "Error: failed to verify the package";
             break;
         case APPLOADER_ERR_LOADING_FAILED:
-            fprintf(stderr, "Error: failed to load the package\n");
+            LOG(ERROR) << "Error: failed to load the package";
             break;
         case APPLOADER_ERR_ALREADY_EXISTS:
-            fprintf(stderr, "Error: application already exists\n");
+            LOG(ERROR) << "Error: application already exists";
             break;
         case APPLOADER_ERR_INTERNAL:
-            fprintf(stderr, "Error: internal apploader error\n");
+            LOG(ERROR) << "Error: internal apploader error";
             break;
         default:
-            fprintf(stderr, "Unrecognized error: %u\n", resp.error);
+            LOG(ERROR) << "Unrecognized error: " << resp.error;
             break;
     }
 
@@ -241,14 +241,14 @@
 
     tipc_fd = tipc_connect(dev_name, APPLOADER_PORT);
     if (tipc_fd < 0) {
-        fprintf(stderr, "Failed to connect to Trusty app loader: %s\n", strerror(-tipc_fd));
+        LOG(ERROR) << "Failed to connect to Trusty app loader: " << strerror(-tipc_fd);
         rc = tipc_fd;
         goto err_tipc_connect;
     }
 
     rc = send_load_message(tipc_fd, package_fd, package_size);
     if (rc < 0) {
-        fprintf(stderr, "Failed to send package: %zd\n", rc);
+        LOG(ERROR) << "Failed to send package: " << rc;
         goto err_send;
     }