Merge "adbd: check auth id." into rvc-dev
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 7f6e723..5307a00 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -986,10 +986,69 @@
fb->GetVar("partition-type:vbmeta_b", &partition_type) == fastboot::SUCCESS;
}
+static std::string fb_fix_numeric_var(std::string var) {
+ // Some bootloaders (angler, for example), send spurious leading whitespace.
+ var = android::base::Trim(var);
+ // Some bootloaders (hammerhead, for example) use implicit hex.
+ // This code used to use strtol with base 16.
+ if (!android::base::StartsWith(var, "0x")) var = "0x" + var;
+ return var;
+}
+
+static void copy_boot_avb_footer(const std::string& partition, struct fastboot_buffer* buf) {
+ if (buf->sz < AVB_FOOTER_SIZE) {
+ return;
+ }
+
+ std::string partition_size_str;
+ if (fb->GetVar("partition-size:" + partition, &partition_size_str) != fastboot::SUCCESS) {
+ die("cannot get boot partition size");
+ }
+
+ partition_size_str = fb_fix_numeric_var(partition_size_str);
+ int64_t partition_size;
+ if (!android::base::ParseInt(partition_size_str, &partition_size)) {
+ die("Couldn't parse partition size '%s'.", partition_size_str.c_str());
+ }
+ if (partition_size == buf->sz) {
+ return;
+ }
+ if (partition_size < buf->sz) {
+ die("boot partition is smaller than boot image");
+ }
+
+ std::string data;
+ if (!android::base::ReadFdToString(buf->fd, &data)) {
+ die("Failed reading from boot");
+ }
+
+ uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE;
+ if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) {
+ return;
+ }
+
+ int fd = make_temporary_fd("boot rewriting");
+ if (!android::base::WriteStringToFd(data, fd)) {
+ die("Failed writing to modified boot");
+ }
+ lseek(fd, partition_size - AVB_FOOTER_SIZE, SEEK_SET);
+ if (!android::base::WriteStringToFd(data.substr(footer_offset), fd)) {
+ die("Failed copying AVB footer in boot");
+ }
+ close(buf->fd);
+ buf->fd = fd;
+ buf->sz = partition_size;
+ lseek(fd, 0, SEEK_SET);
+}
+
static void flash_buf(const std::string& partition, struct fastboot_buffer *buf)
{
sparse_file** s;
+ if (partition == "boot" || partition == "boot_a" || partition == "boot_b") {
+ copy_boot_avb_footer(partition, buf);
+ }
+
// Rewrite vbmeta if that's what we're flashing and modification has been requested.
if (g_disable_verity || g_disable_verification) {
if (partition == "vbmeta" || partition == "vbmeta_a" || partition == "vbmeta_b") {
@@ -1485,15 +1544,6 @@
fb->RawCommand(command, "");
}
-static std::string fb_fix_numeric_var(std::string var) {
- // Some bootloaders (angler, for example), send spurious leading whitespace.
- var = android::base::Trim(var);
- // Some bootloaders (hammerhead, for example) use implicit hex.
- // This code used to use strtol with base 16.
- if (!android::base::StartsWith(var, "0x")) var = "0x" + var;
- return var;
-}
-
static unsigned fb_get_flash_block_size(std::string name) {
std::string sizeString;
if (fb->GetVar(name, &sizeString) != fastboot::SUCCESS || sizeString.empty()) {
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index f5daf91..cd64599 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -162,10 +162,13 @@
defaults: ["fs_mgr_defaults"],
static_libs: [
"libavb_user",
+ "libutils",
+ "libvold_binder",
],
shared_libs: [
"libbootloader_message",
"libbase",
+ "libbinder",
"libcutils",
"libcrypto",
"libext4_utils",
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 1c5bb6c..9561471 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -331,7 +331,7 @@
// try backup superblock, if main superblock is corrupted
for (unsigned int blocksize = EXT4_MIN_BLOCK_SIZE; blocksize <= EXT4_MAX_BLOCK_SIZE;
blocksize *= 2) {
- unsigned int superblock = blocksize * 8;
+ uint64_t superblock = blocksize * 8;
if (blocksize == EXT4_MIN_BLOCK_SIZE) superblock++;
if (TEMP_FAILURE_RETRY(pread(fd, sb, sizeof(*sb), superblock * blocksize)) !=
@@ -1065,7 +1065,8 @@
class CheckpointManager {
public:
- CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
+ CheckpointManager(int needs_checkpoint = -1, bool metadata_encrypted = false)
+ : needs_checkpoint_(needs_checkpoint), metadata_encrypted_(metadata_encrypted) {}
bool NeedsCheckpoint() {
if (needs_checkpoint_ != UNKNOWN) {
@@ -1083,7 +1084,7 @@
return true;
}
- if (entry->fs_mgr_flags.checkpoint_blk) {
+ if (entry->fs_mgr_flags.checkpoint_blk && !metadata_encrypted_) {
call_vdc({"checkpoint", "restoreCheckpoint", entry->blk_device}, nullptr);
}
@@ -1192,6 +1193,7 @@
enum { UNKNOWN = -1, NO = 0, YES = 1 };
int needs_checkpoint_;
+ bool metadata_encrypted_;
std::map<std::string, std::string> device_map_;
};
@@ -1825,11 +1827,11 @@
// in turn, and stop on 1st success, or no more match.
static int fs_mgr_do_mount_helper(Fstab* fstab, const std::string& n_name,
const std::string& n_blk_device, const char* tmp_mount_point,
- int needs_checkpoint) {
+ int needs_checkpoint, bool metadata_encrypted) {
int mount_errors = 0;
int first_mount_errno = 0;
std::string mount_point;
- CheckpointManager checkpoint_manager(needs_checkpoint);
+ CheckpointManager checkpoint_manager(needs_checkpoint, metadata_encrypted);
AvbUniquePtr avb_handle(nullptr);
if (!fstab) {
@@ -1939,12 +1941,13 @@
}
int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point) {
- return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1);
+ return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, -1, false);
}
int fs_mgr_do_mount(Fstab* fstab, const char* n_name, char* n_blk_device, char* tmp_mount_point,
- bool needs_checkpoint) {
- return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint);
+ bool needs_checkpoint, bool metadata_encrypted) {
+ return fs_mgr_do_mount_helper(fstab, n_name, n_blk_device, tmp_mount_point, needs_checkpoint,
+ metadata_encrypted);
}
/*
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 24cbad7..def1c21 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -24,6 +24,7 @@
#include <unistd.h>
#include <string>
+#include <thread>
#include <utility>
#include <vector>
@@ -31,6 +32,8 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
+#include <android/os/IVold.h>
+#include <binder/IServiceManager.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
#include <fec/io.h>
@@ -103,8 +106,23 @@
::exit(0); // SUCCESS
}
+static android::sp<android::os::IVold> GetVold() {
+ while (true) {
+ if (auto sm = android::defaultServiceManager()) {
+ if (auto binder = sm->getService(android::String16("vold"))) {
+ if (auto vold = android::interface_cast<android::os::IVold>(binder)) {
+ return vold;
+ }
+ }
+ }
+ std::this_thread::sleep_for(2s);
+ }
+}
+
} // namespace
+using namespace std::chrono_literals;
+
static int do_remount(int argc, char* argv[]) {
enum {
SUCCESS = 0,
@@ -118,6 +136,9 @@
BAD_OVERLAY,
NO_MOUNTS,
REMOUNT_FAILED,
+ MUST_REBOOT,
+ BINDER_ERROR,
+ CHECKPOINTING
} retval = SUCCESS;
// If somehow this executable is delivered on a "user" build, it can
@@ -191,6 +212,22 @@
return NO_FSTAB;
}
+ if (android::base::GetBoolProperty("ro.virtual_ab.enabled", false) &&
+ !android::base::GetBoolProperty("ro.virtual_ab.retrofit", false)) {
+ // Virtual A/B devices can use /data as backing storage; make sure we're
+ // not checkpointing.
+ auto vold = GetVold();
+ bool checkpointing = false;
+ if (!vold->isCheckpointing(&checkpointing).isOk()) {
+ LOG(ERROR) << "Could not determine checkpointing status.";
+ return BINDER_ERROR;
+ }
+ if (checkpointing) {
+ LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
+ return CHECKPOINTING;
+ }
+ }
+
// Generate the list of supported overlayfs mount points.
auto overlayfs_candidates = fs_mgr_overlayfs_candidate_list(fstab);
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 86090c1..2a67b8c 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -69,7 +69,7 @@
int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const char* n_name, char* n_blk_device,
char* tmp_mount_point);
int fs_mgr_do_mount(android::fs_mgr::Fstab* fstab, const char* n_name, char* n_blk_device,
- char* tmp_mount_point, bool need_cp);
+ char* tmp_mount_point, bool need_cp, bool metadata_encrypted);
int fs_mgr_do_mount_one(const android::fs_mgr::FstabEntry& entry,
const std::string& mount_point = "");
int fs_mgr_do_tmpfs_mount(const char *n_name);
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index f71d0c3..22f381c 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -311,6 +311,8 @@
}
};
+std::recursive_mutex FuseBridgeLoop::mutex_;
+
FuseBridgeLoop::FuseBridgeLoop() : opened_(true) {
base::unique_fd epoll_fd(epoll_create1(EPOLL_CLOEXEC));
if (epoll_fd.get() == -1) {
@@ -328,7 +330,7 @@
std::unique_ptr<FuseBridgeEntry> bridge(
new FuseBridgeEntry(mount_id, std::move(dev_fd), std::move(proxy_fd)));
- std::lock_guard<std::mutex> lock(mutex_);
+ std::lock_guard<std::recursive_mutex> lock(mutex_);
if (!opened_) {
LOG(ERROR) << "Tried to add a mount to a closed bridge";
return false;
@@ -372,7 +374,7 @@
const bool wait_result = epoll_controller_->Wait(bridges_.size(), &entries);
LOG(VERBOSE) << "Receive epoll events";
{
- std::lock_guard<std::mutex> lock(mutex_);
+ std::lock_guard<std::recursive_mutex> lock(mutex_);
if (!(wait_result && ProcessEventLocked(entries, callback))) {
for (auto it = bridges_.begin(); it != bridges_.end();) {
callback->OnClosed(it->second->mount_id());
@@ -385,5 +387,13 @@
}
}
+void FuseBridgeLoop::Lock() {
+ mutex_.lock();
+}
+
+void FuseBridgeLoop::Unlock() {
+ mutex_.unlock();
+}
+
} // namespace fuse
} // namespace android
diff --git a/libappfuse/include/libappfuse/FuseBridgeLoop.h b/libappfuse/include/libappfuse/FuseBridgeLoop.h
index 6bfda98..d5fc28f 100644
--- a/libappfuse/include/libappfuse/FuseBridgeLoop.h
+++ b/libappfuse/include/libappfuse/FuseBridgeLoop.h
@@ -50,6 +50,10 @@
// thread from one which invokes |Start|.
bool AddBridge(int mount_id, base::unique_fd dev_fd, base::unique_fd proxy_fd);
+ static void Lock();
+
+ static void Unlock();
+
private:
bool ProcessEventLocked(const std::unordered_set<FuseBridgeEntry*>& entries,
FuseBridgeLoopCallback* callback);
@@ -60,7 +64,7 @@
std::map<int, std::unique_ptr<FuseBridgeEntry>> bridges_;
// Lock for multi-threading.
- std::mutex mutex_;
+ static std::recursive_mutex mutex_;
bool opened_;
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index d006ba4..3bdc30f 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -96,7 +96,7 @@
((logger_list->start.tv_sec != buf.l.realtime.tv_sec) ||
(logger_list->start.tv_nsec <= buf.l.realtime.tv_nsec)))) &&
(!logger_list->pid || (logger_list->pid == buf.p.pid))) {
- char* msg = reinterpret_cast<char*>(&log_msg->entry) + log_msg->entry.hdr_size;
+ char* msg = reinterpret_cast<char*>(&log_msg->entry) + sizeof(log_msg->entry);
*msg = buf.prio;
fd = atomic_load(&logger_list->fd);
if (fd <= 0) {
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
index a7687af..4806b08 100644
--- a/libmodprobe/include/modprobe/modprobe.h
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -36,7 +36,7 @@
std::vector<std::string>* post_dependencies);
void ResetModuleCount() { module_count_ = 0; }
int GetModuleCount() { return module_count_; }
- void EnableBlacklist(bool enable);
+ void EnableBlocklist(bool enable);
void EnableVerbose(bool enable);
private:
@@ -55,7 +55,7 @@
bool ParseSoftdepCallback(const std::vector<std::string>& args);
bool ParseLoadCallback(const std::vector<std::string>& args);
bool ParseOptionsCallback(const std::vector<std::string>& args);
- bool ParseBlacklistCallback(const std::vector<std::string>& args);
+ bool ParseBlocklistCallback(const std::vector<std::string>& args);
void ParseKernelCmdlineOptions();
void ParseCfg(const std::string& cfg, std::function<bool(const std::vector<std::string>&)> f);
@@ -65,8 +65,8 @@
std::vector<std::pair<std::string, std::string>> module_post_softdep_;
std::vector<std::string> module_load_;
std::unordered_map<std::string, std::string> module_options_;
- std::set<std::string> module_blacklist_;
+ std::set<std::string> module_blocklist_;
std::unordered_set<std::string> module_loaded_;
int module_count_ = 0;
- bool blacklist_enabled = false;
+ bool blocklist_enabled = false;
};
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index d193796..5a6ae8b 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -194,17 +194,17 @@
return true;
}
-bool Modprobe::ParseBlacklistCallback(const std::vector<std::string>& args) {
+bool Modprobe::ParseBlocklistCallback(const std::vector<std::string>& args) {
auto it = args.begin();
const std::string& type = *it++;
- if (type != "blacklist") {
- LOG(ERROR) << "non-blacklist line encountered in modules.blacklist";
+ if (type != "blocklist") {
+ LOG(ERROR) << "non-blocklist line encountered in modules.blocklist";
return false;
}
if (args.size() != 2) {
- LOG(ERROR) << "lines in modules.blacklist must have exactly 2 entries, not " << args.size();
+ LOG(ERROR) << "lines in modules.blocklist must have exactly 2 entries, not " << args.size();
return false;
}
@@ -214,7 +214,7 @@
if (canonical_name.empty()) {
return false;
}
- this->module_blacklist_.emplace(canonical_name);
+ this->module_blocklist_.emplace(canonical_name);
return true;
}
@@ -331,16 +331,16 @@
auto options_callback = std::bind(&Modprobe::ParseOptionsCallback, this, _1);
ParseCfg(base_path + "/modules.options", options_callback);
- auto blacklist_callback = std::bind(&Modprobe::ParseBlacklistCallback, this, _1);
- ParseCfg(base_path + "/modules.blacklist", blacklist_callback);
+ auto blocklist_callback = std::bind(&Modprobe::ParseBlocklistCallback, this, _1);
+ ParseCfg(base_path + "/modules.blocklist", blocklist_callback);
}
ParseKernelCmdlineOptions();
android::base::SetMinimumLogSeverity(android::base::INFO);
}
-void Modprobe::EnableBlacklist(bool enable) {
- blacklist_enabled = enable;
+void Modprobe::EnableBlocklist(bool enable) {
+ blocklist_enabled = enable;
}
void Modprobe::EnableVerbose(bool enable) {
diff --git a/libmodprobe/libmodprobe_ext.cpp b/libmodprobe/libmodprobe_ext.cpp
index 6589708..84f7150 100644
--- a/libmodprobe/libmodprobe_ext.cpp
+++ b/libmodprobe/libmodprobe_ext.cpp
@@ -80,8 +80,8 @@
bool Modprobe::ModuleExists(const std::string& module_name) {
struct stat fileStat;
- if (blacklist_enabled && module_blacklist_.count(module_name)) {
- LOG(INFO) << "module " << module_name << " is blacklisted";
+ if (blocklist_enabled && module_blocklist_.count(module_name)) {
+ LOG(INFO) << "module " << module_name << " is blocklisted";
return false;
}
auto deps = GetDependencies(module_name);
diff --git a/libmodprobe/libmodprobe_ext_test.cpp b/libmodprobe/libmodprobe_ext_test.cpp
index 9ee5ba7..e79bfaf 100644
--- a/libmodprobe/libmodprobe_ext_test.cpp
+++ b/libmodprobe/libmodprobe_ext_test.cpp
@@ -72,7 +72,7 @@
bool Modprobe::ModuleExists(const std::string& module_name) {
auto deps = GetDependencies(module_name);
- if (blacklist_enabled && module_blacklist_.count(module_name)) {
+ if (blocklist_enabled && module_blocklist_.count(module_name)) {
return false;
}
if (deps.empty()) {
diff --git a/libmodprobe/libmodprobe_test.cpp b/libmodprobe/libmodprobe_test.cpp
index eea0abd..5919c49 100644
--- a/libmodprobe/libmodprobe_test.cpp
+++ b/libmodprobe/libmodprobe_test.cpp
@@ -113,9 +113,9 @@
"options test9.ko param_x=1 param_y=2 param_z=3\n"
"options test100.ko param_1=1\n";
- const std::string modules_blacklist =
- "blacklist test9.ko\n"
- "blacklist test3.ko\n";
+ const std::string modules_blocklist =
+ "blocklist test9.ko\n"
+ "blocklist test3.ko\n";
const std::string modules_load =
"test4.ko\n"
@@ -139,7 +139,7 @@
0600, getuid(), getgid()));
ASSERT_TRUE(android::base::WriteStringToFile(modules_load, dir_path + "/modules.load", 0600,
getuid(), getgid()));
- ASSERT_TRUE(android::base::WriteStringToFile(modules_blacklist, dir_path + "/modules.blacklist",
+ ASSERT_TRUE(android::base::WriteStringToFile(modules_blocklist, dir_path + "/modules.blocklist",
0600, getuid(), getgid()));
for (auto i = test_modules.begin(); i != test_modules.end(); ++i) {
@@ -176,6 +176,6 @@
EXPECT_TRUE(modules_loaded == expected_after_remove);
- m.EnableBlacklist(true);
+ m.EnableBlocklist(true);
EXPECT_FALSE(m.LoadWithAliases("test4", true));
}
diff --git a/llkd/README.md b/llkd/README.md
index 191f988..6f92f14 100644
--- a/llkd/README.md
+++ b/llkd/README.md
@@ -1,199 +1,237 @@
-Android Live-LocK Daemon
-========================
+<!--
+Project: /_project.yaml
+Book: /_book.yaml
-Introduction
-------------
+{% include "_versions.html" %}
+-->
-Android Live-LocK Daemon (llkd) is used to catch kernel deadlocks and mitigate.
+<!--
+ Copyright 2020 The Android Open Source Project
-Code is structured to allow integration into another service as either as part
-of the main loop, or spun off as a thread should that be necessary. A default
-standalone implementation is provided by llkd component.
+ 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
-The 'C' interface from libllkd component is thus:
+ http://www.apache.org/licenses/LICENSE-2.0
- #include "llkd.h"
- bool llkInit(const char* threadname) /* return true if enabled */
- unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
+ 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.
+-->
-If a threadname is provided, a thread will be automatically spawned, otherwise
-caller must call llkCheckMilliseconds in its main loop. Function will return
-the period of time before the next expected call to this handler.
+# Android Live-LocK Daemon (llkd)
-Operations
-----------
+Android 10 <!-- {{ androidQVersionNumber }} --> includes the Android Live-LocK Daemon
+(`llkd`), which is designed to catch and mitigate kernel deadlocks. The `llkd`
+component provides a default standalone implementation, but you can
+alternatively integrate the `llkd` code into another service, either as part of
+the main loop or as a separate thread.
-There are two detection scenarios. Persistent D or Z state, and persistent
+## Detection scenarios <!-- {:#detection-scenarios} -->
+
+The `llkd` has two detection scenarios: Persistent D or Z state, and persistent
stack signature.
-If a thread is in D or Z state with no forward progress for longer than
-ro.llk.timeout_ms, or ro.llk.[D|Z].timeout_ms, kill the process or parent
-process respectively. If another scan shows the same process continues to
-exist, then have a confirmed live-lock condition and need to panic. Panic
-the kernel in a manner to provide the greatest bugreporting details as to the
-condition. Add a alarm self watchdog should llkd ever get locked up that is
-double the expected time to flow through the mainloop. Sampling is every
-ro.llk_sample_ms.
+### Persistent D or Z state <!-- {:#persistent-d-or-z-state} -->
-For usedebug releases only, persistent stack signature checking is enabled.
-If a thread in any state but Z, has a persistent listed ro.llk.stack kernel
-symbol always being reported, even if there is forward scheduling progress, for
-longer than ro.llk.timeout_ms, or ro.llk.stack.timeout_ms, then issue a kill
-to the process. If another scan shows the same process continues to exist,
-then have a confirmed live-lock condition and need to panic. There is no
-ABA detection since forward scheduling progress is allowed, thus the condition
-for the symbols are:
+If a thread is in D (uninterruptible sleep) or Z (zombie) state with no forward
+progress for longer than `ro.llk.timeout_ms or ro.llk.[D|Z].timeout_ms`, the
+`llkd` kills the process (or parent process). If a subsequent scan shows the
+same process continues to exist, the `llkd` confirms a live-lock condition and
+panics the kernel in a manner that provides the most detailed bug report for the
+condition.
-- Check is looking for " __symbol__+0x" or " __symbol__.cfi+0x" in
- /proc/__pid__/stack.
-- The __symbol__ should be rare and short lived enough that on a typical
- system the function is seen at most only once in a sample over the timeout
- period of ro.llk.stack.timeout_ms, samples occur every ro.llk.check_ms. This
- can be the only way to prevent a false trigger as there is no ABA protection.
-- Persistent continuously when the live lock condition exists.
-- Should be just below the function that is calling the lock that could
- contend, because if the lock is below or in the symbol function, the
- symbol will show in all affected processes, not just the one that
- caused the lockup.
+The `llkd` includes a self watchdog that alarms if `llkd` locks up; watchdog is
+double the expected time to flow through the mainloop and sampling is every
+`ro.llk_sample_ms`.
-Default will not monitor init, or [kthreadd] and all that [kthreadd] spawns.
-This reduces the effectiveness of llkd by limiting its coverage. If there is
-value in covering [kthreadd] spawned threads, the requirement will be that
-the drivers not remain in a persistent 'D' state, or that they have mechanisms
-to recover the thread should it be killed externally (this is good driver
-coding hygiene, a common request to add such to publicly reviewed kernel.org
-maintained drivers). For instance use wait_event_interruptible() instead of
-wait_event(). The blacklists can be adjusted accordingly if these
-conditions are met to cover kernel components. For the stack symbol checking,
-there is an additional process blacklist so that we do not incide sepolicy
-violations on services that block ptrace operations.
+### Persistent stack signature <!-- {:#persistent-stack-signature} -->
-An accompanying gTest set have been added, and will setup a persistent D or Z
-process, with and without forward progress, but not in a live-lock state
-because that would require a buggy kernel, or a module or kernel modification
-to stimulate. The test will check that llkd will mitigate first by killing
-the appropriate process. D state is setup by vfork() waiting for exec() in
-child process. Z state is setup by fork() and an un-waited for child process.
-Should be noted that both of these conditions should never happen on Android
-on purpose, and llkd effectively sweeps up processes that create these
-conditions. If the test can, it will reconfigure llkd to expedite the test
-duration by adjusting the ro.llk.* Android properties. Tests run the D state
-with some scheduling progress to ensure that ABA checking prevents false
-triggers. If 100% reliable ABA on platform, then ro.llk.killtest can be
-set to false; however this will result in some of the unit tests to panic
-kernel instead of deal with more graceful kill operation.
+For userdebug releases, the `llkd` can detect kernel live-locks using persistent
+stack signature checking. If a thread in any state except Z has a persistent
+listed `ro.llk.stack` kernel symbol that is reported for longer than
+`ro.llk.timeout_ms` or `ro.llk.stack.timeout_ms`, the `llkd` kills the process
+(even if there is forward scheduling progress). If a subsequent scan shows the
+same process continues to exist, the `llkd` confirms a live-lock condition and
+panics the kernel in a manner that provides the most detailed bug report for the
+condition.
-Android Properties
-------------------
+Note: Because forward scheduling progress is allowed, the `llkd` does not
+perform [ABA detection](https://en.wikipedia.org/wiki/ABA_problem){:.external}.
-The following are the Android Properties llkd respond to.
-*prop*_ms named properties are in milliseconds.
-Properties that use comma (*,*) separator for lists, use a leading separator to
-preserve default and add or subtract entries with (*optional*) plus (*+*) and
-minus (*-*) prefixes respectively.
-For these lists, the string "*false*" is synonymous with an *empty* list,
-and *blank* or *missing* resorts to the specified *default* value.
+The `lldk` check persists continuously when the live lock condition exists and
+looks for the composed strings `" symbol+0x"` or `" symbol.cfi+0x"` in the
+`/proc/pid/stack` file on Linux. The list of symbols is in `ro.llk.stack` and
+defaults to the comma-separated list of
+"`cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable`".
-#### ro.config.low_ram
-device is configured with limited memory.
+Symbols should be rare and short-lived enough that on a typical system the
+function is seen only once in a sample over the timeout period of
+`ro.llk.stack.timeout_ms` (samples occur every `ro.llk.check_ms`). Due to lack
+of ABA protection, this is the only way to prevent a false trigger. The symbol
+function must appear below the function calling the lock that could contend. If
+the lock is below or in the symbol function, the symbol appears in all affected
+processes, not just the one that caused the lockup.
-#### ro.debuggable
-device is configured for userdebug or eng build.
+## Coverage <!-- {:#coverage} -->
-#### ro.llk.sysrq_t
-default not ro.config.low_ram, or ro.debuggable if property is "eng".
-if true do sysrq t (dump all threads).
+The default implementation of `llkd` does not monitor `init`, `[kthreadd]`, or
+`[kthreadd]` spawns. For the `llkd` to cover `[kthreadd]`-spawned threads:
-#### ro.llk.enable
-default false, allow live-lock daemon to be enabled.
+* Drivers must not remain in a persistent D state,
-#### llk.enable
-default ro.llk.enable, and evaluated for eng.
+OR
-#### ro.khungtask.enable
-default false, allow [khungtask] daemon to be enabled.
+* Drivers must have mechanisms to recover the thread should it be killed
+ externally. For example, use `wait_event_interruptible()` instead of
+ `wait_event()`.
-#### khungtask.enable
-default ro.khungtask.enable and evaluated for eng.
+If one of the above conditions is met, the `llkd` ignorelist can be adjusted to
+cover kernel components. Stack symbol checking involves an additional process
+ignore list to prevent sepolicy violations on services that block `ptrace`
+operations.
-#### ro.llk.mlockall
-default false, enable call to mlockall().
+## Android properties <!-- {:#android-properties} -->
-#### ro.khungtask.timeout
-default value 12 minutes, [khungtask] maximum timelimit.
+The `llkd` responds to several Android properties (listed below).
-#### ro.llk.timeout_ms
-default 10 minutes, D or Z maximum timelimit, double this value and it sets
-the alarm watchdog for llkd.
+* Properties named `prop_ms` are in milliseconds.
+* Properties that use comma (,) separator for lists use a leading separator to
+ preserve the default entry, then add or subtract entries with optional plus
+ (+) and minus (-) prefixes respectively. For these lists, the string "false"
+ is synonymous with an empty list, and blank or missing entries resort to the
+ specified default value.
-#### ro.llk.D.timeout_ms
-default ro.llk.timeout_ms, D maximum timelimit.
+### ro.config.low_ram <!-- {:#ro-config-low-ram} -->
-#### ro.llk.Z.timeout_ms
-default ro.llk.timeout_ms, Z maximum timelimit.
+Device is configured with limited memory.
-#### ro.llk.stack.timeout_ms
-default ro.llk.timeout_ms,
-checking for persistent stack symbols maximum timelimit.
-Only active on userdebug or eng builds.
+### ro.debuggable <!-- {:#ro-debuggable} -->
-#### ro.llk.check_ms
-default 2 minutes samples of threads for D or Z.
+Device is configured for userdebug or eng build.
-#### ro.llk.stack
-default cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable
-comma separated list of kernel symbols.
-Look for kernel stack symbols that if ever persistently present can
-indicate a subsystem is locked up.
-Beware, check does not on purpose do forward scheduling ABA except by polling
-every ro.llk_check_ms over the period ro.llk.stack.timeout_ms, so stack symbol
-should be exceptionally rare and fleeting.
-One must be convinced that it is virtually *impossible* for symbol to show up
-persistently in all samples of the stack.
-Again, looks for a match for either " **symbol**+0x" or " **symbol**.cfi+0x"
-in stack expansion.
-Only available on userdebug or eng builds, limited privileges due to security
-concerns on user builds prevents this checking.
+### ro.llk.sysrq_t <!-- {:#ro-llk-sysrq-t} -->
-#### ro.llk.blacklist.process
-default 0,1,2 (kernel, init and [kthreadd]) plus process names
-init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd,
-[watchdogd],[watchdogd/0],...,[watchdogd/***get_nprocs**-1*].
-Do not watch these processes. A process can be comm, cmdline or pid reference.
-NB: automated default here can be larger than the current maximum property
-size of 92.
-NB: false is a very very very unlikely process to want to blacklist.
+If property is "eng", the default is not `ro.config.low_ram` or `ro.debuggable`.
+If true, dump all threads (`sysrq t`).
-#### ro.llk.blacklist.parent
-default 0,2,adbd&[setsid] (kernel, [kthreadd] and adbd *only for zombie setsid*).
-Do not watch processes that have this parent.
-An ampersand (*&*) separator is used to specify that the parent is ignored
-only in combination with the target child process.
-Ampersand was selected because it is never part of a process name,
-however a setprop in the shell requires it to be escaped or quoted;
-init rc file where this is normally specified does not have this issue.
-A parent or target processes can be specified as comm, cmdline or pid reference.
+### ro.llk.enable <!-- {:#ro-llk-enable} -->
-#### ro.llk.blacklist.uid
-default *empty* or false, comma separated list of uid numbers or names.
-Do not watch processes that match this uid.
+Allow live-lock daemon to be enabled. Default is false.
-#### ro.llk.blacklist.process.stack
-default process names init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd.
-This subset of processes are not monitored for live lock stack signatures.
-Also prevents the sepolicy violation associated with processes that block
-ptrace, as these can not be checked anyways.
-Only active on userdebug and eng builds.
+### llk.enable <!-- {:#llk-enable} -->
-Architectural Concerns
-----------------------
+Evaluated for eng builds. Default is `ro.llk.enable`.
-- built-in [khungtask] daemon is too generic and trips on driver code that
- sits around in D state too much. To switch to S instead makes the task(s)
- killable, so the drivers should be able to resurrect them if needed.
-- Properties are limited to 92 characters.
-- Create kernel module and associated gTest to actually test panic.
-- Create gTest to test out blacklist (ro.llk.blacklist.*properties* generally
- not be inputs). Could require more test-only interfaces to libllkd.
-- Speed up gTest using something else than ro.llk.*properties*, which should
- not be inputs as they should be baked into the product.
+### ro.khungtask.enable <!-- {:#ro-khungtask-enable} -->
+
+Allow `[khungtask]` daemon to be enabled. Default is false.
+
+### khungtask.enable <!-- {:#khungtask-enable} -->
+
+Evaluated for eng builds. Default is `ro.khungtask.enable`.
+
+### ro.llk.mlockall <!-- {:#ro-llk-mlockall} -->
+
+Enable call to `mlockall()`. Default is false.
+
+### ro.khungtask.timeout <!-- {:#ro-khungtask-timeout} -->
+
+`[khungtask]` maximum time limit. Default is 12 minutes.
+
+### ro.llk.timeout_ms <!-- {:#ro-llk-timeout-ms} -->
+
+D or Z maximum time limit. Default is 10 minutes. Double this value to set the
+alarm watchdog for `llkd`.
+
+### ro.llk.D.timeout_ms <!-- {:#ro-llk-D-timeout-ms} -->
+
+D maximum time limit. Default is `ro.llk.timeout_ms`.
+
+### ro.llk.Z.timeout_ms <!-- {:#ro-llk-Z-timeout-ms} -->
+
+Z maximum time limit. Default is `ro.llk.timeout_ms`.
+
+### ro.llk.stack.timeout_ms <!-- {:#ro-llk-stack-timeout-ms} -->
+
+Checks for persistent stack symbols maximum time limit. Default is
+`ro.llk.timeout_ms`. **Active only on userdebug or eng builds**.
+
+### ro.llk.check_ms <!-- {:#ro-llk-check-ms} -->
+
+Samples of threads for D or Z. Default is two minutes.
+
+### ro.llk.stack <!-- {:#ro-llk-stack} -->
+
+Checks for kernel stack symbols that if persistently present can indicate a
+subsystem is locked up. Default is
+`cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable`
+comma-separated list of kernel symbols. The check doesn't do forward scheduling
+ABA except by polling every `ro.llk_check_ms` over the period
+`ro.llk.stack.timeout_ms`, so stack symbols should be exceptionally rare and
+fleeting (it is highly unlikely for a symbol to show up persistently in all
+samples of the stack). Checks for a match for `" symbol+0x"` or
+`" symbol.cfi+0x"` in stack expansion. **Available only on userdebug or eng
+builds**; security concerns on user builds result in limited privileges that
+prevent this check.
+
+### ro.llk.ignorelist.process <!-- {:#ro-llk-ignorelist-process} -->
+
+The `llkd` does not watch the specified processes. Default is `0,1,2` (`kernel`,
+`init`, and `[kthreadd]`) plus process names
+`init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd, [watchdogd],[watchdogd/0],...,[watchdogd/get_nprocs-1]`.
+A process can be a `comm`, `cmdline`, or `pid` reference. An automated default
+can be larger than the current maximum property size of 92.
+
+Note: `false` is an extremely unlikely process to want to ignore.
+
+### ro.llk.ignorelist.parent <!-- {:#ro-llk-ignorelist-parent} -->
+
+The `llkd` does not watch processes that have the specified parent(s). Default
+is `0,2,adbd&[setsid]` (`kernel`, `[kthreadd]`, and `adbd` only for zombie
+`setsid`). An ampersand (&) separator specifies that the parent is ignored only
+in combination with the target child process. Ampersand was selected because it
+is never part of a process name; however, a `setprop` in the shell requires the
+ampersand to be escaped or quoted, although the `init rc` file where this is
+normally specified does not have this issue. A parent or target process can be a
+`comm`, `cmdline`, or `pid` reference.
+
+### ro.llk.ignorelist.uid <!-- {:#ro-llk-ignorelist-uid} -->
+
+The `llkd` does not watch processes that match the specified uid(s).
+Comma-separated list of uid numbers or names. Default is empty or false.
+
+### ro.llk.ignorelist.process.stack <!-- {:#ro-llk-ignorelist-process-stack} -->
+
+The `llkd` does not monitor the specified subset of processes for live lock stack
+signatures. Default is process names
+`init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd`. Prevents the sepolicy
+violation associated with processes that block `ptrace` (as these can't be
+checked). **Active only on userdebug and eng builds**. For details on build
+types, refer to [Building Android](/setup/build/building#choose-a-target).
+
+## Architectural concerns <!-- {:#architectural-concerns} -->
+
+* Properties are limited to 92 characters. However, this is not limited for
+ defaults defined in the `include/llkd.h` file in the sources.
+* The built-in `[khungtask]` daemon is too generic and trips on driver code that
+ sits around in D state too much. Switching drivers to sleep, or S state,
+ would make task(s) killable, and need to be resurrectable by drivers on an
+ as-need basis.
+
+## Library interface (optional) <!-- {:#library-interface-optional} -->
+
+You can optionally incorporate the `llkd` into another privileged daemon using
+the following C interface from the `libllkd` component:
+
+```
+#include "llkd.h"
+bool llkInit(const char* threadname) /* return true if enabled */
+unsigned llkCheckMillseconds(void) /* ms to sleep for next check */
+```
+
+If a threadname is provided, a thread automatically spawns, otherwise the caller
+must call `llkCheckMilliseconds` in its main loop. The function returns the
+period of time before the next expected call to this handler.
diff --git a/llkd/include/llkd.h b/llkd/include/llkd.h
index 3586ca1..4b20a56 100644
--- a/llkd/include/llkd.h
+++ b/llkd/include/llkd.h
@@ -30,37 +30,37 @@
unsigned llkCheckMilliseconds(void);
/* clang-format off */
-#define LLK_ENABLE_WRITEABLE_PROPERTY "llk.enable"
-#define LLK_ENABLE_PROPERTY "ro." LLK_ENABLE_WRITEABLE_PROPERTY
-#define LLK_ENABLE_DEFAULT false /* "eng" and userdebug true */
-#define KHT_ENABLE_WRITEABLE_PROPERTY "khungtask.enable"
-#define KHT_ENABLE_PROPERTY "ro." KHT_ENABLE_WRITEABLE_PROPERTY
-#define LLK_ENABLE_SYSRQ_T_PROPERTY "ro.llk.sysrq_t"
-#define LLK_ENABLE_SYSRQ_T_DEFAULT true
-#define LLK_MLOCKALL_PROPERTY "ro.llk.mlockall"
-#define LLK_MLOCKALL_DEFAULT true
-#define LLK_KILLTEST_PROPERTY "ro.llk.killtest"
-#define LLK_KILLTEST_DEFAULT true
-#define LLK_TIMEOUT_MS_PROPERTY "ro.llk.timeout_ms"
-#define KHT_TIMEOUT_PROPERTY "ro.khungtask.timeout"
-#define LLK_D_TIMEOUT_MS_PROPERTY "ro.llk.D.timeout_ms"
-#define LLK_Z_TIMEOUT_MS_PROPERTY "ro.llk.Z.timeout_ms"
-#define LLK_STACK_TIMEOUT_MS_PROPERTY "ro.llk.stack.timeout_ms"
-#define LLK_CHECK_MS_PROPERTY "ro.llk.check_ms"
+#define LLK_ENABLE_WRITEABLE_PROPERTY "llk.enable"
+#define LLK_ENABLE_PROPERTY "ro." LLK_ENABLE_WRITEABLE_PROPERTY
+#define LLK_ENABLE_DEFAULT false /* "eng" and userdebug true */
+#define KHT_ENABLE_WRITEABLE_PROPERTY "khungtask.enable"
+#define KHT_ENABLE_PROPERTY "ro." KHT_ENABLE_WRITEABLE_PROPERTY
+#define LLK_ENABLE_SYSRQ_T_PROPERTY "ro.llk.sysrq_t"
+#define LLK_ENABLE_SYSRQ_T_DEFAULT true
+#define LLK_MLOCKALL_PROPERTY "ro.llk.mlockall"
+#define LLK_MLOCKALL_DEFAULT true
+#define LLK_KILLTEST_PROPERTY "ro.llk.killtest"
+#define LLK_KILLTEST_DEFAULT true
+#define LLK_TIMEOUT_MS_PROPERTY "ro.llk.timeout_ms"
+#define KHT_TIMEOUT_PROPERTY "ro.khungtask.timeout"
+#define LLK_D_TIMEOUT_MS_PROPERTY "ro.llk.D.timeout_ms"
+#define LLK_Z_TIMEOUT_MS_PROPERTY "ro.llk.Z.timeout_ms"
+#define LLK_STACK_TIMEOUT_MS_PROPERTY "ro.llk.stack.timeout_ms"
+#define LLK_CHECK_MS_PROPERTY "ro.llk.check_ms"
/* LLK_CHECK_MS_DEFAULT = actual timeout_ms / LLK_CHECKS_PER_TIMEOUT_DEFAULT */
-#define LLK_CHECKS_PER_TIMEOUT_DEFAULT 5
-#define LLK_CHECK_STACK_PROPERTY "ro.llk.stack"
-#define LLK_CHECK_STACK_DEFAULT \
+#define LLK_CHECKS_PER_TIMEOUT_DEFAULT 5
+#define LLK_CHECK_STACK_PROPERTY "ro.llk.stack"
+#define LLK_CHECK_STACK_DEFAULT \
"cma_alloc,__get_user_pages,bit_wait_io,wait_on_page_bit_killable"
-#define LLK_BLACKLIST_PROCESS_PROPERTY "ro.llk.blacklist.process"
-#define LLK_BLACKLIST_PROCESS_DEFAULT \
+#define LLK_IGNORELIST_PROCESS_PROPERTY "ro.llk.ignorelist.process"
+#define LLK_IGNORELIST_PROCESS_DEFAULT \
"0,1,2,init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
-#define LLK_BLACKLIST_PARENT_PROPERTY "ro.llk.blacklist.parent"
-#define LLK_BLACKLIST_PARENT_DEFAULT "0,2,[kthreadd],adbd&[setsid]"
-#define LLK_BLACKLIST_UID_PROPERTY "ro.llk.blacklist.uid"
-#define LLK_BLACKLIST_UID_DEFAULT ""
-#define LLK_BLACKLIST_STACK_PROPERTY "ro.llk.blacklist.process.stack"
-#define LLK_BLACKLIST_STACK_DEFAULT "init,lmkd.llkd,llkd,keystore,ueventd,apexd"
+#define LLK_IGNORELIST_PARENT_PROPERTY "ro.llk.ignorelist.parent"
+#define LLK_IGNORELIST_PARENT_DEFAULT "0,2,[kthreadd],adbd&[setsid]"
+#define LLK_IGNORELIST_UID_PROPERTY "ro.llk.ignorelist.uid"
+#define LLK_IGNORELIST_UID_DEFAULT ""
+#define LLK_IGNORELIST_STACK_PROPERTY "ro.llk.ignorelist.process.stack"
+#define LLK_IGNORELIST_STACK_DEFAULT "init,lmkd.llkd,llkd,keystore,ueventd,apexd"
/* clang-format on */
__END_DECLS
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 8ad9900..a24d900 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -98,26 +98,26 @@
std::unordered_set<std::string> llkCheckStackSymbols;
#endif
-// Blacklist variables, initialized with comma separated lists of high false
+// Ignorelist variables, initialized with comma separated lists of high false
// positive and/or dangerous references, e.g. without self restart, for pid,
// ppid, name and uid:
// list of pids, or tids or names to skip. kernel pid (0), init pid (1),
// [kthreadd] pid (2), ourselves, "init", "[kthreadd]", "lmkd", "llkd" or
// combinations of watchdogd in kernel and user space.
-std::unordered_set<std::string> llkBlacklistProcess;
+std::unordered_set<std::string> llkIgnorelistProcess;
// list of parent pids, comm or cmdline names to skip. default:
// kernel pid (0), [kthreadd] (2), or ourselves, enforced and implied
-std::unordered_set<std::string> llkBlacklistParent;
+std::unordered_set<std::string> llkIgnorelistParent;
// list of parent and target processes to skip. default:
// adbd *and* [setsid]
-std::unordered_map<std::string, std::unordered_set<std::string>> llkBlacklistParentAndChild;
+std::unordered_map<std::string, std::unordered_set<std::string>> llkIgnorelistParentAndChild;
// list of uids, and uid names, to skip, default nothing
-std::unordered_set<std::string> llkBlacklistUid;
+std::unordered_set<std::string> llkIgnorelistUid;
#ifdef __PTRACE_ENABLED__
// list of names to skip stack checking. "init", "lmkd", "llkd", "keystore" or
// "logd" (if not userdebug).
-std::unordered_set<std::string> llkBlacklistStack;
+std::unordered_set<std::string> llkIgnorelistStack;
#endif
class dir {
@@ -626,9 +626,9 @@
return flag ? "true" : "false";
}
-std::string llkFormat(const std::unordered_set<std::string>& blacklist) {
+std::string llkFormat(const std::unordered_set<std::string>& ignorelist) {
std::string ret;
- for (const auto& entry : blacklist) {
+ for (const auto& entry : ignorelist) {
if (!ret.empty()) ret += ",";
ret += entry;
}
@@ -636,10 +636,10 @@
}
std::string llkFormat(
- const std::unordered_map<std::string, std::unordered_set<std::string>>& blacklist,
+ const std::unordered_map<std::string, std::unordered_set<std::string>>& ignorelist,
bool leading_comma = false) {
std::string ret;
- for (const auto& entry : blacklist) {
+ for (const auto& entry : ignorelist) {
for (const auto& target : entry.second) {
if (leading_comma || !ret.empty()) ret += ",";
ret += entry.first + "&" + target;
@@ -699,61 +699,61 @@
}
bool llkSkipName(const std::string& name,
- const std::unordered_set<std::string>& blacklist = llkBlacklistProcess) {
- if (name.empty() || blacklist.empty()) return false;
+ const std::unordered_set<std::string>& ignorelist = llkIgnorelistProcess) {
+ if (name.empty() || ignorelist.empty()) return false;
- return blacklist.find(name) != blacklist.end();
+ return ignorelist.find(name) != ignorelist.end();
}
bool llkSkipProc(proc* procp,
- const std::unordered_set<std::string>& blacklist = llkBlacklistProcess) {
+ const std::unordered_set<std::string>& ignorelist = llkIgnorelistProcess) {
if (!procp) return false;
- if (llkSkipName(std::to_string(procp->pid), blacklist)) return true;
- if (llkSkipName(procp->getComm(), blacklist)) return true;
- if (llkSkipName(procp->getCmdline(), blacklist)) return true;
- if (llkSkipName(android::base::Basename(procp->getCmdline()), blacklist)) return true;
+ if (llkSkipName(std::to_string(procp->pid), ignorelist)) return true;
+ if (llkSkipName(procp->getComm(), ignorelist)) return true;
+ if (llkSkipName(procp->getCmdline(), ignorelist)) return true;
+ if (llkSkipName(android::base::Basename(procp->getCmdline()), ignorelist)) return true;
return false;
}
const std::unordered_set<std::string>& llkSkipName(
const std::string& name,
- const std::unordered_map<std::string, std::unordered_set<std::string>>& blacklist) {
+ const std::unordered_map<std::string, std::unordered_set<std::string>>& ignorelist) {
static const std::unordered_set<std::string> empty;
- if (name.empty() || blacklist.empty()) return empty;
- auto found = blacklist.find(name);
- if (found == blacklist.end()) return empty;
+ if (name.empty() || ignorelist.empty()) return empty;
+ auto found = ignorelist.find(name);
+ if (found == ignorelist.end()) return empty;
return found->second;
}
bool llkSkipPproc(proc* pprocp, proc* procp,
const std::unordered_map<std::string, std::unordered_set<std::string>>&
- blacklist = llkBlacklistParentAndChild) {
- if (!pprocp || !procp || blacklist.empty()) return false;
- if (llkSkipProc(procp, llkSkipName(std::to_string(pprocp->pid), blacklist))) return true;
- if (llkSkipProc(procp, llkSkipName(pprocp->getComm(), blacklist))) return true;
- if (llkSkipProc(procp, llkSkipName(pprocp->getCmdline(), blacklist))) return true;
+ ignorelist = llkIgnorelistParentAndChild) {
+ if (!pprocp || !procp || ignorelist.empty()) return false;
+ if (llkSkipProc(procp, llkSkipName(std::to_string(pprocp->pid), ignorelist))) return true;
+ if (llkSkipProc(procp, llkSkipName(pprocp->getComm(), ignorelist))) return true;
+ if (llkSkipProc(procp, llkSkipName(pprocp->getCmdline(), ignorelist))) return true;
return llkSkipProc(procp,
- llkSkipName(android::base::Basename(pprocp->getCmdline()), blacklist));
+ llkSkipName(android::base::Basename(pprocp->getCmdline()), ignorelist));
}
bool llkSkipPid(pid_t pid) {
- return llkSkipName(std::to_string(pid), llkBlacklistProcess);
+ return llkSkipName(std::to_string(pid), llkIgnorelistProcess);
}
bool llkSkipPpid(pid_t ppid) {
- return llkSkipName(std::to_string(ppid), llkBlacklistParent);
+ return llkSkipName(std::to_string(ppid), llkIgnorelistParent);
}
bool llkSkipUid(uid_t uid) {
// Match by number?
- if (llkSkipName(std::to_string(uid), llkBlacklistUid)) {
+ if (llkSkipName(std::to_string(uid), llkIgnorelistUid)) {
return true;
}
// Match by name?
auto pwd = ::getpwuid(uid);
return (pwd != nullptr) && __predict_true(pwd->pw_name != nullptr) &&
- __predict_true(pwd->pw_name[0] != '\0') && llkSkipName(pwd->pw_name, llkBlacklistUid);
+ __predict_true(pwd->pw_name[0] != '\0') && llkSkipName(pwd->pw_name, llkIgnorelistUid);
}
bool getValidTidDir(dirent* dp, std::string* piddir) {
@@ -811,7 +811,7 @@
}
// Don't check process that are known to block ptrace, save sepolicy noise.
- if (llkSkipProc(procp, llkBlacklistStack)) return false;
+ if (llkSkipProc(procp, llkIgnorelistStack)) return false;
auto kernel_stack = ReadFile(piddir + "/stack");
if (kernel_stack.empty()) {
LOG(VERBOSE) << piddir << "/stack empty comm=" << procp->getComm()
@@ -917,12 +917,12 @@
<< LLK_CHECK_MS_PROPERTY "=" << llkFormat(llkCheckMs) << "\n"
#ifdef __PTRACE_ENABLED__
<< LLK_CHECK_STACK_PROPERTY "=" << llkFormat(llkCheckStackSymbols) << "\n"
- << LLK_BLACKLIST_STACK_PROPERTY "=" << llkFormat(llkBlacklistStack) << "\n"
+ << LLK_IGNORELIST_STACK_PROPERTY "=" << llkFormat(llkIgnorelistStack) << "\n"
#endif
- << LLK_BLACKLIST_PROCESS_PROPERTY "=" << llkFormat(llkBlacklistProcess) << "\n"
- << LLK_BLACKLIST_PARENT_PROPERTY "=" << llkFormat(llkBlacklistParent)
- << llkFormat(llkBlacklistParentAndChild, true) << "\n"
- << LLK_BLACKLIST_UID_PROPERTY "=" << llkFormat(llkBlacklistUid);
+ << LLK_IGNORELIST_PROCESS_PROPERTY "=" << llkFormat(llkIgnorelistProcess) << "\n"
+ << LLK_IGNORELIST_PARENT_PROPERTY "=" << llkFormat(llkIgnorelistParent)
+ << llkFormat(llkIgnorelistParentAndChild, true) << "\n"
+ << LLK_IGNORELIST_UID_PROPERTY "=" << llkFormat(llkIgnorelistUid);
}
void* llkThread(void* obj) {
@@ -932,14 +932,14 @@
std::string name = std::to_string(::gettid());
if (!llkSkipName(name)) {
- llkBlacklistProcess.emplace(name);
+ llkIgnorelistProcess.emplace(name);
}
name = static_cast<const char*>(obj);
prctl(PR_SET_NAME, name.c_str());
if (__predict_false(!llkSkipName(name))) {
- llkBlacklistProcess.insert(name);
+ llkIgnorelistProcess.insert(name);
}
- // No longer modifying llkBlacklistProcess.
+ // No longer modifying llkIgnorelistProcess.
llkRunning = true;
llkLogConfig();
while (llkRunning) {
@@ -1122,12 +1122,12 @@
}
if (pprocp) {
if (llkSkipPproc(pprocp, procp)) break;
- if (llkSkipProc(pprocp, llkBlacklistParent)) break;
+ if (llkSkipProc(pprocp, llkIgnorelistParent)) break;
} else {
- if (llkSkipName(std::to_string(ppid), llkBlacklistParent)) break;
+ if (llkSkipName(std::to_string(ppid), llkIgnorelistParent)) break;
}
- if ((llkBlacklistUid.size() != 0) && llkSkipUid(procp->getUid())) {
+ if ((llkIgnorelistUid.size() != 0) && llkSkipUid(procp->getUid())) {
continue;
}
@@ -1320,29 +1320,29 @@
if (debuggable) {
llkCheckStackSymbols = llkSplit(LLK_CHECK_STACK_PROPERTY, LLK_CHECK_STACK_DEFAULT);
}
- std::string defaultBlacklistStack(LLK_BLACKLIST_STACK_DEFAULT);
- if (!debuggable) defaultBlacklistStack += ",logd,/system/bin/logd";
- llkBlacklistStack = llkSplit(LLK_BLACKLIST_STACK_PROPERTY, defaultBlacklistStack);
+ std::string defaultIgnorelistStack(LLK_IGNORELIST_STACK_DEFAULT);
+ if (!debuggable) defaultIgnorelistStack += ",logd,/system/bin/logd";
+ llkIgnorelistStack = llkSplit(LLK_IGNORELIST_STACK_PROPERTY, defaultIgnorelistStack);
#endif
- std::string defaultBlacklistProcess(
- std::to_string(kernelPid) + "," + std::to_string(initPid) + "," +
- std::to_string(kthreaddPid) + "," + std::to_string(::getpid()) + "," +
- std::to_string(::gettid()) + "," LLK_BLACKLIST_PROCESS_DEFAULT);
+ std::string defaultIgnorelistProcess(
+ std::to_string(kernelPid) + "," + std::to_string(initPid) + "," +
+ std::to_string(kthreaddPid) + "," + std::to_string(::getpid()) + "," +
+ std::to_string(::gettid()) + "," LLK_IGNORELIST_PROCESS_DEFAULT);
if (threadname) {
- defaultBlacklistProcess += ","s + threadname;
+ defaultIgnorelistProcess += ","s + threadname;
}
for (int cpu = 1; cpu < get_nprocs_conf(); ++cpu) {
- defaultBlacklistProcess += ",[watchdog/" + std::to_string(cpu) + "]";
+ defaultIgnorelistProcess += ",[watchdog/" + std::to_string(cpu) + "]";
}
- llkBlacklistProcess = llkSplit(LLK_BLACKLIST_PROCESS_PROPERTY, defaultBlacklistProcess);
+ llkIgnorelistProcess = llkSplit(LLK_IGNORELIST_PROCESS_PROPERTY, defaultIgnorelistProcess);
if (!llkSkipName("[khungtaskd]")) { // ALWAYS ignore as special
- llkBlacklistProcess.emplace("[khungtaskd]");
+ llkIgnorelistProcess.emplace("[khungtaskd]");
}
- llkBlacklistParent = llkSplit(LLK_BLACKLIST_PARENT_PROPERTY,
- std::to_string(kernelPid) + "," + std::to_string(kthreaddPid) +
- "," LLK_BLACKLIST_PARENT_DEFAULT);
- // derive llkBlacklistParentAndChild by moving entries with '&' from above
- for (auto it = llkBlacklistParent.begin(); it != llkBlacklistParent.end();) {
+ llkIgnorelistParent = llkSplit(LLK_IGNORELIST_PARENT_PROPERTY,
+ std::to_string(kernelPid) + "," + std::to_string(kthreaddPid) +
+ "," LLK_IGNORELIST_PARENT_DEFAULT);
+ // derive llkIgnorelistParentAndChild by moving entries with '&' from above
+ for (auto it = llkIgnorelistParent.begin(); it != llkIgnorelistParent.end();) {
auto pos = it->find('&');
if (pos == std::string::npos) {
++it;
@@ -1350,18 +1350,18 @@
}
auto parent = it->substr(0, pos);
auto child = it->substr(pos + 1);
- it = llkBlacklistParent.erase(it);
+ it = llkIgnorelistParent.erase(it);
- auto found = llkBlacklistParentAndChild.find(parent);
- if (found == llkBlacklistParentAndChild.end()) {
- llkBlacklistParentAndChild.emplace(std::make_pair(
+ auto found = llkIgnorelistParentAndChild.find(parent);
+ if (found == llkIgnorelistParentAndChild.end()) {
+ llkIgnorelistParentAndChild.emplace(std::make_pair(
std::move(parent), std::unordered_set<std::string>({std::move(child)})));
} else {
found->second.emplace(std::move(child));
}
}
- llkBlacklistUid = llkSplit(LLK_BLACKLIST_UID_PROPERTY, LLK_BLACKLIST_UID_DEFAULT);
+ llkIgnorelistUid = llkSplit(LLK_IGNORELIST_UID_PROPERTY, LLK_IGNORELIST_UID_DEFAULT);
// internal watchdog
::signal(SIGALRM, llkAlarmHandler);
diff --git a/logd/main.cpp b/logd/main.cpp
index 23bbf86..acf9a07 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -62,14 +62,13 @@
// has a 'sigstop' feature that sends SIGSTOP to a service immediately before calling exec(). This
// allows debuggers, etc to be attached to logd at the very beginning, while still having init
// handle the user, groups, capabilities, files, etc setup.
-static int drop_privs(bool klogd, bool auditd) {
- sched_param param = {};
-
+static int DropPrivs(bool klogd, bool auditd) {
if (set_sched_policy(0, SP_BACKGROUND) < 0) {
android::prdebug("failed to set background scheduling policy");
return -1;
}
+ sched_param param = {};
if (sched_setscheduler((pid_t)0, SCHED_BATCH, ¶m) < 0) {
android::prdebug("failed to set batch scheduler");
return -1;
@@ -84,21 +83,24 @@
std::unique_ptr<struct _cap_struct, int (*)(void*)> caps(cap_init(), cap_free);
if (cap_clear(caps.get()) < 0) {
+ android::prdebug("cap_clear() failed");
return -1;
}
- std::vector<cap_value_t> cap_value;
if (klogd) {
- cap_value.emplace_back(CAP_SYSLOG);
+ cap_value_t cap_syslog = CAP_SYSLOG;
+ if (cap_set_flag(caps.get(), CAP_PERMITTED, 1, &cap_syslog, CAP_SET) < 0 ||
+ cap_set_flag(caps.get(), CAP_EFFECTIVE, 1, &cap_syslog, CAP_SET) < 0) {
+ android::prdebug("Failed to set CAP_SYSLOG");
+ return -1;
+ }
}
if (auditd) {
- cap_value.emplace_back(CAP_AUDIT_CONTROL);
- }
-
- if (cap_set_flag(caps.get(), CAP_PERMITTED, cap_value.size(), cap_value.data(), CAP_SET) < 0) {
- return -1;
- }
- if (cap_set_flag(caps.get(), CAP_EFFECTIVE, cap_value.size(), cap_value.data(), CAP_SET) < 0) {
- return -1;
+ cap_value_t cap_audit_control = CAP_AUDIT_CONTROL;
+ if (cap_set_flag(caps.get(), CAP_PERMITTED, 1, &cap_audit_control, CAP_SET) < 0 ||
+ cap_set_flag(caps.get(), CAP_EFFECTIVE, 1, &cap_audit_control, CAP_SET) < 0) {
+ android::prdebug("Failed to set CAP_AUDIT_CONTROL");
+ return -1;
+ }
}
if (cap_set_proc(caps.get()) < 0) {
android::prdebug("failed to set CAP_SYSLOG or CAP_AUDIT_CONTROL (%d)", errno);
@@ -332,7 +334,7 @@
}
bool auditd = __android_logger_property_get_bool("ro.logd.auditd", BOOL_DEFAULT_TRUE);
- if (drop_privs(klogd, auditd) != 0) {
+ if (DropPrivs(klogd, auditd) != 0) {
return EXIT_FAILURE;
}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 73ac7fd..510d1e9 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -448,6 +448,9 @@
# Load persist properties and override properties (if enabled) from /data.
trigger load_persist_props_action
+ # Should be before netd, but after apex, properties and logging is available.
+ trigger load_bpf_programs
+
# Now we can start zygote for devices with file based encryption
trigger zygote-start
@@ -517,6 +520,12 @@
mkdir /metadata/apex 0700 root system
mkdir /metadata/apex/sessions 0700 root system
+ # On some devices we see a weird behaviour in which /metadata/apex doesn't
+ # have a correct label. To workaround this bug, explicitly call restorecon
+ # on /metadata/apex. For most of the boot sequences /metadata/apex will
+ # already have a correct selinux label, meaning that this call will be a
+ # no-op.
+ restorecon_recursive /metadata/apex
mkdir /metadata/staged-install 0770 root system
on late-fs
@@ -815,6 +824,7 @@
on zygote-start && property:ro.crypto.state=unencrypted
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
+ start statsd
start netd
start zygote
start zygote_secondary
@@ -822,6 +832,7 @@
on zygote-start && property:ro.crypto.state=unsupported
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
+ start statsd
start netd
start zygote
start zygote_secondary
@@ -829,6 +840,7 @@
on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
+ start statsd
start netd
start zygote
start zygote_secondary
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 7029748..fb9e99b 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -12,7 +12,7 @@
onrestart restart media
onrestart restart netd
onrestart restart wificond
- writepid /dev/cpuset/foreground/tasks
+ task_profiles ProcessCapacityHigh MaxPerformance
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
class main
@@ -22,4 +22,4 @@
socket zygote_secondary stream 660 root system
socket usap_pool_secondary stream 660 root system
onrestart restart zygote
- writepid /dev/cpuset/foreground/tasks
+ task_profiles ProcessCapacityHigh MaxPerformance
diff --git a/toolbox/modprobe.cpp b/toolbox/modprobe.cpp
index 1b5f54e..3ffa74e 100644
--- a/toolbox/modprobe.cpp
+++ b/toolbox/modprobe.cpp
@@ -36,7 +36,7 @@
std::cerr << " modprobe [-alrqvsDb] [-d DIR] MODULE [symbol=value][...]" << std::endl;
std::cerr << std::endl;
std::cerr << "Options:" << std::endl;
- std::cerr << " -b: Apply blacklist to module names too" << std::endl;
+ std::cerr << " -b: Apply blocklist to module names too" << std::endl;
std::cerr << " -d: Load modules from DIR, option may be used multiple times" << std::endl;
std::cerr << " -D: Print dependencies for modules only, do not load";
std::cerr << " -h: Print this help" << std::endl;
@@ -59,7 +59,7 @@
std::string module_parameters;
std::vector<std::string> mod_dirs;
modprobe_mode mode = AddModulesMode;
- bool blacklist = false;
+ bool blocklist = false;
bool verbose = false;
int rv = EXIT_SUCCESS;
@@ -72,7 +72,7 @@
check_mode();
break;
case 'b':
- blacklist = true;
+ blocklist = true;
break;
case 'd':
mod_dirs.emplace_back(optarg);
@@ -151,8 +151,8 @@
Modprobe m(mod_dirs);
m.EnableVerbose(verbose);
- if (blacklist) {
- m.EnableBlacklist(true);
+ if (blocklist) {
+ m.EnableBlocklist(true);
}
for (const auto& module : modules) {