Merge "Suppress clang-analyzer-security.FloatLoopCounter warnings"
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 2a769c7..70f333e 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -303,6 +303,7 @@
process_info->scudo_stack_depot = crash_info->data.d.scudo_stack_depot;
process_info->scudo_region_info = crash_info->data.d.scudo_region_info;
process_info->scudo_ring_buffer = crash_info->data.d.scudo_ring_buffer;
+ process_info->scudo_ring_buffer_size = crash_info->data.d.scudo_ring_buffer_size;
FALLTHROUGH_INTENDED;
case 1:
case 2:
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index c64de0e..7120d73 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -187,27 +187,29 @@
* mutex is being held, so we don't want to use any libc functions that
* could allocate memory or hold a lock.
*/
-static void log_signal_summary(const siginfo_t* info) {
+static void log_signal_summary(const siginfo_t* si) {
char main_thread_name[MAX_TASK_NAME_LEN + 1];
if (!get_main_thread_name(main_thread_name, sizeof(main_thread_name))) {
strncpy(main_thread_name, "<unknown>", sizeof(main_thread_name));
}
- if (info->si_signo == BIONIC_SIGNAL_DEBUGGER) {
+ if (si->si_signo == BIONIC_SIGNAL_DEBUGGER) {
async_safe_format_log(ANDROID_LOG_INFO, "libc", "Requested dump for pid %d (%s)", __getpid(),
main_thread_name);
return;
}
- // Many signals don't have an address or sender.
- char addr_desc[32] = ""; // ", fault addr 0x1234"
- if (signal_has_si_addr(info)) {
- async_safe_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
- }
+ // Many signals don't have a sender or extra detail, but some do...
pid_t self_pid = __getpid();
char sender_desc[32] = {}; // " from pid 1234, uid 666"
- if (signal_has_sender(info, self_pid)) {
- get_signal_sender(sender_desc, sizeof(sender_desc), info);
+ if (signal_has_sender(si, self_pid)) {
+ get_signal_sender(sender_desc, sizeof(sender_desc), si);
+ }
+ char extra_desc[32] = {}; // ", fault addr 0x1234" or ", syscall 1234"
+ if (si->si_signo == SIGSYS && si->si_code == SYS_SECCOMP) {
+ async_safe_format_buffer(extra_desc, sizeof(extra_desc), ", syscall %d", si->si_syscall);
+ } else if (signal_has_si_addr(si)) {
+ async_safe_format_buffer(extra_desc, sizeof(extra_desc), ", fault addr %p", si->si_addr);
}
char thread_name[MAX_TASK_NAME_LEN + 1]; // one more for termination
@@ -221,8 +223,8 @@
async_safe_format_log(ANDROID_LOG_FATAL, "libc",
"Fatal signal %d (%s), code %d (%s%s)%s in tid %d (%s), pid %d (%s)",
- info->si_signo, get_signame(info), info->si_code, get_sigcode(info),
- sender_desc, addr_desc, __gettid(), thread_name, self_pid, main_thread_name);
+ si->si_signo, get_signame(si), si->si_code, get_sigcode(si), sender_desc,
+ extra_desc, __gettid(), thread_name, self_pid, main_thread_name);
}
/*
@@ -371,12 +373,30 @@
{.iov_base = thread_info->ucontext, .iov_len = sizeof(ucontext_t)},
};
+ constexpr size_t kHeaderSize = sizeof(version) + sizeof(siginfo_t) + sizeof(ucontext_t);
+
if (thread_info->process_info.fdsan_table) {
// Dynamic executables always use version 4. There is no need to increment the version number if
// the format changes, because the sender (linker) and receiver (crash_dump) are version locked.
version = 4;
expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic);
+ static_assert(sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic) ==
+ kHeaderSize + sizeof(thread_info->process_info),
+ "Wire protocol structs do not match the data sent.");
+#define ASSERT_SAME_OFFSET(MEMBER1, MEMBER2) \
+ static_assert(sizeof(CrashInfoHeader) + offsetof(CrashInfoDataDynamic, MEMBER1) == \
+ kHeaderSize + offsetof(debugger_process_info, MEMBER2), \
+ "Wire protocol offset does not match data sent: " #MEMBER1);
+ ASSERT_SAME_OFFSET(fdsan_table_address, fdsan_table);
+ ASSERT_SAME_OFFSET(gwp_asan_state, gwp_asan_state);
+ ASSERT_SAME_OFFSET(gwp_asan_metadata, gwp_asan_metadata);
+ ASSERT_SAME_OFFSET(scudo_stack_depot, scudo_stack_depot);
+ ASSERT_SAME_OFFSET(scudo_region_info, scudo_region_info);
+ ASSERT_SAME_OFFSET(scudo_ring_buffer, scudo_ring_buffer);
+ ASSERT_SAME_OFFSET(scudo_ring_buffer_size, scudo_ring_buffer_size);
+#undef ASSERT_SAME_OFFSET
+
iovs[3] = {.iov_base = &thread_info->process_info,
.iov_len = sizeof(thread_info->process_info)};
} else {
@@ -384,6 +404,10 @@
version = 1;
expected = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic);
+ static_assert(
+ sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic) == kHeaderSize + sizeof(uintptr_t),
+ "Wire protocol structs do not match the data sent.");
+
iovs[3] = {.iov_base = &thread_info->process_info.abort_msg, .iov_len = sizeof(uintptr_t)};
}
errno = 0;
diff --git a/debuggerd/include/debuggerd/handler.h b/debuggerd/include/debuggerd/handler.h
index 68b2e67..1f9f4e2 100644
--- a/debuggerd/include/debuggerd/handler.h
+++ b/debuggerd/include/debuggerd/handler.h
@@ -43,6 +43,7 @@
const char* scudo_stack_depot;
const char* scudo_region_info;
const char* scudo_ring_buffer;
+ size_t scudo_ring_buffer_size;
};
// These callbacks are called in a signal handler, and thus must be async signal safe.
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index a51e276..5a2a7ab 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -50,6 +50,7 @@
uintptr_t scudo_stack_depot = 0;
uintptr_t scudo_region_info = 0;
uintptr_t scudo_ring_buffer = 0;
+ size_t scudo_ring_buffer_size = 0;
bool has_fault_address = false;
uintptr_t untagged_fault_address = 0;
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
index 5d861f8..37e390b 100644
--- a/debuggerd/libdebuggerd/scudo.cpp
+++ b/debuggerd/libdebuggerd/scudo.cpp
@@ -45,7 +45,7 @@
auto region_info = AllocAndReadFully(process_memory, process_info.scudo_region_info,
__scudo_get_region_info_size());
auto ring_buffer = AllocAndReadFully(process_memory, process_info.scudo_ring_buffer,
- __scudo_get_ring_buffer_size());
+ process_info.scudo_ring_buffer_size);
if (!stack_depot || !region_info || !ring_buffer) {
return;
}
diff --git a/debuggerd/protocol.h b/debuggerd/protocol.h
index f33b2f0..e7cb218 100644
--- a/debuggerd/protocol.h
+++ b/debuggerd/protocol.h
@@ -98,6 +98,7 @@
uintptr_t scudo_stack_depot;
uintptr_t scudo_region_info;
uintptr_t scudo_ring_buffer;
+ size_t scudo_ring_buffer_size;
};
struct __attribute__((__packed__)) CrashInfo {
diff --git a/debuggerd/test_permissive_mte/Android.bp b/debuggerd/test_permissive_mte/Android.bp
index 1c09240..d3f7520 100644
--- a/debuggerd/test_permissive_mte/Android.bp
+++ b/debuggerd/test_permissive_mte/Android.bp
@@ -18,6 +18,7 @@
cc_binary {
name: "mte_crash",
+ tidy: false,
srcs: ["mte_crash.cpp"],
sanitize: {
memtag_heap: true,
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index 610eebf..a4b9307 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -191,16 +191,30 @@
// Iterate over the endpoints for this interface and see if there
// are any that do bulk in/out.
- for (UInt8 endpoint = 1; endpoint <= interfaceNumEndpoints; endpoint++) {
+ for (UInt8 endpoint = 1; endpoint <= interfaceNumEndpoints; ++endpoint) {
UInt8 transferType;
- UInt16 maxPacketSize;
+ UInt16 endPointMaxPacketSize = 0;
UInt8 interval;
+
+ // Attempt to retrieve the 'true' packet-size from supported interface.
+ kr = (*interface)
+ ->GetEndpointProperties(interface, 0, endpoint,
+ kUSBOut,
+ &transferType,
+ &endPointMaxPacketSize, &interval);
+ if (kr == kIOReturnSuccess && !endPointMaxPacketSize) {
+ ERR("GetEndpointProperties() returned zero len packet-size");
+ }
+
+ UInt16 pipePropMaxPacketSize;
UInt8 number;
UInt8 direction;
+ // Proceed with extracting the transfer direction, so we can fill in the
+ // appropriate fields (bulkIn or bulkOut).
kr = (*interface)->GetPipeProperties(interface, endpoint,
&direction,
- &number, &transferType, &maxPacketSize, &interval);
+ &number, &transferType, &pipePropMaxPacketSize, &interval);
if (kr == 0) {
if (transferType != kUSBBulk) {
@@ -216,7 +230,8 @@
}
if (handle->info.ifc_protocol == 0x01) {
- handle->zero_mask = maxPacketSize - 1;
+ handle->zero_mask = (endPointMaxPacketSize == 0) ?
+ pipePropMaxPacketSize - 1 : endPointMaxPacketSize - 1;
}
} else {
ERR("could not get pipe properties for endpoint %u (%08x)\n", endpoint, kr);
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index cdff06e..9eb89b6 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -395,6 +395,10 @@
// first-stage to decide whether to launch snapuserd.
bool IsSnapuserdRequired();
+ // This is primarily used to device reboot. If OTA update is in progress,
+ // init will avoid killing processes
+ bool IsUserspaceSnapshotUpdateInProgress();
+
enum class SnapshotDriver {
DM_SNAPSHOT,
DM_USER,
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 6fed09c..10d2f18 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -4349,5 +4349,16 @@
return status.source_build_fingerprint();
}
+bool SnapshotManager::IsUserspaceSnapshotUpdateInProgress() {
+ auto slot = GetCurrentSlot();
+ if (slot == Slot::Target) {
+ if (IsSnapuserdRequired()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace snapshot
} // namespace android
diff --git a/healthd/Android.bp b/healthd/Android.bp
index a090b74..76b6ad0 100644
--- a/healthd/Android.bp
+++ b/healthd/Android.bp
@@ -2,17 +2,8 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-cc_library_headers {
- name: "libhealthd_headers",
- vendor_available: true,
- recovery_available: true,
- export_include_dirs: ["include"],
- header_libs: ["libbatteryservice_headers"],
- export_header_lib_headers: ["libbatteryservice_headers"],
-}
-
-cc_library_static {
- name: "libbatterymonitor",
+cc_defaults {
+ name: "libbatterymonitor_defaults",
srcs: ["BatteryMonitor.cpp"],
cflags: ["-Wall", "-Werror"],
vendor_available: true,
@@ -25,6 +16,66 @@
// Need HealthInfo definition from headers of these shared
// libraries. Clients don't need to link to these.
"android.hardware.health@2.1",
+ ],
+ header_libs: ["libhealthd_headers"],
+ export_header_lib_headers: ["libhealthd_headers"],
+}
+
+cc_defaults {
+ name: "libhealthd_charger_ui_defaults",
+ vendor_available: true,
+ export_include_dirs: [
+ "include",
+ "include_charger",
+ ],
+
+ static_libs: [
+ "libcharger_sysprop",
+ "libhealthd_draw",
+ "libhealthloop",
+ "libminui",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "liblog",
+ "libpng",
+ "libsuspend",
+ "libutils",
+ ],
+
+ header_libs: [
+ "libhealthd_headers",
+ ],
+
+ srcs: [
+ "healthd_mode_charger.cpp",
+ "AnimationParser.cpp",
+ ],
+
+ target: {
+ vendor: {
+ exclude_static_libs: [
+ "libcharger_sysprop",
+ ],
+ },
+ },
+}
+
+cc_library_headers {
+ name: "libhealthd_headers",
+ vendor_available: true,
+ recovery_available: true,
+ export_include_dirs: ["include"],
+ header_libs: ["libbatteryservice_headers"],
+ export_header_lib_headers: ["libbatteryservice_headers"],
+}
+
+cc_library_static {
+ name: "libbatterymonitor",
+ defaults: ["libbatterymonitor_defaults"],
+ static_libs: [
"android.hardware.health-V1-ndk",
],
whole_static_libs: [
@@ -32,8 +83,20 @@
// BatteryMonitor.
"android.hardware.health-translate-ndk",
],
- header_libs: ["libhealthd_headers"],
- export_header_lib_headers: ["libhealthd_headers"],
+}
+
+// TODO(b/251425963): remove when android.hardware.health is upgraded to V2.
+cc_library_static {
+ name: "libbatterymonitor-V1",
+ defaults: ["libbatterymonitor_defaults"],
+ static_libs: [
+ "android.hardware.health-V1-ndk",
+ ],
+ whole_static_libs: [
+ // Need to translate HIDL to AIDL to support legacy APIs in
+ // BatteryMonitor.
+ "android.hardware.health-translate-V1-ndk",
+ ],
}
cc_defaults {
@@ -136,50 +199,31 @@
cc_library_static {
name: "libhealthd_charger_ui",
- vendor_available: true,
- export_include_dirs: [
- "include",
- "include_charger",
- ],
+ defaults: ["libhealthd_charger_ui_defaults"],
static_libs: [
"android.hardware.health-V1-ndk",
"android.hardware.health-translate-ndk",
- "libcharger_sysprop",
- "libhealthd_draw",
- "libhealthloop",
- "libminui",
- ],
-
- shared_libs: [
- "libbase",
- "libcutils",
- "liblog",
- "libpng",
- "libsuspend",
- "libutils",
- ],
-
- header_libs: [
- "libhealthd_headers",
],
export_static_lib_headers: [
"android.hardware.health-V1-ndk",
],
+}
- srcs: [
- "healthd_mode_charger.cpp",
- "AnimationParser.cpp",
+// TODO(b/251425963): remove when android.hardware.health is upgraded to V2.
+cc_library_static {
+ name: "libhealthd_charger_ui-V1",
+ defaults: ["libhealthd_charger_ui_defaults"],
+
+ static_libs: [
+ "android.hardware.health-V1-ndk",
+ "android.hardware.health-translate-V1-ndk",
],
- target: {
- vendor: {
- exclude_static_libs: [
- "libcharger_sysprop",
- ],
- },
- },
+ export_static_lib_headers: [
+ "android.hardware.health-V1-ndk",
+ ],
}
cc_library_static {
diff --git a/init/README.md b/init/README.md
index 957eb9e..4a5d0ec 100644
--- a/init/README.md
+++ b/init/README.md
@@ -244,6 +244,10 @@
"r", "w" or "rw". For native executables see libcutils
android\_get\_control\_file().
+`gentle_kill`
+> This service will be sent SIGTERM instead of SIGKILL when stopped. After a 200 ms timeout, it will
+ be sent SIGKILL.
+
`group <groupname> [ <groupname>\* ]`
> Change to 'groupname' before exec'ing this service. Additional
groupnames beyond the (required) first one are used to set the
diff --git a/init/apex_init_util.cpp b/init/apex_init_util.cpp
index d618a6e..c818f8f 100644
--- a/init/apex_init_util.cpp
+++ b/init/apex_init_util.cpp
@@ -18,7 +18,6 @@
#include <glob.h>
-#include <map>
#include <vector>
#include <android-base/logging.h>
@@ -66,18 +65,20 @@
}
static Result<void> ParseConfigs(const std::vector<std::string>& configs) {
- Parser parser = CreateApexConfigParser(ActionManager::GetInstance(),
- ServiceList::GetInstance());
- bool success = true;
+ Parser parser =
+ CreateApexConfigParser(ActionManager::GetInstance(), ServiceList::GetInstance());
+ std::vector<std::string> errors;
for (const auto& c : configs) {
- success &= parser.ParseConfigFile(c);
+ auto result = parser.ParseConfigFile(c);
+ // We should handle other config files even when there's an error.
+ if (!result.ok()) {
+ errors.push_back(result.error().message());
+ }
}
-
- if (success) {
- return {};
- } else {
- return Error() << "Unable to parse apex configs";
+ if (!errors.empty()) {
+ return Error() << "Unable to parse apex configs: " << base::Join(errors, "|");
}
+ return {};
}
Result<void> ParseApexConfigs(const std::string& apex_name) {
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 18a08c7..1e69ede 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -16,13 +16,16 @@
#include <functional>
#include <string_view>
+#include <thread>
#include <type_traits>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
+#include <android/api-level.h>
#include <gtest/gtest.h>
#include <selinux/selinux.h>
+#include <sys/resource.h>
#include "action.h"
#include "action_manager.h"
@@ -626,6 +629,105 @@
ASSERT_EQ(1u, parser.parse_error_count());
}
+TEST(init, MemLockLimit) {
+ // Test is enforced only for U+ devices
+ if (android::base::GetIntProperty("ro.vendor.api_level", 0) < __ANDROID_API_U__) {
+ GTEST_SKIP();
+ }
+
+ // Verify we are running memlock at, or under, 64KB
+ const unsigned long max_limit = 65536;
+ struct rlimit curr_limit;
+ ASSERT_EQ(getrlimit(RLIMIT_MEMLOCK, &curr_limit), 0);
+ ASSERT_LE(curr_limit.rlim_cur, max_limit);
+ ASSERT_LE(curr_limit.rlim_max, max_limit);
+}
+
+static std::vector<const char*> ConvertToArgv(const std::vector<std::string>& args) {
+ std::vector<const char*> argv;
+ argv.reserve(args.size() + 1);
+ for (const auto& arg : args) {
+ if (argv.empty()) {
+ LOG(DEBUG) << arg;
+ } else {
+ LOG(DEBUG) << " " << arg;
+ }
+ argv.emplace_back(arg.data());
+ }
+ argv.emplace_back(nullptr);
+ return argv;
+}
+
+pid_t ForkExecvpAsync(const std::vector<std::string>& args) {
+ auto argv = ConvertToArgv(args);
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+
+ execvp(argv[0], const_cast<char**>(argv.data()));
+ PLOG(ERROR) << "exec in ForkExecvpAsync init test";
+ _exit(EXIT_FAILURE);
+ }
+ if (pid == -1) {
+ PLOG(ERROR) << "fork in ForkExecvpAsync init test";
+ return -1;
+ }
+ return pid;
+}
+
+TEST(init, GentleKill) {
+ std::string init_script = R"init(
+service test_gentle_kill /system/bin/sleep 1000
+ disabled
+ oneshot
+ gentle_kill
+ user root
+ group root
+ seclabel u:r:toolbox:s0
+)init";
+
+ ActionManager action_manager;
+ ServiceList service_list;
+ TestInitText(init_script, BuiltinFunctionMap(), {}, &action_manager, &service_list);
+ ASSERT_EQ(std::distance(service_list.begin(), service_list.end()), 1);
+
+ auto service = service_list.begin()->get();
+ ASSERT_NE(service, nullptr);
+ ASSERT_RESULT_OK(service->Start());
+ const pid_t pid = service->pid();
+ ASSERT_GT(pid, 0);
+ EXPECT_NE(getsid(pid), 0);
+
+ TemporaryFile logfile;
+ logfile.DoNotRemove();
+ ASSERT_TRUE(logfile.fd != -1);
+
+ std::vector<std::string> cmd;
+ cmd.push_back("system/bin/strace");
+ cmd.push_back("-o");
+ cmd.push_back(logfile.path);
+ cmd.push_back("-e");
+ cmd.push_back("signal");
+ cmd.push_back("-p");
+ cmd.push_back(std::to_string(pid));
+ pid_t strace_pid = ForkExecvpAsync(cmd);
+
+ // Give strace a moment to connect
+ std::this_thread::sleep_for(1s);
+ service->Stop();
+
+ int status;
+ waitpid(strace_pid, &status, 0);
+
+ std::string logs;
+ android::base::ReadFdToString(logfile.fd, &logs);
+ int pos = logs.find("killed by SIGTERM");
+ ASSERT_NE(pos, (int)std::string::npos);
+}
+
class TestCaseLogger : public ::testing::EmptyTestEventListener {
void OnTestStart(const ::testing::TestInfo& test_info) override {
#ifdef __ANDROID__
diff --git a/init/parser.cpp b/init/parser.cpp
index 0a388db..adb41ad 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -141,19 +141,19 @@
return true;
}
-bool Parser::ParseConfigFile(const std::string& path) {
+Result<void> Parser::ParseConfigFile(const std::string& path) {
LOG(INFO) << "Parsing file " << path << "...";
android::base::Timer t;
auto config_contents = ReadFile(path);
if (!config_contents.ok()) {
- LOG(INFO) << "Unable to read config file '" << path << "': " << config_contents.error();
- return false;
+ return Error() << "Unable to read config file '" << path
+ << "': " << config_contents.error();
}
ParseData(path, &config_contents.value());
LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
- return true;
+ return {};
}
bool Parser::ParseConfigDir(const std::string& path) {
@@ -176,8 +176,8 @@
// Sort first so we load files in a consistent order (bug 31996208)
std::sort(files.begin(), files.end());
for (const auto& file : files) {
- if (!ParseConfigFile(file)) {
- LOG(ERROR) << "could not import file '" << file << "'";
+ if (auto result = ParseConfigFile(file); !result.ok()) {
+ LOG(ERROR) << "could not import file '" << file << "': " << result.error();
}
}
return true;
@@ -187,7 +187,11 @@
if (is_dir(path.c_str())) {
return ParseConfigDir(path);
}
- return ParseConfigFile(path);
+ auto result = ParseConfigFile(path);
+ if (!result.ok()) {
+ LOG(INFO) << result.error();
+ }
+ return result.ok();
}
} // namespace init
diff --git a/init/parser.h b/init/parser.h
index 95b0cd7..980ae0c 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -72,7 +72,7 @@
Parser();
bool ParseConfig(const std::string& path);
- bool ParseConfigFile(const std::string& path);
+ Result<void> ParseConfigFile(const std::string& path);
void AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser);
void AddSingleLineParser(const std::string& prefix, LineCallback callback);
diff --git a/init/reboot.cpp b/init/reboot.cpp
index a3fc534..27a7876 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -51,6 +51,7 @@
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
#include <fs_mgr.h>
+#include <libsnapshot/snapshot.h>
#include <logwrap/logwrap.h>
#include <private/android_filesystem_config.h>
#include <selinux/selinux.h>
@@ -422,11 +423,31 @@
if (run_fsck && !FindPartitionsToUmount(&block_devices, &emulated_devices, false)) {
return UMOUNT_STAT_ERROR;
}
-
+ auto sm = snapshot::SnapshotManager::New();
+ bool ota_update_in_progress = false;
+ if (sm->IsUserspaceSnapshotUpdateInProgress()) {
+ LOG(INFO) << "OTA update in progress";
+ ota_update_in_progress = true;
+ }
UmountStat stat = UmountPartitions(timeout - t.duration());
if (stat != UMOUNT_STAT_SUCCESS) {
LOG(INFO) << "umount timeout, last resort, kill all and try";
if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo();
+ // Since umount timedout, we will try to kill all processes
+ // and do one more attempt to umount the partitions.
+ //
+ // However, if OTA update is in progress, we don't want
+ // to kill the snapuserd daemon as the daemon will
+ // be serving I/O requests. Killing the daemon will
+ // end up with I/O failures. If the update is in progress,
+ // we will just return the umount failure status immediately.
+ // This is ok, given the fact that killing the processes
+ // and doing an umount is just a last effort. We are
+ // still not doing fsck when all processes are killed.
+ //
+ if (ota_update_in_progress) {
+ return stat;
+ }
KillAllProcesses();
// even if it succeeds, still it is timeout and do not run fsck with all processes killed
UmountStat st = UmountPartitions(0ms);
diff --git a/init/service.cpp b/init/service.cpp
index b9b3309..87d9c3a 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -26,6 +26,7 @@
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>
+#include <thread>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -887,6 +888,10 @@
}
if (pid_) {
+ if (flags_ & SVC_GENTLE_KILL) {
+ KillProcessGroup(SIGTERM);
+ if (!process_cgroup_empty()) std::this_thread::sleep_for(200ms);
+ }
KillProcessGroup(SIGKILL);
NotifyStateChange("stopping");
} else {
diff --git a/init/service.h b/init/service.h
index f9749d2..3ef8902 100644
--- a/init/service.h
+++ b/init/service.h
@@ -56,6 +56,8 @@
// should not be killed during shutdown
#define SVC_TEMPORARY 0x1000 // This service was started by 'exec' and should be removed from the
// service list once it is reaped.
+#define SVC_GENTLE_KILL 0x2000 // This service should be stopped with SIGTERM instead of SIGKILL
+ // Will still be SIGKILLed after timeout period of 200 ms
#define NR_SVC_SUPP_GIDS 12 // twelve supplementary groups
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 24a2024..3563084 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -151,6 +151,11 @@
return {};
}
+Result<void> ServiceParser::ParseGentleKill(std::vector<std::string>&& args) {
+ service_->flags_ |= SVC_GENTLE_KILL;
+ return {};
+}
+
Result<void> ServiceParser::ParseGroup(std::vector<std::string>&& args) {
auto gid = DecodeUid(args[1]);
if (!gid.ok()) {
@@ -584,6 +589,7 @@
{"disabled", {0, 0, &ServiceParser::ParseDisabled}},
{"enter_namespace", {2, 2, &ServiceParser::ParseEnterNamespace}},
{"file", {2, 2, &ServiceParser::ParseFile}},
+ {"gentle_kill", {0, 0, &ServiceParser::ParseGentleKill}},
{"group", {1, NR_SVC_SUPP_GIDS + 1, &ServiceParser::ParseGroup}},
{"interface", {2, 2, &ServiceParser::ParseInterface}},
{"ioprio", {2, 2, &ServiceParser::ParseIoprio}},
diff --git a/init/service_parser.h b/init/service_parser.h
index 54503dd..670a5c6 100644
--- a/init/service_parser.h
+++ b/init/service_parser.h
@@ -53,6 +53,7 @@
Result<void> ParseDisabled(std::vector<std::string>&& args);
Result<void> ParseEnterNamespace(std::vector<std::string>&& args);
Result<void> ParseGroup(std::vector<std::string>&& args);
+ Result<void> ParseGentleKill(std::vector<std::string>&& args);
Result<void> ParsePriority(std::vector<std::string>&& args);
Result<void> ParseInterface(std::vector<std::string>&& args);
Result<void> ParseIoprio(std::vector<std::string>&& args);
diff --git a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
index 3188337..6728cc6 100644
--- a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
+++ b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
@@ -60,6 +60,10 @@
if (prctl(PR_SET_TAGGED_ADDR_CTRL, res & ~PR_MTE_TCF_SYNC, 0, 0, 0) == -1) abort();
}
std::unique_ptr<volatile char[]> f(new char[1]);
+ // This out-of-bounds is on purpose: we are testing MTE, which is designed to turn
+ // out-of-bound errors into segfaults.
+ // This binary gets run by src/com/android/tests/init/MteUpgradeTest.java, which
+ // asserts that it crashes as expected.
f[17] = 'x';
char buf[1];
read(1, buf, 1);
diff --git a/libcutils/include/cutils/qtaguid.h b/libcutils/include/cutils/qtaguid.h
index a5ffb03..8902c2b 100644
--- a/libcutils/include/cutils/qtaguid.h
+++ b/libcutils/include/cutils/qtaguid.h
@@ -33,12 +33,6 @@
*/
extern int qtaguid_untagSocket(int sockfd);
-/*
- * Enable/disable qtaguid functionnality at a lower level.
- * When pacified, the kernel will accept commands but do nothing.
- */
-extern int qtaguid_setPacifier(int on);
-
#ifdef __cplusplus
}
#endif
diff --git a/libdiskconfig/diskconfig.c b/libdiskconfig/diskconfig.c
index c7e1b43..5f34748 100644
--- a/libdiskconfig/diskconfig.c
+++ b/libdiskconfig/diskconfig.c
@@ -398,7 +398,7 @@
case PART_SCHEME_GPT:
/* not supported yet */
default:
- ALOGE("Uknown partition scheme.");
+ ALOGE("Unknown partition scheme.");
break;
}
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 8c00326..468d796 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -49,7 +49,7 @@
static constexpr const char* CGROUP_PROCS_FILE = "/cgroup.procs";
static constexpr const char* CGROUP_TASKS_FILE = "/tasks";
-static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.tasks";
+static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.threads";
uint32_t CgroupController::version() const {
CHECK(HasValue());
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index 4b8fc19..e44d3bf 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -462,7 +462,7 @@
{
"Controller": "blkio",
"Path": "background"
- }
+ }
},
{
"Name": "SetAttribute",
@@ -502,7 +502,7 @@
{
"Controller": "blkio",
"Path": ""
- }
+ }
},
{
"Name": "SetAttribute",
@@ -542,7 +542,7 @@
{
"Controller": "blkio",
"Path": ""
- }
+ }
},
{
"Name": "SetAttribute",
@@ -582,7 +582,7 @@
{
"Controller": "blkio",
"Path": ""
- }
+ }
},
{
"Name": "SetAttribute",
diff --git a/mkbootfs/mkbootfs.c b/mkbootfs/mkbootfs.c
index 05d1940..64e5a8c 100644
--- a/mkbootfs/mkbootfs.c
+++ b/mkbootfs/mkbootfs.c
@@ -1,17 +1,23 @@
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
-#include <ctype.h>
+#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/sysmacros.h>
#include <dirent.h>
#include <stdarg.h>
#include <fcntl.h>
+#include <linux/kdev_t.h>
+
#include <private/android_filesystem_config.h>
#include <private/fs_config.h>
@@ -21,7 +27,6 @@
** an explanation of this file format
** - dotfiles are ignored
** - directories named 'root' are ignored
-** - device notes, pipes, etc are not supported (error)
*/
static void die(const char* why, ...) {
@@ -86,6 +91,10 @@
fs_config(path, is_dir, target_out_path, &s->st_uid, &s->st_gid, &st_mode, &capabilities);
s->st_mode = (typeof(s->st_mode)) st_mode;
}
+
+ if (S_ISREG(s->st_mode) || S_ISDIR(s->st_mode) || S_ISLNK(s->st_mode)) {
+ s->st_rdev = 0;
+ }
}
static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
@@ -115,8 +124,8 @@
datasize,
0, // volmajor
0, // volminor
- 0, // devmajor
- 0, // devminor,
+ major(s->st_rdev),
+ minor(s->st_rdev),
olen + 1,
0,
out,
@@ -267,6 +276,9 @@
size = readlink(in, buf, 1024);
if(size < 0) die("cannot read symlink '%s'", in);
_eject(&s, out, olen, buf, size);
+ } else if(S_ISBLK(s.st_mode) || S_ISCHR(s.st_mode) ||
+ S_ISFIFO(s.st_mode) || S_ISSOCK(s.st_mode)) {
+ _eject(&s, out, olen, NULL, 0);
} else {
die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
}
@@ -327,34 +339,157 @@
fclose(f);
}
+static void devnodes_desc_error(const char* filename, unsigned long line_num,
+ const char* msg)
+{
+ errx(EXIT_FAILURE, "failed to read nodes desc file '%s' line %lu: %s", filename, line_num, msg);
+}
+
+static int append_devnodes_desc_dir(char* path, char* args)
+{
+ struct stat s;
+
+ if (sscanf(args, "%o %d %d", &s.st_mode, &s.st_uid, &s.st_gid) != 3) return -1;
+
+ s.st_mode |= S_IFDIR;
+
+ _eject(&s, path, strlen(path), NULL, 0);
+
+ return 0;
+}
+
+static int append_devnodes_desc_nod(char* path, char* args)
+{
+ int minor, major;
+ struct stat s;
+ char dev;
+
+ if (sscanf(args, "%o %d %d %c %d %d", &s.st_mode, &s.st_uid, &s.st_gid,
+ &dev, &major, &minor) != 6) return -1;
+
+ s.st_rdev = MKDEV(major, minor);
+ switch (dev) {
+ case 'b':
+ s.st_mode |= S_IFBLK;
+ break;
+ case 'c':
+ s.st_mode |= S_IFCHR;
+ break;
+ default:
+ return -1;
+ }
+
+ _eject(&s, path, strlen(path), NULL, 0);
+
+ return 0;
+}
+
+static void append_devnodes_desc(const char* filename)
+{
+ FILE* f = fopen(filename, "re");
+ if (!f) err(EXIT_FAILURE, "failed to open nodes description file '%s'", filename);
+
+ char *line, *args, *type, *path;
+ unsigned long line_num = 0;
+ size_t allocated_len;
+
+ while (getline(&line, &allocated_len, f) != -1) {
+ char* type;
+
+ line_num++;
+
+ if (*line == '#') continue;
+
+ if (!(type = strtok(line, " \t"))) {
+ devnodes_desc_error(filename, line_num, "a type is missing");
+ }
+
+ if (*type == '\n') continue;
+
+ if (!(path = strtok(NULL, " \t"))) {
+ devnodes_desc_error(filename, line_num, "a path is missing");
+ }
+
+ if (!(args = strtok(NULL, "\n"))) {
+ devnodes_desc_error(filename, line_num, "args are missing");
+ }
+
+ if (!strcmp(type, "dir")) {
+ if (append_devnodes_desc_dir(path, args)) {
+ devnodes_desc_error(filename, line_num, "bad arguments for dir");
+ }
+ } else if (!strcmp(type, "nod")) {
+ if (append_devnodes_desc_nod(path, args)) {
+ devnodes_desc_error(filename, line_num, "bad arguments for nod");
+ }
+ } else {
+ devnodes_desc_error(filename, line_num, "type unknown");
+ }
+ }
+
+ free(line);
+ fclose(f);
+}
+
+static const struct option long_options[] = {
+ { "dirname", required_argument, NULL, 'd' },
+ { "file", required_argument, NULL, 'f' },
+ { "help", no_argument, NULL, 'h' },
+ { "nodes", required_argument, NULL, 'n' },
+ { NULL, 0, NULL, 0 },
+};
+
+static void usage(void)
+{
+ fprintf(stderr,
+ "Usage: mkbootfs [-n FILE] [-d DIR|-F FILE] DIR...\n"
+ "\n"
+ "\t-d, --dirname=DIR: fs-config directory\n"
+ "\t-f, --file=FILE: Canned configuration file\n"
+ "\t-h, --help: Print this help\n"
+ "\t-n, --nodes=FILE: Dev nodes description file\n"
+ "\nDev nodes description:\n"
+ "\t[dir|nod] [perms] [uid] [gid] [c|b] [minor] [major]\n"
+ "\tExample:\n"
+ "\t\t# My device nodes\n"
+ "\t\tdir dev 0755 0 0\n"
+ "\t\tnod dev/null 0600 0 0 c 1 5\n"
+ );
+}
int main(int argc, char *argv[])
{
- if (argc == 1) {
- fprintf(stderr,
- "usage: %s [-d TARGET_OUTPUT_PATH] [-f CANNED_CONFIGURATION_PATH] DIRECTORIES...\n",
- argv[0]);
- exit(1);
+ int opt, unused;
+
+ while ((opt = getopt_long(argc, argv, "hd:f:n:", long_options, &unused)) != -1) {
+ switch (opt) {
+ case 'd':
+ target_out_path = argv[optind - 1];
+ break;
+ case 'f':
+ read_canned_config(argv[optind - 1]);
+ break;
+ case 'h':
+ usage();
+ return 0;
+ case 'n':
+ append_devnodes_desc(argv[optind - 1]);
+ break;
+ default:
+ usage();
+ die("Unknown option %s", argv[optind - 1]);
+ }
}
- argc--;
- argv++;
+ int num_dirs = argc - optind;
+ argv += optind;
- if (argc > 1 && strcmp(argv[0], "-d") == 0) {
- target_out_path = argv[1];
- argc -= 2;
- argv += 2;
+ if (num_dirs <= 0) {
+ usage();
+ die("no directories to process?!");
}
- if (argc > 1 && strcmp(argv[0], "-f") == 0) {
- read_canned_config(argv[1]);
- argc -= 2;
- argv += 2;
- }
-
- if(argc == 0) die("no directories to process?!");
-
- while(argc-- > 0){
+ while(num_dirs-- > 0){
char *x = strchr(*argv, '=');
if(x != 0) {
*x++ = 0;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 55be31a..efad37c 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -47,6 +47,9 @@
# Allow up to 32K FDs per process
setrlimit nofile 32768 32768
+ # set RLIMIT_MEMLOCK to 64KB
+ setrlimit memlock 65536 65536
+
# Set up linker config subdirectories based on mount namespaces
mkdir /linkerconfig/bootstrap 0755
mkdir /linkerconfig/default 0755
@@ -490,18 +493,26 @@
service boringssl_self_test32 /system/bin/boringssl_self_test32
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
+ # Explicitly specify that boringssl_self_test32 doesn't require any capabilities
+ capabilities
service boringssl_self_test64 /system/bin/boringssl_self_test64
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
+ # Explicitly specify that boringssl_self_test64 doesn't require any capabilities
+ capabilities
service boringssl_self_test_apex32 /apex/com.android.conscrypt/bin/boringssl_self_test32
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
+ # Explicitly specify that boringssl_self_test_apex32 doesn't require any capabilities
+ capabilities
service boringssl_self_test_apex64 /apex/com.android.conscrypt/bin/boringssl_self_test64
reboot_on_failure reboot,boringssl-self-check-failed
stdio_to_kmsg
+ # Explicitly specify that boringssl_self_test_apex64 doesn't require any capabilities
+ capabilities
# Healthd can trigger a full boot from charger mode by signaling this
@@ -839,7 +850,7 @@
# Delete any stale files owned by the old virtualizationservice uid (b/230056726).
chmod 0770 /data/misc/virtualizationservice
exec - virtualizationservice system -- /bin/rm -rf /data/misc/virtualizationservice
- mkdir /data/misc/virtualizationservice 0770 system system
+ mkdir /data/misc/virtualizationservice 0771 system system
# /data/preloads uses encryption=None because it only contains preloaded
# files that are public information, similar to the system image.
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index 63b09c0..2f0ec8a 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -7,6 +7,9 @@
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on
+ # NOTE: If the wakelock name here is changed, then also
+ # update it in SystemSuspend.cpp
+ onrestart write /sys/power/wake_lock zygote_kwl
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index b6ca5c0..74a64c8 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -7,6 +7,9 @@
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on
+ # NOTE: If the wakelock name here is changed, then also
+ # update it in SystemSuspend.cpp
+ onrestart write /sys/power/wake_lock zygote_kwl
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
diff --git a/trusty/trusty-base.mk b/trusty/trusty-base.mk
index 0609709..7b4aa26 100644
--- a/trusty/trusty-base.mk
+++ b/trusty/trusty-base.mk
@@ -22,8 +22,21 @@
# For gatekeeper, we include the generic -service and -impl to use legacy
# HAL loading of gatekeeper.trusty.
+# Allow the KeyMint HAL service implementation to be selected at build time. This needs to be
+# done in sync with the TA implementation included in Trusty. Possible values are:
+#
+# - Rust implementation: export TRUSTY_KEYMINT_IMPL=rust
+# - C++ implementation: (any other value of TRUSTY_KEYMINT_IMPL)
+
+ifeq ($(TRUSTY_KEYMINT_IMPL),rust)
+ LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.rust.trusty
+else
+ # Default to the C++ implementation
+ LOCAL_KEYMINT_PRODUCT_PACKAGE := android.hardware.security.keymint-service.trusty
+endif
+
PRODUCT_PACKAGES += \
- android.hardware.security.keymint-service.trusty \
+ $(LOCAL_KEYMINT_PRODUCT_PACKAGE) \
android.hardware.gatekeeper@1.0-service.trusty \
trusty_apploader \
RemoteProvisioner