Merge "trusty: Add trusty unittest control utility"
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 07f9d66..07e3c8a 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -212,7 +212,7 @@
sABOverrideValue = ab_device;
}
-MetadataBuilder::MetadataBuilder() : auto_slot_suffixing_(false) {
+MetadataBuilder::MetadataBuilder() : auto_slot_suffixing_(false), ignore_slot_suffixing_(false) {
memset(&geometry_, 0, sizeof(geometry_));
geometry_.magic = LP_METADATA_GEOMETRY_MAGIC;
geometry_.struct_size = sizeof(geometry_);
@@ -436,7 +436,7 @@
LERROR << "Could not find partition group: " << group_name;
return nullptr;
}
- if (IsABDevice() && !auto_slot_suffixing_ && name != "scratch" &&
+ if (IsABDevice() && !auto_slot_suffixing_ && name != "scratch" && !ignore_slot_suffixing_ &&
GetPartitionSlotSuffix(name).empty()) {
LERROR << "Unsuffixed partition not allowed on A/B device: " << name;
return nullptr;
@@ -972,6 +972,10 @@
auto_slot_suffixing_ = true;
}
+void MetadataBuilder::IgnoreSlotSuffixing() {
+ ignore_slot_suffixing_ = true;
+}
+
bool MetadataBuilder::IsABDevice() const {
if (sABOverrideSet) {
return sABOverrideValue;
@@ -983,5 +987,18 @@
return GetBlockDevicePartitionName(block_devices_[0]) != LP_METADATA_DEFAULT_PARTITION_NAME;
}
+bool MetadataBuilder::AddLinearExtent(Partition* partition, const std::string& block_device,
+ uint64_t num_sectors, uint64_t physical_sector) {
+ uint32_t device_index;
+ if (!FindBlockDeviceByName(block_device, &device_index)) {
+ LERROR << "Could not find backing block device for extent: " << block_device;
+ return false;
+ }
+
+ auto extent = std::make_unique<LinearExtent>(num_sectors, device_index, physical_sector);
+ partition->AddExtent(std::move(extent));
+ return true;
+}
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index f477b4b..57cce21 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -219,6 +219,10 @@
// Find a group by name. If no group is found, nullptr is returned.
PartitionGroup* FindGroup(const std::string& name);
+ // Add a predetermined extent to a partition.
+ bool AddLinearExtent(Partition* partition, const std::string& block_device,
+ uint64_t num_sectors, uint64_t physical_sector);
+
// Grow or shrink a partition to the requested size. This size will be
// rounded UP to the nearest block (512 bytes).
//
@@ -244,6 +248,9 @@
// Set the LP_METADATA_AUTO_SLOT_SUFFIXING flag.
void SetAutoSlotSuffixing();
+ // If set, checks for slot suffixes will be ignored internally.
+ void IgnoreSlotSuffixing();
+
bool GetBlockDeviceInfo(const std::string& partition_name, BlockDeviceInfo* info) const;
bool UpdateBlockDeviceInfo(const std::string& partition_name, const BlockDeviceInfo& info);
@@ -306,6 +313,7 @@
std::vector<std::unique_ptr<PartitionGroup>> groups_;
std::vector<LpMetadataBlockDevice> block_devices_;
bool auto_slot_suffixing_;
+ bool ignore_slot_suffixing_;
};
// Read BlockDeviceInfo for a given block device. This always returns false
diff --git a/init/devices.cpp b/init/devices.cpp
index 45b17a2..1a77ba1 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -320,6 +320,7 @@
auto link_path = "/dev/block/" + type + "/" + device;
+ bool is_boot_device = boot_devices_.find(device) != boot_devices_.end();
if (!uevent.partition_name.empty()) {
std::string partition_name_sanitized(uevent.partition_name);
SanitizePartitionName(&partition_name_sanitized);
@@ -329,9 +330,13 @@
}
links.emplace_back(link_path + "/by-name/" + partition_name_sanitized);
// Adds symlink: /dev/block/by-name/<partition_name>.
- if (boot_devices_.find(device) != boot_devices_.end()) {
+ if (is_boot_device) {
links.emplace_back("/dev/block/by-name/" + partition_name_sanitized);
}
+ } else if (is_boot_device) {
+ // If we don't have a partition name but we are a partition on a boot device, create a
+ // symlink of /dev/block/by-name/<device_name> for symmetry.
+ links.emplace_back("/dev/block/by-name/" + uevent.device_name);
}
auto last_slash = uevent.path.rfind('/');
diff --git a/llkd/README.md b/llkd/README.md
index 224e184..43bb94a 100644
--- a/llkd/README.md
+++ b/llkd/README.md
@@ -86,7 +86,13 @@
Android Properties
------------------
-Android Properties llkd respond to (*prop*_ms parms are in milliseconds):
+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.
#### ro.config.low_ram
device is configured with limited memory.
@@ -135,8 +141,8 @@
default 2 minutes samples of threads for D or Z.
#### ro.llk.stack
-default cma_alloc,__get_user_pages,bit_wait_io comma separated list of kernel
-symbols. The string "*false*" is the equivalent to an *empty* list.
+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
@@ -153,7 +159,6 @@
default 0,1,2 (kernel, init and [kthreadd]) plus process names
init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd,
[watchdogd],[watchdogd/0],...,[watchdogd/***get_nprocs**-1*].
-The string "*false*" is the equivalent to an *empty* list.
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.
@@ -161,18 +166,15 @@
#### ro.llk.blacklist.parent
default 0,2,adbd (kernel, [kthreadd] and adbd).
-The string "*false*" is the equivalent to an *empty* list.
Do not watch processes that have this parent.
A parent process can be comm, cmdline or pid reference.
#### ro.llk.blacklist.uid
default *empty* or false, comma separated list of uid numbers or names.
-The string "*false*" is the equivalent to an *empty* list.
Do not watch processes that match this uid.
#### ro.llk.blacklist.process.stack
default process names init,lmkd.llkd,llkd,keystore,ueventd,apexd,logd.
-The string "*false*" is the equivalent to an *empty* list.
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.
diff --git a/llkd/include/llkd.h b/llkd/include/llkd.h
index 1efa32b..7b7dbf9 100644
--- a/llkd/include/llkd.h
+++ b/llkd/include/llkd.h
@@ -50,7 +50,8 @@
/* 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 "cma_alloc,__get_user_pages,bit_wait_io"
+#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 \
"0,1,2,init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 267da4a..3a593ec 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -24,6 +24,7 @@
#include <pwd.h> // getpwuid()
#include <signal.h>
#include <stdint.h>
+#include <string.h>
#include <sys/cdefs.h> // ___STRING, __predict_true() and _predict_false()
#include <sys/mman.h> // mlockall()
#include <sys/prctl.h>
@@ -617,17 +618,24 @@
std::string llkFormat(const std::unordered_set<std::string>& blacklist) {
std::string ret;
for (const auto& entry : blacklist) {
- if (ret.size()) {
- ret += ",";
- }
+ if (!ret.empty()) ret += ",";
ret += entry;
}
return ret;
}
+// This function parses the properties as a list, incorporating the supplied
+// default. A leading comma separator means preserve the defaults and add
+// entries (with an optional leading + sign), or removes entries with a leading
+// - sign.
+//
// We only officially support comma separators, but wetware being what they
// are will take some liberty and I do not believe they should be punished.
-std::unordered_set<std::string> llkSplit(const std::string& s) {
+std::unordered_set<std::string> llkSplit(const std::string& prop, const std::string& def) {
+ auto s = android::base::GetProperty(prop, def);
+ constexpr char separators[] = ", \t:;";
+ if (!s.empty() && (s != def) && strchr(separators, s[0])) s = def + s;
+
std::unordered_set<std::string> result;
// Special case, allow boolean false to empty the list, otherwise expected
@@ -637,9 +645,29 @@
size_t base = 0;
while (s.size() > base) {
- auto found = s.find_first_of(", \t:", base);
- // Only emplace content, empty entries are not an option
- if (found != base) result.emplace(s.substr(base, found - base));
+ auto found = s.find_first_of(separators, base);
+ // Only emplace unique content, empty entries are not an option
+ if (found != base) {
+ switch (s[base]) {
+ case '-':
+ ++base;
+ if (base >= s.size()) break;
+ if (base != found) {
+ auto have = result.find(s.substr(base, found - base));
+ if (have != result.end()) result.erase(have);
+ }
+ break;
+ case '+':
+ ++base;
+ if (base >= s.size()) break;
+ if (base == found) break;
+ // FALLTHRU (for gcc, lint, pcc, etc; following for clang)
+ FALLTHROUGH_INTENDED;
+ default:
+ result.emplace(s.substr(base, found - base));
+ break;
+ }
+ }
if (found == s.npos) break;
base = found + 1;
}
@@ -648,13 +676,21 @@
bool llkSkipName(const std::string& name,
const std::unordered_set<std::string>& blacklist = llkBlacklistProcess) {
- if ((name.size() == 0) || (blacklist.size() == 0)) {
- return false;
- }
+ if (name.empty() || blacklist.empty()) return false;
return blacklist.find(name) != blacklist.end();
}
+bool llkSkipProc(proc* procp,
+ const std::unordered_set<std::string>& blacklist = llkBlacklistProcess) {
+ 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;
+ return false;
+}
+
bool llkSkipPid(pid_t pid) {
return llkSkipName(std::to_string(pid), llkBlacklistProcess);
}
@@ -730,26 +766,24 @@
}
// Don't check process that are known to block ptrace, save sepolicy noise.
- if (llkSkipName(std::to_string(procp->pid), llkBlacklistStack)) return false;
- if (llkSkipName(procp->getComm(), llkBlacklistStack)) return false;
- if (llkSkipName(procp->getCmdline(), llkBlacklistStack)) return false;
- if (llkSkipName(android::base::Basename(procp->getCmdline()), llkBlacklistStack)) return false;
-
+ if (llkSkipProc(procp, llkBlacklistStack)) return false;
auto kernel_stack = ReadFile(piddir + "/stack");
if (kernel_stack.empty()) {
- LOG(INFO) << piddir << "/stack empty comm=" << procp->getComm()
- << " cmdline=" << procp->getCmdline();
+ LOG(VERBOSE) << piddir << "/stack empty comm=" << procp->getComm()
+ << " cmdline=" << procp->getCmdline();
return false;
}
// A scheduling incident that should not reset count_stack
if (kernel_stack.find(" cpu_worker_pools+0x") != std::string::npos) return false;
char idx = -1;
char match = -1;
+ std::string matched_stack_symbol = "<unknown>";
for (const auto& stack : llkCheckStackSymbols) {
if (++idx < 0) break;
if ((kernel_stack.find(" "s + stack + "+0x") != std::string::npos) ||
(kernel_stack.find(" "s + stack + ".cfi+0x") != std::string::npos)) {
match = idx;
+ matched_stack_symbol = stack;
break;
}
}
@@ -760,7 +794,9 @@
}
if (match == char(-1)) return false;
procp->count_stack += llkCycle;
- return procp->count_stack >= llkStateTimeoutMs[llkStateStack];
+ if (procp->count_stack < llkStateTimeoutMs[llkStateStack]) return false;
+ LOG(WARNING) << "Found " << matched_stack_symbol << " in stack for pid " << procp->pid;
+ return true;
}
#endif
@@ -776,12 +812,12 @@
// but if there are problems we assume at least a few
// samples of reads occur before we take any real action.
std::string schedString = ReadFile(piddir + "/sched");
- if (schedString.size() == 0) {
+ if (schedString.empty()) {
// /schedstat is not as standardized, but in 3.1+
// Android devices, the third field is nr_switches
// from /sched:
schedString = ReadFile(piddir + "/schedstat");
- if (schedString.size() == 0) {
+ if (schedString.empty()) {
return;
}
auto val = static_cast<unsigned long long>(-1);
@@ -939,7 +975,7 @@
// Get the process stat
std::string stat = ReadFile(piddir + "/stat");
- if (stat.size() == 0) {
+ if (stat.empty()) {
continue;
}
unsigned tid = -1;
@@ -1028,11 +1064,10 @@
if (pprocp == nullptr) {
pprocp = llkTidAlloc(ppid, ppid, 0, "", 0, '?');
}
- if ((pprocp != nullptr) &&
- (llkSkipName(pprocp->getComm(), llkBlacklistParent) ||
- llkSkipName(pprocp->getCmdline(), llkBlacklistParent) ||
- llkSkipName(android::base::Basename(pprocp->getCmdline()), llkBlacklistParent))) {
- break;
+ if (pprocp) {
+ if (llkSkipProc(pprocp, llkBlacklistParent)) break;
+ } else {
+ if (llkSkipName(std::to_string(ppid), llkBlacklistParent)) break;
}
if ((llkBlacklistUid.size() != 0) && llkSkipUid(procp->getUid())) {
@@ -1131,21 +1166,15 @@
if (!p->second.updated) {
IF_ALOG(LOG_VERBOSE, LOG_TAG) {
std::string ppidCmdline = llkProcGetName(p->second.ppid, nullptr, nullptr);
- if (ppidCmdline.size()) {
- ppidCmdline = "(" + ppidCmdline + ")";
- }
+ if (!ppidCmdline.empty()) ppidCmdline = "(" + ppidCmdline + ")";
std::string pidCmdline;
if (p->second.pid != p->second.tid) {
pidCmdline = llkProcGetName(p->second.pid, nullptr, p->second.getCmdline());
- if (pidCmdline.size()) {
- pidCmdline = "(" + pidCmdline + ")";
- }
+ if (!pidCmdline.empty()) pidCmdline = "(" + pidCmdline + ")";
}
std::string tidCmdline =
llkProcGetName(p->second.tid, p->second.getComm(), p->second.getCmdline());
- if (tidCmdline.size()) {
- tidCmdline = "(" + tidCmdline + ")";
- }
+ if (!tidCmdline.empty()) tidCmdline = "(" + tidCmdline + ")";
LOG(VERBOSE) << "thread " << p->second.ppid << ppidCmdline << "->" << p->second.pid
<< pidCmdline << "->" << p->second.tid << tidCmdline << " removed";
}
@@ -1222,13 +1251,11 @@
llkValidate(); // validate all (effectively minus llkTimeoutMs)
#ifdef __PTRACE_ENABLED__
if (debuggable) {
- llkCheckStackSymbols = llkSplit(
- android::base::GetProperty(LLK_CHECK_STACK_PROPERTY, LLK_CHECK_STACK_DEFAULT));
+ 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(
- android::base::GetProperty(LLK_BLACKLIST_STACK_PROPERTY, defaultBlacklistStack));
+ llkBlacklistStack = llkSplit(LLK_BLACKLIST_STACK_PROPERTY, defaultBlacklistStack);
#endif
std::string defaultBlacklistProcess(
std::to_string(kernelPid) + "," + std::to_string(initPid) + "," +
@@ -1240,17 +1267,14 @@
for (int cpu = 1; cpu < get_nprocs_conf(); ++cpu) {
defaultBlacklistProcess += ",[watchdog/" + std::to_string(cpu) + "]";
}
- defaultBlacklistProcess =
- android::base::GetProperty(LLK_BLACKLIST_PROCESS_PROPERTY, defaultBlacklistProcess);
- llkBlacklistProcess = llkSplit(defaultBlacklistProcess);
+ llkBlacklistProcess = llkSplit(LLK_BLACKLIST_PROCESS_PROPERTY, defaultBlacklistProcess);
if (!llkSkipName("[khungtaskd]")) { // ALWAYS ignore as special
llkBlacklistProcess.emplace("[khungtaskd]");
}
- llkBlacklistParent = llkSplit(android::base::GetProperty(
- LLK_BLACKLIST_PARENT_PROPERTY, std::to_string(kernelPid) + "," + std::to_string(kthreaddPid) +
- "," LLK_BLACKLIST_PARENT_DEFAULT));
- llkBlacklistUid =
- llkSplit(android::base::GetProperty(LLK_BLACKLIST_UID_PROPERTY, LLK_BLACKLIST_UID_DEFAULT));
+ llkBlacklistParent = llkSplit(LLK_BLACKLIST_PARENT_PROPERTY,
+ std::to_string(kernelPid) + "," + std::to_string(kthreaddPid) +
+ "," LLK_BLACKLIST_PARENT_DEFAULT);
+ llkBlacklistUid = llkSplit(LLK_BLACKLIST_UID_PROPERTY, LLK_BLACKLIST_UID_DEFAULT);
// internal watchdog
::signal(SIGALRM, llkAlarmHandler);
diff --git a/llkd/tests/llkd_test.cpp b/llkd/tests/llkd_test.cpp
index f54932b..d738935 100644
--- a/llkd/tests/llkd_test.cpp
+++ b/llkd/tests/llkd_test.cpp
@@ -87,7 +87,8 @@
execute("stop llkd-1");
rest();
std::string setprop("setprop ");
- execute((setprop + LLK_CHECK_STACK_PROPERTY + " SyS_openat").c_str());
+ // Manually check that SyS_openat is _added_ to the list when restarted
+ execute((setprop + LLK_CHECK_STACK_PROPERTY + " ,SyS_openat").c_str());
rest();
execute((setprop + LLK_ENABLE_WRITEABLE_PROPERTY + " false").c_str());
rest();