Merge "mini-keyctl: fix key id parsing by "0x" prefix"
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp index e9d9c63..3c8f393 100644 --- a/adb/daemon/shell_service.cpp +++ b/adb/daemon/shell_service.cpp
@@ -406,11 +406,16 @@ strerror(errno)); return false; } - // Raw subprocess + shell protocol allows for splitting stderr. - if (!CreateSocketpair(&stderr_sfd_, &child_stderr_sfd)) { - *error = android::base::StringPrintf("failed to create socketpair for stderr: %s", - strerror(errno)); - return false; + if (protocol_ == SubprocessProtocol::kShell) { + // Shell protocol allows for splitting stderr. + if (!CreateSocketpair(&stderr_sfd_, &child_stderr_sfd)) { + *error = android::base::StringPrintf("failed to create socketpair for stderr: %s", + strerror(errno)); + return false; + } + } else { + // Raw protocol doesn't support multiple output streams, so combine stdout and stderr. + child_stderr_sfd.reset(dup(child_stdinout_sfd)); } D("execinprocess: stdin/stdout FD = %d, stderr FD = %d", stdinout_sfd_.get(),
diff --git a/adb/daemon/shell_service_test.cpp b/adb/daemon/shell_service_test.cpp index 323bcec..dc79d12 100644 --- a/adb/daemon/shell_service_test.cpp +++ b/adb/daemon/shell_service_test.cpp
@@ -35,7 +35,6 @@ static void SetUpTestCase() { // This is normally done in main.cpp. saved_sigpipe_handler_ = signal(SIGPIPE, SIG_IGN); - } static void TearDownTestCase() { @@ -49,26 +48,32 @@ SubprocessProtocol protocol); void CleanupTestSubprocess(); - virtual void TearDown() override { - void CleanupTestSubprocess(); - } + void StartTestCommandInProcess(std::string name, Command command, SubprocessProtocol protocol); + + virtual void TearDown() override { CleanupTestSubprocess(); } static sighandler_t saved_sigpipe_handler_; - unique_fd subprocess_fd_; + unique_fd command_fd_; }; sighandler_t ShellServiceTest::saved_sigpipe_handler_ = nullptr; void ShellServiceTest::StartTestSubprocess( const char* command, SubprocessType type, SubprocessProtocol protocol) { - subprocess_fd_ = StartSubprocess(command, nullptr, type, protocol); - ASSERT_TRUE(subprocess_fd_ >= 0); + command_fd_ = StartSubprocess(command, nullptr, type, protocol); + ASSERT_TRUE(command_fd_ >= 0); } void ShellServiceTest::CleanupTestSubprocess() { } +void ShellServiceTest::StartTestCommandInProcess(std::string name, Command command, + SubprocessProtocol protocol) { + command_fd_ = StartCommandInProcess(std::move(name), std::move(command), protocol); + ASSERT_TRUE(command_fd_ >= 0); +} + namespace { // Reads raw data from |fd| until it closes or errors. @@ -93,7 +98,7 @@ stdout->clear(); stderr->clear(); - ShellProtocol* protocol = new ShellProtocol(fd); + auto protocol = std::make_unique<ShellProtocol>(fd); while (protocol->Read()) { switch (protocol->id()) { case ShellProtocol::kIdStdout: @@ -111,7 +116,6 @@ ADD_FAILURE() << "Unidentified packet ID: " << protocol->id(); } } - delete protocol; return exit_code; } @@ -154,7 +158,7 @@ // [ -t 0 ] == 0 means we have a terminal (PTY). Even when requesting a raw subprocess, without // the shell protocol we should always force a PTY to ensure proper cleanup. - ExpectLinesEqual(ReadRaw(subprocess_fd_), {"foo", "bar", "0"}); + ExpectLinesEqual(ReadRaw(command_fd_), {"foo", "bar", "0"}); } // Tests a PTY subprocess with no protocol. @@ -165,7 +169,7 @@ SubprocessType::kPty, SubprocessProtocol::kNone)); // [ -t 0 ] == 0 means we have a terminal (PTY). - ExpectLinesEqual(ReadRaw(subprocess_fd_), {"foo", "bar", "0"}); + ExpectLinesEqual(ReadRaw(command_fd_), {"foo", "bar", "0"}); } // Tests a raw subprocess with the shell protocol. @@ -175,7 +179,7 @@ SubprocessType::kRaw, SubprocessProtocol::kShell)); std::string stdout, stderr; - EXPECT_EQ(24, ReadShellProtocol(subprocess_fd_, &stdout, &stderr)); + EXPECT_EQ(24, ReadShellProtocol(command_fd_, &stdout, &stderr)); ExpectLinesEqual(stdout, {"foo", "baz"}); ExpectLinesEqual(stderr, {"bar"}); } @@ -189,7 +193,7 @@ // PTY always combines stdout and stderr but the shell protocol should // still give us an exit code. std::string stdout, stderr; - EXPECT_EQ(50, ReadShellProtocol(subprocess_fd_, &stdout, &stderr)); + EXPECT_EQ(50, ReadShellProtocol(command_fd_, &stdout, &stderr)); ExpectLinesEqual(stdout, {"foo", "bar", "baz"}); ExpectLinesEqual(stderr, {}); } @@ -204,7 +208,7 @@ "echo --${TEST_STR}--", "exit"}; - ShellProtocol* protocol = new ShellProtocol(subprocess_fd_); + ShellProtocol* protocol = new ShellProtocol(command_fd_); for (std::string command : commands) { // Interactive shell requires a newline to complete each command. command.push_back('\n'); @@ -214,7 +218,7 @@ delete protocol; std::string stdout, stderr; - EXPECT_EQ(0, ReadShellProtocol(subprocess_fd_, &stdout, &stderr)); + EXPECT_EQ(0, ReadShellProtocol(command_fd_, &stdout, &stderr)); // An unpredictable command prompt makes parsing exact output difficult but // it should at least contain echoed input and the expected output. for (const char* command : commands) { @@ -230,14 +234,14 @@ SubprocessType::kRaw, SubprocessProtocol::kShell)); std::string input = "foo\nbar"; - ShellProtocol* protocol = new ShellProtocol(subprocess_fd_); + ShellProtocol* protocol = new ShellProtocol(command_fd_); memcpy(protocol->data(), input.data(), input.length()); ASSERT_TRUE(protocol->Write(ShellProtocol::kIdStdin, input.length())); ASSERT_TRUE(protocol->Write(ShellProtocol::kIdCloseStdin, 0)); delete protocol; std::string stdout, stderr; - EXPECT_EQ(0, ReadShellProtocol(subprocess_fd_, &stdout, &stderr)); + EXPECT_EQ(0, ReadShellProtocol(command_fd_, &stdout, &stderr)); ExpectLinesEqual(stdout, {"foo", "barTEST_DONE"}); ExpectLinesEqual(stderr, {}); } @@ -249,7 +253,7 @@ SubprocessType::kRaw, SubprocessProtocol::kShell)); std::string stdout, stderr; - EXPECT_EQ(0, ReadShellProtocol(subprocess_fd_, &stdout, &stderr)); + EXPECT_EQ(0, ReadShellProtocol(command_fd_, &stdout, &stderr)); ExpectLinesEqual(stdout, {}); ExpectLinesEqual(stderr, {"bar"}); } @@ -261,7 +265,56 @@ SubprocessType::kRaw, SubprocessProtocol::kShell)); std::string stdout, stderr; - EXPECT_EQ(0, ReadShellProtocol(subprocess_fd_, &stdout, &stderr)); + EXPECT_EQ(0, ReadShellProtocol(command_fd_, &stdout, &stderr)); ExpectLinesEqual(stdout, {"foo"}); ExpectLinesEqual(stderr, {}); } + +// Tests an inprocess command with no protocol. +TEST_F(ShellServiceTest, RawNoProtocolInprocess) { + ASSERT_NO_FATAL_FAILURE( + StartTestCommandInProcess("123", + [](auto args, auto in, auto out, auto err) -> int { + EXPECT_EQ("123", args); + char input[10]; + EXPECT_TRUE(ReadFdExactly(in, input, 2)); + input[2] = 0; + EXPECT_STREQ("in", input); + WriteFdExactly(out, "out\n"); + WriteFdExactly(err, "err\n"); + return 0; + }, + SubprocessProtocol::kNone)); + + WriteFdExactly(command_fd_, "in"); + ExpectLinesEqual(ReadRaw(command_fd_), {"out", "err"}); +} + +// Tests an inprocess command with the shell protocol. +TEST_F(ShellServiceTest, RawShellProtocolInprocess) { + ASSERT_NO_FATAL_FAILURE( + StartTestCommandInProcess("321", + [](auto args, auto in, auto out, auto err) -> int { + EXPECT_EQ("321", args); + char input[10]; + EXPECT_TRUE(ReadFdExactly(in, input, 2)); + input[2] = 0; + EXPECT_STREQ("in", input); + WriteFdExactly(out, "out\n"); + WriteFdExactly(err, "err\n"); + return 0; + }, + SubprocessProtocol::kShell)); + + { + auto write_protocol = std::make_unique<ShellProtocol>(command_fd_); + memcpy(write_protocol->data(), "in", 2); + write_protocol->Write(ShellProtocol::kIdStdin, 2); + } + + std::string stdout, stderr; + // For in-process commands the exit code is always the default (1). + EXPECT_EQ(1, ReadShellProtocol(command_fd_, &stdout, &stderr)); + ExpectLinesEqual(stdout, {"out"}); + ExpectLinesEqual(stderr, {"err"}); +}
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp index f0bdfbf..3041664 100644 --- a/debuggerd/crasher/crasher.cpp +++ b/debuggerd/crasher/crasher.cpp
@@ -193,6 +193,7 @@ fprintf(stderr, " kuser_memory_barrier call kuser_memory_barrier\n"); fprintf(stderr, " kuser_cmpxchg64 call kuser_cmpxchg64\n"); #endif + fprintf(stderr, " xom read execute-only memory\n"); fprintf(stderr, "\n"); fprintf(stderr, " LOG_ALWAYS_FATAL call liblog LOG_ALWAYS_FATAL\n"); fprintf(stderr, " LOG_ALWAYS_FATAL_IF call liblog LOG_ALWAYS_FATAL_IF\n"); @@ -314,6 +315,11 @@ } else if (!strcasecmp(arg, "seccomp")) { set_system_seccomp_filter(); syscall(99999); +#if defined(__LP64__) + } else if (!strcasecmp(arg, "xom")) { + // Try to read part of our code, which will fail if XOM is active. + printf("*%lx = %lx\n", reinterpret_cast<long>(usage), *reinterpret_cast<long*>(usage)); +#endif #if defined(__arm__) } else if (!strcasecmp(arg, "kuser_helper_version")) { return __kuser_helper_version;
diff --git a/fastboot/fuzzy_fastboot/fixtures.cpp b/fastboot/fuzzy_fastboot/fixtures.cpp index c23da01..bc13a8c 100644 --- a/fastboot/fuzzy_fastboot/fixtures.cpp +++ b/fastboot/fuzzy_fastboot/fixtures.cpp
@@ -59,7 +59,7 @@ namespace fastboot { -int FastBootTest::MatchFastboot(usb_ifc_info* info, const char* local_serial) { +int FastBootTest::MatchFastboot(usb_ifc_info* info, const std::string& local_serial) { if (info->ifc_class != 0xff || info->ifc_subclass != 0x42 || info->ifc_protocol != 0x03) { return -1; } @@ -68,8 +68,8 @@ // require matching serial number or device path if requested // at the command line with the -s option. - if (local_serial && (strcmp(local_serial, info->serial_number) != 0 && - strcmp(local_serial, info->device_path) != 0)) + if (!local_serial.empty() && local_serial != info->serial_number && + local_serial != info->device_path) return -1; return 0; } @@ -113,7 +113,9 @@ ASSERT_TRUE(UsbStillAvailible()); // The device disconnected } - const auto matcher = [](usb_ifc_info* info) -> int { return MatchFastboot(info, nullptr); }; + const auto matcher = [](usb_ifc_info* info) -> int { + return MatchFastboot(info, device_serial); + }; for (int i = 0; i < MAX_USB_TRIES && !transport; i++) { std::unique_ptr<UsbTransport> usb(usb_open(matcher, USB_TIMEOUT)); if (usb) @@ -172,7 +174,9 @@ ; printf("WAITING FOR DEVICE\n"); // Need to wait for device - const auto matcher = [](usb_ifc_info* info) -> int { return MatchFastboot(info, nullptr); }; + const auto matcher = [](usb_ifc_info* info) -> int { + return MatchFastboot(info, device_serial); + }; while (!transport) { std::unique_ptr<UsbTransport> usb(usb_open(matcher, USB_TIMEOUT)); if (usb) { @@ -238,6 +242,7 @@ std::string FastBootTest::cb_scratch = ""; std::string FastBootTest::initial_slot = ""; int FastBootTest::serial_port = 0; +std::string FastBootTest::device_serial = ""; template <bool UNLOCKED> void ModeTest<UNLOCKED>::SetUp() {
diff --git a/fastboot/fuzzy_fastboot/fixtures.h b/fastboot/fuzzy_fastboot/fixtures.h index 7c8d54d..c71c897 100644 --- a/fastboot/fuzzy_fastboot/fixtures.h +++ b/fastboot/fuzzy_fastboot/fixtures.h
@@ -43,9 +43,10 @@ class FastBootTest : public testing::Test { public: static int serial_port; + static std::string device_serial; static constexpr int MAX_USB_TRIES = 10; - static int MatchFastboot(usb_ifc_info* info, const char* local_serial = nullptr); + static int MatchFastboot(usb_ifc_info* info, const std::string& local_serial = ""); bool UsbStillAvailible(); bool UserSpaceFastboot(); void ReconnectFastbootDevice();
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp index a40bc27..ff918a7 100644 --- a/fastboot/fuzzy_fastboot/main.cpp +++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -162,7 +162,7 @@ // Test that USB even works TEST(USBFunctionality, USBConnect) { const auto matcher = [](usb_ifc_info* info) -> int { - return FastBootTest::MatchFastboot(info, nullptr); + return FastBootTest::MatchFastboot(info, fastboot::FastBootTest::device_serial); }; Transport* transport = nullptr; for (int i = 0; i < FastBootTest::MAX_USB_TRIES && !transport; i++) { @@ -1738,10 +1738,14 @@ fastboot::GenerateXmlTests(fastboot::config); } + if (args.find("serial") != args.end()) { + fastboot::FastBootTest::device_serial = args.at("serial"); + } + setbuf(stdout, NULL); // no buffering printf("<Waiting for Device>\n"); const auto matcher = [](usb_ifc_info* info) -> int { - return fastboot::FastBootTest::MatchFastboot(info, nullptr); + return fastboot::FastBootTest::MatchFastboot(info, fastboot::FastBootTest::device_serial); }; Transport* transport = nullptr; while (!transport) {
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index dea4844..8984752 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -159,6 +159,9 @@ auto save_errno = errno; errno = 0; auto has_shared_blocks = fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device); + if (!has_shared_blocks && (entry->mount_point == "/system")) { + has_shared_blocks = fs_mgr_has_shared_blocks("/", entry->blk_device); + } // special case for first stage init for system as root (taimen) if (!has_shared_blocks && (errno == ENOENT) && (entry->blk_device == "/dev/root")) { has_shared_blocks = true; @@ -612,7 +615,9 @@ if (!dm.GetDmDevicePathByName(partition_name, &path)) { // non-DAP A/B device? if (fs_mgr_access(super_device)) return ""; - path = kPhysicalDevice + "system" + (slot_number ? "_a" : "_b"); + auto other_slot = fs_mgr_get_other_slot_suffix(); + if (other_slot.empty()) return ""; + path = kPhysicalDevice + "system" + other_slot; } } return scratch_device_cache = path; @@ -715,7 +720,7 @@ } if (changed || partition_create) { - if (!CreateLogicalPartition(super_device, slot_number, partition_name, true, 0s, + if (!CreateLogicalPartition(super_device, slot_number, partition_name, true, 10s, scratch_device)) return false; @@ -940,7 +945,7 @@ auto slot_number = fs_mgr_overlayfs_slot_number(); auto super_device = fs_mgr_overlayfs_super_device(slot_number); const auto partition_name = android::base::Basename(kScratchMountPoint); - CreateLogicalPartition(super_device, slot_number, partition_name, true, 0s, + CreateLogicalPartition(super_device, slot_number, partition_name, true, 10s, &scratch_device); } mount_scratch = fs_mgr_overlayfs_mount_scratch(scratch_device,
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp index 093d44d..cbe2008 100644 --- a/fs_mgr/fs_mgr_remount.cpp +++ b/fs_mgr/fs_mgr_remount.cpp
@@ -371,17 +371,13 @@ continue; } } - PLOG(WARNING) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point; - // If errno = EROFS at this point, we are dealing with r/o + PLOG(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point; + // If errno is EROFS at this point, we are dealing with r/o // filesystem types like squashfs, erofs or ext4 dedupe. We will // consider such a device that does not have CONFIG_OVERLAY_FS - // in the kernel as a misconfigured; except for ext4 dedupe. - if ((errno == EROFS) && can_reboot) { - const std::vector<std::string> msg = {"--fsck_unshare_blocks"}; - std::string err; - if (write_bootloader_message(msg, &err)) reboot(true); - LOG(ERROR) << "Failed to set bootloader message: " << err; - errno = EROFS; + // in the kernel as a misconfigured. + if (errno == EROFS) { + LOG(ERROR) << "Consider providing all the dependencies to enable overlayfs"; } retval = REMOUNT_FAILED; }
diff --git a/fs_mgr/libfiemap_writer/Android.mk b/fs_mgr/libfiemap_writer/Android.mk new file mode 100644 index 0000000..3c07b8e --- /dev/null +++ b/fs_mgr/libfiemap_writer/Android.mk
@@ -0,0 +1,22 @@ +# +# Copyright (C) 2019 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := VtsFiemapWriterTest +-include test/vts/tools/build/Android.host_config.mk
diff --git a/fs_mgr/libfiemap_writer/AndroidTest.xml b/fs_mgr/libfiemap_writer/AndroidTest.xml new file mode 100644 index 0000000..08cff0e --- /dev/null +++ b/fs_mgr/libfiemap_writer/AndroidTest.xml
@@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Config for VTS VtsFiemapWriterTest"> + <option name="config-descriptor:metadata" key="plan" value="vts-kernel" /> + <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher"> + <option name="abort-on-push-failure" value="false"/> + <option name="push-group" value="HostDrivenTest.push"/> + </target_preparer> + <test class="com.android.tradefed.testtype.VtsMultiDeviceTest"> + <option name="test-module-name" value="VtsFiemapWriterTest"/> + <option name="binary-test-source" value="_32bit::DATA/nativetest/fiemap_writer_test/fiemap_writer_test" /> + <option name="binary-test-source" value="_64bit::DATA/nativetest64/fiemap_writer_test/fiemap_writer_test" /> + <option name="binary-test-type" value="gtest"/> + <option name="test-timeout" value="1m"/> + </test> +</configuration>
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp b/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp index ca51689..dda7dfd 100644 --- a/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp +++ b/fs_mgr/libfiemap_writer/fiemap_writer_test.cpp
@@ -498,17 +498,22 @@ int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); - if (argc <= 1) { - cerr << "Usage: <test_dir> [file_size]\n"; + if (argc > 1 && argv[1] == "-h"s) { + cerr << "Usage: [test_dir] [file_size]\n"; cerr << "\n"; cerr << "Note: test_dir must be a writable, unencrypted directory.\n"; exit(EXIT_FAILURE); } ::android::base::InitLogging(argv, ::android::base::StderrLogger); - std::string tempdir = argv[1] + "/XXXXXX"s; + std::string root_dir = "/data/local/unencrypted"; + if (access(root_dir.c_str(), F_OK)) { + root_dir = "/data"; + } + + std::string tempdir = root_dir + "/XXXXXX"s; if (!mkdtemp(tempdir.data())) { - cerr << "unable to create tempdir on " << argv[1] << "\n"; + cerr << "unable to create tempdir on " << root_dir << "\n"; exit(EXIT_FAILURE); } if (!android::base::Realpath(tempdir, &gTestDir)) {
diff --git a/fs_mgr/libfs_avb/avb_ops.cpp b/fs_mgr/libfs_avb/avb_ops.cpp index 6a3e2c0..c192bf5 100644 --- a/fs_mgr/libfs_avb/avb_ops.cpp +++ b/fs_mgr/libfs_avb/avb_ops.cpp
@@ -36,6 +36,7 @@ #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <libavb/libavb.h> +#include <libdm/dm.h> #include <utils/Compat.h> #include "util.h" @@ -104,6 +105,20 @@ return AVB_IO_RESULT_OK; } +// Converts a partition name (with ab_suffix) to the corresponding mount point. +// e.g., "system_a" => "/system", +// e.g., "vendor_a" => "/vendor", +static std::string DeriveMountPoint(const std::string& partition_name) { + const std::string ab_suffix = fs_mgr_get_slot_suffix(); + std::string mount_point(partition_name); + auto found = partition_name.rfind(ab_suffix); + if (found != std::string::npos) { + mount_point.erase(found); // converts system_a => system + } + + return "/" + mount_point; +} + FsManagerAvbOps::FsManagerAvbOps() { // We only need to provide the implementation of read_from_partition() // operation since that's all what is being used by the avb_slot_verify(). @@ -122,14 +137,53 @@ avb_ops_.user_data = this; } +// Given a partition name (with ab_suffix), e.g., system_a, returns the corresponding +// dm-linear path for it. e.g., /dev/block/dm-0. If not found, returns an empty string. +// This assumes that the prefix of the partition name and the mount point are the same. +// e.g., partition vendor_a is mounted under /vendor, product_a is mounted under /product, etc. +// This might not be true for some special fstab files, e.g., fstab.postinstall. +// But it's good enough for the default fstab. Also note that the logical path is a +// fallback solution when the physical path (/dev/block/by-name/<partition>) cannot be found. +std::string FsManagerAvbOps::GetLogicalPath(const std::string& partition_name) { + if (fstab_.empty() && !ReadDefaultFstab(&fstab_)) { + return ""; + } + + const auto mount_point = DeriveMountPoint(partition_name); + if (mount_point.empty()) return ""; + + auto fstab_entry = GetEntryForMountPoint(&fstab_, mount_point); + if (!fstab_entry) return ""; + + std::string device_path; + if (fstab_entry->fs_mgr_flags.logical) { + dm::DeviceMapper& dm = dm::DeviceMapper::Instance(); + if (!dm.GetDmDevicePathByName(fstab_entry->blk_device, &device_path)) { + LERROR << "Failed to resolve logical device path for: " << fstab_entry->blk_device; + return ""; + } + return device_path; + } + + return ""; +} + AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset, size_t num_bytes, void* buffer, size_t* out_num_read) { - const std::string path = "/dev/block/by-name/"s + partition; + std::string path = "/dev/block/by-name/"s + partition; // Ensures the device path (a symlink created by init) is ready to access. if (!WaitForFile(path, 1s)) { - return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + LERROR << "Device path not found: " << path; + // Falls back to logical path if the physical path is not found. + // This mostly only works for emulator (no bootloader). Because in normal + // device, bootloader is unable to read logical partitions. So if libavb in + // the bootloader failed to read a physical partition, it will failed to boot + // the HLOS and we won't reach the code here. + path = GetLogicalPath(partition); + if (path.empty() || !WaitForFile(path, 1s)) return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + LINFO << "Fallback to use logical device path: " << path; } android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
diff --git a/fs_mgr/libfs_avb/avb_ops.h b/fs_mgr/libfs_avb/avb_ops.h index a849d94..b39812d 100644 --- a/fs_mgr/libfs_avb/avb_ops.h +++ b/fs_mgr/libfs_avb/avb_ops.h
@@ -28,6 +28,7 @@ #include <vector> #include <fs_avb/types.h> +#include <fstab/fstab.h> #include <libavb/libavb.h> namespace android { @@ -60,7 +61,9 @@ std::vector<VBMetaData>* out_vbmeta_images); private: + std::string GetLogicalPath(const std::string& partition_name); AvbOps avb_ops_; + Fstab fstab_; }; } // namespace fs_mgr
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp index 27222af..41c01da 100644 --- a/fs_mgr/liblp/builder.cpp +++ b/fs_mgr/liblp/builder.cpp
@@ -1057,7 +1057,7 @@ if (sABOverrideSet) { return sABOverrideValue; } - return android::base::GetBoolProperty("ro.build.ab_update", false); + return !android::base::GetProperty("ro.boot.slot_suffix", "").empty(); } bool MetadataBuilder::IsRetrofitDevice() const {
diff --git a/fs_mgr/liblp/partition_opener.cpp b/fs_mgr/liblp/partition_opener.cpp index bb8ec9c..3b12213 100644 --- a/fs_mgr/liblp/partition_opener.cpp +++ b/fs_mgr/liblp/partition_opener.cpp
@@ -26,6 +26,7 @@ #include <unistd.h> #include <android-base/file.h> +#include <android-base/strings.h> #include "utility.h" @@ -37,7 +38,7 @@ namespace { std::string GetPartitionAbsolutePath(const std::string& path) { - if (path[0] == '/') { + if (android::base::StartsWith(path, "/")) { return path; } return "/dev/block/by-name/" + path;
diff --git a/init/README.md b/init/README.md index aadf11d..51deb5a 100644 --- a/init/README.md +++ b/init/README.md
@@ -488,7 +488,11 @@ This is included in the default init.rc. `loglevel <level>` -> Sets the kernel log level to level. Properties are expanded within _level_. +> Sets init's log level to the integer level, from 7 (all logging) to 0 + (fatal logging only). The numeric values correspond to the kernel log + levels, but this command does not affect the kernel log level. Use the + `write` command to write to `/proc/sys/kernel/printk` to change that. + Properties are expanded within _level_. `mkdir <path> [mode] [owner] [group]` > Create a directory at _path_, optionally with the given mode, owner, and
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp index d458924..3900f72 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp
@@ -80,7 +80,7 @@ bool InitMappedDevice(const std::string& verity_device); bool InitDeviceMapper(); bool CreateLogicalPartitions(); - bool MountPartition(const Fstab::iterator& begin, bool erase_used_fstab_entry, + bool MountPartition(const Fstab::iterator& begin, bool erase_same_mounts, Fstab::iterator* end = nullptr); bool MountPartitions(); @@ -437,21 +437,26 @@ uevent_listener_.RegenerateUeventsForPath(syspath, verity_callback); if (!found) { - LOG(INFO) << "dm-verity device not found in /sys, waiting for its uevent"; + LOG(INFO) << "dm device '" << dm_device << "' not found in /sys, waiting for its uevent"; Timer t; uevent_listener_.Poll(verity_callback, 10s); - LOG(INFO) << "wait for dm-verity device returned after " << t; + LOG(INFO) << "wait for dm device '" << dm_device << "' returned after " << t; } if (!found) { - LOG(ERROR) << "dm-verity device not found after polling timeout"; + LOG(ERROR) << "dm device '" << dm_device << "' not found after polling timeout"; return false; } return true; } -bool FirstStageMount::MountPartition(const Fstab::iterator& begin, bool erase_used_fstab_entry, +bool FirstStageMount::MountPartition(const Fstab::iterator& begin, bool erase_same_mounts, Fstab::iterator* end) { + // Sets end to begin + 1, so we can just return on failure below. + if (end) { + *end = begin + 1; + } + if (begin->fs_mgr_flags.logical) { if (!fs_mgr_update_logical_partition(&(*begin))) { return false; @@ -477,7 +482,7 @@ mounted = (fs_mgr_do_mount_one(*current) == 0); } } - if (erase_used_fstab_entry) { + if (erase_same_mounts) { current = fstab_.erase(begin, current); } if (end) { @@ -494,7 +499,7 @@ return entry.mount_point == "/metadata"; }); if (metadata_partition != fstab_.end()) { - if (MountPartition(metadata_partition, true /* erase_used_fstab_entry */)) { + if (MountPartition(metadata_partition, true /* erase_same_mounts */)) { UseGsiIfPresent(); } } @@ -505,7 +510,7 @@ if (system_partition == fstab_.end()) return true; - if (MountPartition(system_partition, false)) { + if (MountPartition(system_partition, false /* erase_same_mounts */)) { if (gsi_not_on_userdata_ && fs_mgr_verity_is_check_at_most_once(*system_partition)) { LOG(ERROR) << "check_most_at_once forbidden on external media"; return false; @@ -560,7 +565,7 @@ } Fstab::iterator end; - if (!MountPartition(current, false, &end)) { + if (!MountPartition(current, false /* erase_same_mounts */, &end)) { if (current->fs_mgr_flags.no_fail) { LOG(INFO) << "Failed to mount " << current->mount_point << ", ignoring mount for no_fail partition"; @@ -797,11 +802,9 @@ bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) { AvbHashtreeResult hashtree_result; - if (fstab_entry->fs_mgr_flags.avb) { - if (!InitAvbHandle()) return false; - hashtree_result = - avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */); - } else if (!fstab_entry->avb_keys.empty()) { + // It's possible for a fstab_entry to have both avb_keys and avb flag. + // In this case, try avb_keys first, then fallback to avb flag. + if (!fstab_entry->avb_keys.empty()) { if (!InitAvbHandle()) return false; // Checks if hashtree should be disabled from the top-level /vbmeta. if (avb_handle_->status() == AvbHandleStatus::kHashtreeDisabled || @@ -813,14 +816,24 @@ auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta(*fstab_entry); if (!avb_standalone_handle) { LOG(ERROR) << "Failed to load offline vbmeta for " << fstab_entry->mount_point; - return false; + // Fallbacks to built-in hashtree if fs_mgr_flags.avb is set. + if (!fstab_entry->fs_mgr_flags.avb) return false; + LOG(INFO) << "Fallback to built-in hashtree for " << fstab_entry->mount_point; + hashtree_result = + avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */); + } else { + // Sets up hashtree via the standalone handle. + if (IsStandaloneImageRollback(*avb_handle_, *avb_standalone_handle, *fstab_entry)) { + return false; + } + hashtree_result = avb_standalone_handle->SetUpAvbHashtree( + fstab_entry, false /* wait_for_verity_dev */); } - if (IsStandaloneImageRollback(*avb_handle_, *avb_standalone_handle, *fstab_entry)) { - return false; - } - hashtree_result = avb_standalone_handle->SetUpAvbHashtree( - fstab_entry, false /* wait_for_verity_dev */); } + } else if (fstab_entry->fs_mgr_flags.avb) { + if (!InitAvbHandle()) return false; + hashtree_result = + avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */); } else { return true; // No need AVB, returns true to mount the partition directly. }
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp index 6bec63c..71980d7 100644 --- a/libbacktrace/Backtrace.cpp +++ b/libbacktrace/Backtrace.cpp
@@ -170,5 +170,7 @@ return "Failed to unwind due to invalid unwind information"; case BACKTRACE_UNWIND_ERROR_REPEATED_FRAME: return "Failed to unwind due to same sp/pc repeating"; + case BACKTRACE_UNWIND_ERROR_INVALID_ELF: + return "Failed to unwind due to invalid elf"; } }
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp index f5f9b2a..36640cd 100644 --- a/libbacktrace/UnwindStack.cpp +++ b/libbacktrace/UnwindStack.cpp
@@ -89,6 +89,10 @@ case unwindstack::ERROR_REPEATED_FRAME: error->error_code = BACKTRACE_UNWIND_ERROR_REPEATED_FRAME; break; + + case unwindstack::ERROR_INVALID_ELF: + error->error_code = BACKTRACE_UNWIND_ERROR_INVALID_ELF; + break; } }
diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h index 10e790b..404e7e8 100644 --- a/libbacktrace/include/backtrace/Backtrace.h +++ b/libbacktrace/include/backtrace/Backtrace.h
@@ -64,6 +64,8 @@ BACKTRACE_UNWIND_ERROR_UNWIND_INFO, // Unwind information stopped due to sp/pc repeating. BACKTRACE_UNWIND_ERROR_REPEATED_FRAME, + // Unwind information stopped due to invalid elf. + BACKTRACE_UNWIND_ERROR_INVALID_ELF, }; struct BacktraceUnwindError {
diff --git a/libmeminfo/tools/procrank.cpp b/libmeminfo/tools/procrank.cpp index 21a684c..5e89254 100644 --- a/libmeminfo/tools/procrank.cpp +++ b/libmeminfo/tools/procrank.cpp
@@ -14,11 +14,17 @@ * limitations under the License. */ +#include <android-base/file.h> +#include <android-base/parseint.h> +#include <android-base/stringprintf.h> +#include <android-base/strings.h> #include <dirent.h> #include <errno.h> #include <inttypes.h> #include <linux/kernel-page-flags.h> #include <linux/oom.h> +#include <meminfo/procmeminfo.h> +#include <meminfo/sysmeminfo.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> @@ -29,14 +35,6 @@ #include <sstream> #include <vector> -#include <android-base/file.h> -#include <android-base/parseint.h> -#include <android-base/stringprintf.h> -#include <android-base/strings.h> - -#include <meminfo/procmeminfo.h> -#include <meminfo/sysmeminfo.h> - using ::android::meminfo::MemUsage; using ::android::meminfo::ProcMemInfo; @@ -460,8 +458,16 @@ auto mark_swap_usage = [&](pid_t pid) -> bool { ProcessRecord proc(pid, show_wss, pgflags, pgflags_mask); if (!proc.valid()) { - std::cerr << "Failed to create process record for: " << pid << std::endl; - return false; + // Check to see if the process is still around, skip the process if the proc + // directory is inaccessible. It was most likely killed while creating the process + // record + std::string procdir = ::android::base::StringPrintf("/proc/%d", pid); + if (access(procdir.c_str(), F_OK | R_OK)) return true; + + // Warn if we failed to gather process stats even while it is still alive. + // Return success here, so we continue to print stats for other processes. + std::cerr << "warning: failed to create process record for: " << pid << std::endl; + return true; } // Skip processes with no memory mappings @@ -479,9 +485,9 @@ return true; }; - // Get a list of all pids currently running in the system in - // 1st pass through all processes. Mark each swap offset used by the process as we find them - // for calculating proportional swap usage later. + // Get a list of all pids currently running in the system in 1st pass through all processes. + // Mark each swap offset used by the process as we find them for calculating proportional + // swap usage later. if (!read_all_pids(&pids, mark_swap_usage)) { std::cerr << "Failed to read all pids from the system" << std::endl; exit(EXIT_FAILURE);
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp index ded5adb..9780606 100644 --- a/libsysutils/src/SocketListener.cpp +++ b/libsysutils/src/SocketListener.cpp
@@ -95,7 +95,7 @@ } else if (!mListen) mClients[mSock] = new SocketClient(mSock, false, mUseCmdNum); - if (pipe(mCtrlPipe)) { + if (pipe2(mCtrlPipe, O_CLOEXEC)) { SLOGE("pipe failed (%s)", strerror(errno)); return -1; }
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp index 4b93abb..3454913 100644 --- a/libunwindstack/Elf.cpp +++ b/libunwindstack/Elf.cpp
@@ -160,7 +160,7 @@ if (valid_) { return interface_->LastErrorCode(); } - return ERROR_NONE; + return ERROR_INVALID_ELF; } uint64_t Elf::GetLastErrorAddress() { @@ -170,22 +170,23 @@ return 0; } +// The relative pc expectd by this function is relative to the start of the elf. +bool Elf::StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory) { + if (!valid_) { + return false; + } + return regs->StepIfSignalHandler(rel_pc, this, process_memory); +} + // The relative pc is always relative to the start of the map from which it comes. -bool Elf::Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory, - bool* finished) { +bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished) { if (!valid_) { return false; } - // The relative pc expectd by StepIfSignalHandler is relative to the start of the elf. - if (regs->StepIfSignalHandler(rel_pc, this, process_memory)) { - *finished = false; - return true; - } - // Lock during the step which can update information in the object. std::lock_guard<std::mutex> guard(lock_); - return interface_->Step(adjusted_rel_pc, regs, process_memory, finished); + return interface_->Step(rel_pc, regs, process_memory, finished); } bool Elf::IsValidElf(Memory* memory) {
diff --git a/libunwindstack/LocalUnwinder.cpp b/libunwindstack/LocalUnwinder.cpp index 5b2fadf..5d81200 100644 --- a/libunwindstack/LocalUnwinder.cpp +++ b/libunwindstack/LocalUnwinder.cpp
@@ -111,6 +111,14 @@ pc_adjustment = 0; } step_pc -= pc_adjustment; + + bool finished = false; + if (elf->StepIfSignalHandler(rel_pc, regs.get(), process_memory_.get())) { + step_pc = rel_pc; + } else if (!elf->Step(step_pc, regs.get(), process_memory_.get(), &finished)) { + finished = true; + } + // Skip any locations that are within this library. if (num_frames != 0 || !ShouldSkipLibrary(map_info->name)) { // Add frame information. @@ -124,22 +132,12 @@ } num_frames++; } - if (!elf->valid()) { - break; - } - if (frame_info->size() == max_frames) { - break; - } + if (finished || frame_info->size() == max_frames || + (cur_pc == regs->pc() && cur_sp == regs->sp())) { + break; + } adjust_pc = true; - bool finished; - if (!elf->Step(rel_pc, step_pc, regs.get(), process_memory_.get(), &finished) || finished) { - break; - } - // pc and sp are the same, terminate the unwind. - if (cur_pc == regs->pc() && cur_sp == regs->sp()) { - break; - } } return num_frames != 0; }
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp index 3f2e1c1..f3d2b5e 100644 --- a/libunwindstack/Unwinder.cpp +++ b/libunwindstack/Unwinder.cpp
@@ -89,8 +89,8 @@ #endif } -void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc, - uint64_t pc_adjustment) { +FrameData* Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, + uint64_t pc_adjustment) { size_t frame_num = frames_.size(); frames_.resize(frame_num + 1); FrameData* frame = &frames_.at(frame_num); @@ -100,7 +100,8 @@ frame->pc = regs_->pc() - pc_adjustment; if (map_info == nullptr) { - return; + // Nothing else to update. + return nullptr; } if (resolve_names_) { @@ -118,12 +119,7 @@ frame->map_end = map_info->end; frame->map_flags = map_info->flags; frame->map_load_bias = elf->GetLoadBias(); - - if (!resolve_names_ || - !elf->GetFunctionName(func_pc, &frame->function_name, &frame->function_offset)) { - frame->function_name = ""; - frame->function_offset = 0; - } + return frame; } static bool ShouldStop(const std::vector<std::string>* map_suffixes_to_ignore, @@ -194,6 +190,7 @@ } } + FrameData* frame = nullptr; if (map_info == nullptr || initial_map_names_to_skip == nullptr || std::find(initial_map_names_to_skip->begin(), initial_map_names_to_skip->end(), basename(map_info->name.c_str())) == initial_map_names_to_skip->end()) { @@ -210,23 +207,21 @@ } } - FillInFrame(map_info, elf, rel_pc, step_pc, pc_adjustment); + frame = FillInFrame(map_info, elf, rel_pc, pc_adjustment); // Once a frame is added, stop skipping frames. initial_map_names_to_skip = nullptr; } adjust_pc = true; - bool stepped; + bool stepped = false; bool in_device_map = false; - if (map_info == nullptr) { - stepped = false; - } else { + bool finished = false; + if (map_info != nullptr) { if (map_info->flags & MAPS_FLAGS_DEVICE_MAP) { // Do not stop here, fall through in case we are // in the speculative unwind path and need to remove // some of the speculative frames. - stepped = false; in_device_map = true; } else { MapInfo* sp_info = maps_->Find(regs_->sp()); @@ -234,19 +229,37 @@ // Do not stop here, fall through in case we are // in the speculative unwind path and need to remove // some of the speculative frames. - stepped = false; in_device_map = true; } else { - bool finished; - stepped = elf->Step(rel_pc, step_pc, regs_, process_memory_.get(), &finished); - elf->GetLastError(&last_error_); - if (stepped && finished) { - break; + if (elf->StepIfSignalHandler(rel_pc, regs_, process_memory_.get())) { + stepped = true; + if (frame != nullptr) { + // Need to adjust the relative pc because the signal handler + // pc should not be adjusted. + frame->rel_pc = rel_pc; + frame->pc += pc_adjustment; + step_pc = rel_pc; + } + } else if (elf->Step(step_pc, regs_, process_memory_.get(), &finished)) { + stepped = true; } + elf->GetLastError(&last_error_); } } } + if (frame != nullptr) { + if (!resolve_names_ || + !elf->GetFunctionName(step_pc, &frame->function_name, &frame->function_offset)) { + frame->function_name = ""; + frame->function_offset = 0; + } + } + + if (finished) { + break; + } + if (!stepped) { if (return_address_attempt) { // Only remove the speculative frame if there are more than two frames
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h index ac94f10..56bf318 100644 --- a/libunwindstack/include/unwindstack/Elf.h +++ b/libunwindstack/include/unwindstack/Elf.h
@@ -67,8 +67,9 @@ uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info); - bool Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory, - bool* finished); + bool StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory); + + bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished); ElfInterface* CreateInterfaceFromMemory(Memory* memory);
diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h index 6ed0e0f..72ec454 100644 --- a/libunwindstack/include/unwindstack/Error.h +++ b/libunwindstack/include/unwindstack/Error.h
@@ -29,6 +29,7 @@ ERROR_INVALID_MAP, // Unwind in an invalid map. ERROR_MAX_FRAMES_EXCEEDED, // The number of frames exceed the total allowed. ERROR_REPEATED_FRAME, // The last frame has the same pc/sp as the next. + ERROR_INVALID_ELF, // Unwind in an invalid elf. }; struct ErrorData {
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h index 8b01654..75be209 100644 --- a/libunwindstack/include/unwindstack/Unwinder.h +++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -118,8 +118,7 @@ Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); } void FillInDexFrame(); - void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc, - uint64_t pc_adjustment); + FrameData* FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t pc_adjustment); size_t max_frames_; Maps* maps_;
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp index 23c9cf8..c432d6d 100644 --- a/libunwindstack/tests/ElfTest.cpp +++ b/libunwindstack/tests/ElfTest.cpp
@@ -132,8 +132,12 @@ uint64_t func_offset; ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset)); + ASSERT_FALSE(elf.StepIfSignalHandler(0, nullptr, nullptr)); + EXPECT_EQ(ERROR_INVALID_ELF, elf.GetLastErrorCode()); + bool finished; - ASSERT_FALSE(elf.Step(0, 0, nullptr, nullptr, &finished)); + ASSERT_FALSE(elf.Step(0, nullptr, nullptr, &finished)); + EXPECT_EQ(ERROR_INVALID_ELF, elf.GetLastErrorCode()); } TEST_F(ElfTest, elf32_invalid_machine) { @@ -295,9 +299,8 @@ } elf.FakeSetValid(true); - bool finished; - ASSERT_TRUE(elf.Step(0x3000, 0x1000, ®s, &process_memory, &finished)); - EXPECT_FALSE(finished); + ASSERT_TRUE(elf.StepIfSignalHandler(0x3000, ®s, &process_memory)); + EXPECT_EQ(ERROR_NONE, elf.GetLastErrorCode()); EXPECT_EQ(15U, regs.pc()); EXPECT_EQ(13U, regs.sp()); } @@ -336,7 +339,7 @@ EXPECT_CALL(*interface, Step(0x1000, ®s, &process_memory, &finished)) .WillOnce(::testing::Return(true)); - ASSERT_TRUE(elf.Step(0x1004, 0x1000, ®s, &process_memory, &finished)); + ASSERT_TRUE(elf.Step(0x1000, ®s, &process_memory, &finished)); } TEST_F(ElfTest, get_global_invalid_elf) {
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp index 02ba9c8..6c64c40 100644 --- a/libunwindstack/tests/UnwindOfflineTest.cpp +++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -1215,7 +1215,7 @@ " #02 pc 0032bff3 libunwindstack_test (SignalOuterFunction+2)\n" " #03 pc 0032fed3 libunwindstack_test " "(unwindstack::SignalCallerHandler(int, siginfo*, void*)+26)\n" - " #04 pc 00026528 libc.so\n" + " #04 pc 0002652c libc.so (__restore)\n" " #05 pc 00000000 <unknown>\n" " #06 pc 0032c2d9 libunwindstack_test (InnerFunction+736)\n" " #07 pc 0032cc4f libunwindstack_test (MiddleFunction+42)\n" @@ -1243,7 +1243,7 @@ EXPECT_EQ(0xf43d2ce8U, unwinder.frames()[2].sp); EXPECT_EQ(0x2e59ed3U, unwinder.frames()[3].pc); EXPECT_EQ(0xf43d2cf0U, unwinder.frames()[3].sp); - EXPECT_EQ(0xf4136528U, unwinder.frames()[4].pc); + EXPECT_EQ(0xf413652cU, unwinder.frames()[4].pc); EXPECT_EQ(0xf43d2d10U, unwinder.frames()[4].sp); EXPECT_EQ(0U, unwinder.frames()[5].pc); EXPECT_EQ(0xffcc0ee0U, unwinder.frames()[5].sp); @@ -1326,7 +1326,7 @@ " #00 pc 000000000014ccbc linker64 (__dl_syscall+28)\n" " #01 pc 000000000005426c linker64 " "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n" - " #02 pc 00000000000008bc vdso.so\n" + " #02 pc 00000000000008c0 vdso.so (__kernel_rt_sigreturn)\n" " #03 pc 00000000000846f4 libc.so (abort+172)\n" " #04 pc 0000000000084ad4 libc.so (__assert2+36)\n" " #05 pc 000000000003d5b4 ANGLEPrebuilt.apk!libfeature_support_angle.so (offset 0x4000) " @@ -1338,7 +1338,7 @@ EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp); EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc); EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[1].sp); - EXPECT_EQ(0x7e82b018bcULL, unwinder.frames()[2].pc); + EXPECT_EQ(0x7e82b018c0ULL, unwinder.frames()[2].pc); EXPECT_EQ(0x7df8ca3da0ULL, unwinder.frames()[2].sp); EXPECT_EQ(0x7e7eecc6f4ULL, unwinder.frames()[3].pc); EXPECT_EQ(0x7dabf3db60ULL, unwinder.frames()[3].sp); @@ -1366,7 +1366,7 @@ " #00 pc 000000000014ccbc linker64 (__dl_syscall+28)\n" " #01 pc 000000000005426c linker64 " "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n" - " #02 pc 00000000000008bc vdso.so\n" + " #02 pc 00000000000008c0 vdso.so (__kernel_rt_sigreturn)\n" " #03 pc 00000000000846f4 libc.so (abort+172)\n" " #04 pc 0000000000084ad4 libc.so (__assert2+36)\n" " #05 pc 000000000003d5b4 ANGLEPrebuilt.apk (offset 0x21d5000)\n" @@ -1377,7 +1377,7 @@ EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp); EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc); EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[1].sp); - EXPECT_EQ(0x7e82b018bcULL, unwinder.frames()[2].pc); + EXPECT_EQ(0x7e82b018c0ULL, unwinder.frames()[2].pc); EXPECT_EQ(0x7df8ca3da0ULL, unwinder.frames()[2].sp); EXPECT_EQ(0x7e7eecc6f4ULL, unwinder.frames()[3].pc); EXPECT_EQ(0x7dabf3db60ULL, unwinder.frames()[3].sp);
diff --git a/libziparchive/unzip.cpp b/libziparchive/unzip.cpp index 6756007..cc059d8 100644 --- a/libziparchive/unzip.cpp +++ b/libziparchive/unzip.cpp
@@ -17,6 +17,7 @@ #include <errno.h> #include <error.h> #include <fcntl.h> +#include <fnmatch.h> #include <getopt.h> #include <inttypes.h> #include <stdio.h> @@ -52,9 +53,21 @@ static uint64_t total_compressed_length = 0; static size_t file_count = 0; -static bool Filter(const std::string& name) { - if (!excludes.empty() && excludes.find(name) != excludes.end()) return true; - if (!includes.empty() && includes.find(name) == includes.end()) return true; +static bool ShouldInclude(const std::string& name) { + // Explicitly excluded? + if (!excludes.empty()) { + for (const auto& exclude : excludes) { + if (!fnmatch(exclude.c_str(), name.c_str(), 0)) return false; + } + } + + // Implicitly included? + if (includes.empty()) return true; + + // Explicitly included? + for (const auto& include : includes) { + if (!fnmatch(include.c_str(), name.c_str(), 0)) return true; + } return false; } @@ -245,7 +258,7 @@ ZipString string; while ((err = Next(cookie, &entry, &string)) >= 0) { std::string name(string.name, string.name + string.name_length); - if (!Filter(name)) ProcessOne(zah, entry, name); + if (ShouldInclude(name)) ProcessOne(zah, entry, name); } if (err < -1) error(1, 0, "failed iterating %s: %s", archive_name, ErrorCodeString(err)); @@ -260,7 +273,8 @@ printf( "\n" - "Extract FILEs from ZIP archive. Default is all files.\n" + "Extract FILEs from ZIP archive. Default is all files. Both the include and\n" + "exclude (-x) lists use shell glob patterns.\n" "\n" "-d DIR Extract into DIR\n" "-l List contents (-lq excludes archive name, -lv is verbose)\n"
diff --git a/logd/Android.bp b/logd/Android.bp index 360f2fe..9b86258 100644 --- a/logd/Android.bp +++ b/logd/Android.bp
@@ -80,6 +80,24 @@ cflags: ["-Werror"], } +cc_binary { + name: "auditctl", + + srcs: ["auditctl.cpp"], + + static_libs: [ + "liblogd", + ], + + shared_libs: ["libbase"], + + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + "-Wconversion" + ], +} prebuilt_etc { name: "logtagd.rc",
diff --git a/logd/auditctl.cpp b/logd/auditctl.cpp new file mode 100644 index 0000000..98bb02d --- /dev/null +++ b/logd/auditctl.cpp
@@ -0,0 +1,74 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <android-base/parseint.h> +#include <error.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include "libaudit.h" + +static void usage(const char* cmdline) { + fprintf(stderr, "Usage: %s [-r rate]\n", cmdline); +} + +static void do_update_rate(uint32_t rate) { + int fd = audit_open(); + if (fd == -1) { + error(EXIT_FAILURE, errno, "Unable to open audit socket"); + } + int result = audit_rate_limit(fd, rate); + close(fd); + if (result < 0) { + fprintf(stderr, "Can't update audit rate limit: %d\n", result); + exit(EXIT_FAILURE); + } +} + +int main(int argc, char* argv[]) { + uint32_t rate = 0; + bool update_rate = false; + int opt; + + while ((opt = getopt(argc, argv, "r:")) != -1) { + switch (opt) { + case 'r': + if (!android::base::ParseUint<uint32_t>(optarg, &rate)) { + error(EXIT_FAILURE, errno, "Invalid Rate"); + } + update_rate = true; + break; + default: /* '?' */ + usage(argv[0]); + exit(EXIT_FAILURE); + } + } + + // In the future, we may add other options to auditctl + // so this if statement will expand. + // if (!update_rate && !update_backlog && !update_whatever) ... + if (!update_rate) { + fprintf(stderr, "Nothing to do\n"); + usage(argv[0]); + exit(EXIT_FAILURE); + } + + if (update_rate) { + do_update_rate(rate); + } + + return 0; +}
diff --git a/logd/libaudit.c b/logd/libaudit.c index 9d9a857..f452c71 100644 --- a/logd/libaudit.c +++ b/logd/libaudit.c
@@ -160,8 +160,7 @@ * and the the mask set to AUDIT_STATUS_PID */ status.pid = pid; - status.mask = AUDIT_STATUS_PID | AUDIT_STATUS_RATE_LIMIT; - status.rate_limit = AUDIT_RATE_LIMIT; /* audit entries per second */ + status.mask = AUDIT_STATUS_PID; /* Let the kernel know this pid will be registering for audit events */ rc = audit_send(fd, AUDIT_SET, &status, sizeof(status)); @@ -188,6 +187,14 @@ return socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_AUDIT); } +int audit_rate_limit(int fd, uint32_t limit) { + struct audit_status status; + memset(&status, 0, sizeof(status)); + status.mask = AUDIT_STATUS_RATE_LIMIT; + status.rate_limit = limit; /* audit entries per second */ + return audit_send(fd, AUDIT_SET, &status, sizeof(status)); +} + int audit_get_reply(int fd, struct audit_message* rep, reply_t block, int peek) { ssize_t len; int flags;
diff --git a/logd/libaudit.h b/logd/libaudit.h index 2a93ea3..b4a92a8 100644 --- a/logd/libaudit.h +++ b/logd/libaudit.h
@@ -89,8 +89,17 @@ */ extern int audit_setup(int fd, pid_t pid); -/* Max audit messages per second */ -#define AUDIT_RATE_LIMIT 5 +/** + * Throttle kernel messages at the provided rate + * @param fd + * The fd returned by a call to audit_open() + * @param rate + * The rate, in messages per second, above which the kernel + * should drop audit messages. + * @return + * This function returns 0 on success, -errno on error. + */ +extern int audit_rate_limit(int fd, uint32_t limit); __END_DECLS
diff --git a/logd/logd.rc b/logd/logd.rc index c740ecf..438419a 100644 --- a/logd/logd.rc +++ b/logd/logd.rc
@@ -16,8 +16,19 @@ group logd writepid /dev/cpuset/system-background/tasks +# Limit SELinux denial generation to 5/second +service logd-auditctl /system/bin/auditctl -r 5 + oneshot + disabled + user logd + group logd + capabilities AUDIT_CONTROL + on fs write /dev/event-log-tags "# content owned by logd " chown logd logd /dev/event-log-tags chmod 0644 /dev/event-log-tags + +on property:sys.boot_completed=1 + start logd-auditctl
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp index 7d7a22f..447b067 100644 --- a/logd/tests/logd_test.cpp +++ b/logd/tests/logd_test.cpp
@@ -39,7 +39,6 @@ #endif #include "../LogReader.h" // pickup LOGD_SNDTIMEO -#include "../libaudit.h" // pickup AUDIT_RATE_LIMIT_* #ifdef __ANDROID__ static void send_to_control(char* buf, size_t len) { @@ -1065,145 +1064,3 @@ TEST(logd, multiple_test_10) { __android_log_btwrite_multiple__helper(10); } - -#ifdef __ANDROID__ -// returns violating pid -static pid_t sepolicy_rate(unsigned rate, unsigned num) { - pid_t pid = fork(); - - if (pid) { - siginfo_t info = {}; - if (TEMP_FAILURE_RETRY(waitid(P_PID, pid, &info, WEXITED))) return -1; - if (info.si_status) return -1; - return pid; - } - - // We may have DAC, but let's not have MAC - if ((setcon("u:object_r:shell:s0") < 0) && (setcon("u:r:shell:s0") < 0)) { - int save_errno = errno; - security_context_t context; - getcon(&context); - if (strcmp(context, "u:r:shell:s0")) { - fprintf(stderr, "setcon(\"u:r:shell:s0\") failed @\"%s\" %s\n", - context, strerror(save_errno)); - freecon(context); - _exit(-1); - // NOTREACHED - return -1; - } - } - - // The key here is we are root, but we are in u:r:shell:s0, - // and the directory does not provide us DAC access - // (eg: 0700 system system) so we trigger the pair dac_override - // and dac_read_search on every try to get past the message - // de-duper. We will also rotate the file name in the directory - // as another measure. - static const char file[] = "/data/drm/cannot_access_directory_%u"; - static const unsigned avc_requests_per_access = 2; - - rate /= avc_requests_per_access; - useconds_t usec; - if (rate == 0) { - rate = 1; - usec = 2000000; - } else { - usec = (1000000 + (rate / 2)) / rate; - } - num = (num + (avc_requests_per_access / 2)) / avc_requests_per_access; - - if (usec < 2) usec = 2; - - while (num > 0) { - if (access(android::base::StringPrintf(file, num).c_str(), F_OK) == 0) { - _exit(-1); - // NOTREACHED - return -1; - } - usleep(usec); - --num; - } - _exit(0); - // NOTREACHED - return -1; -} - -static constexpr int background_period = 10; - -static int count_avc(pid_t pid) { - int count = 0; - - // pid=-1 skip as pid is in error - if (pid == (pid_t)-1) return count; - - // pid=0 means we want to report the background count of avc: activities - struct logger_list* logger_list = - pid ? android_logger_list_alloc( - ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, pid) - : android_logger_list_alloc_time( - ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, - log_time(android_log_clockid()) - - log_time(background_period, 0), - 0); - if (!logger_list) return count; - struct logger* logger = android_logger_open(logger_list, LOG_ID_EVENTS); - if (!logger) { - android_logger_list_close(logger_list); - return count; - } - for (;;) { - log_msg log_msg; - - if (android_logger_list_read(logger_list, &log_msg) <= 0) break; - - if ((log_msg.entry.pid != pid) || (log_msg.entry.len < (4 + 1 + 8)) || - (log_msg.id() != LOG_ID_EVENTS)) - continue; - - char* eventData = log_msg.msg(); - if (!eventData) continue; - - uint32_t tag = get4LE(eventData); - if (tag != AUDITD_LOG_TAG) continue; - - if (eventData[4] != EVENT_TYPE_STRING) continue; - - // int len = get4LE(eventData + 4 + 1); - log_msg.buf[LOGGER_ENTRY_MAX_LEN] = '\0'; - const char* cp = strstr(eventData + 4 + 1 + 4, "): avc: denied"); - if (!cp) continue; - - ++count; - } - - android_logger_list_close(logger_list); - - return count; -} -#endif - -TEST(logd, sepolicy_rate_limiter) { -#ifdef __ANDROID__ - int background_selinux_activity_too_high = count_avc(0); - if (background_selinux_activity_too_high > 2) { - GTEST_LOG_(ERROR) << "Too much background selinux activity " - << background_selinux_activity_too_high * 60 / - background_period - << "/minute on the device, this test\n" - << "can not measure the functionality of the " - << "sepolicy rate limiter. Expect test to\n" - << "fail as this device is in a bad state, " - << "but is not strictly a unit test failure."; - } - - static const int rate = AUDIT_RATE_LIMIT; - static const int duration = 2; - // Two seconds of sustained denials. Depending on the overlap in the time - // window that the kernel is considering vs what this test is considering, - // allow some additional denials to prevent a flaky test. - EXPECT_LE(count_avc(sepolicy_rate(rate, rate * duration)), - rate * duration + rate); -#else - GTEST_LOG_(INFO) << "This test does nothing.\n"; -#endif -}
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt index 7324ba9..8792671 100644 --- a/rootdir/etc/ld.config.legacy.txt +++ b/rootdir/etc/ld.config.legacy.txt
@@ -79,8 +79,10 @@ namespace.runtime.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.links = default -# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library -# when it exists. +# Need allow_all_shared_libs because libart.so can dlopen oat files in +# /system/framework and /data. +# TODO(b/130340935): Use a dynamically created linker namespace similar to +# classloader-namespace for oat files, and tighten this up. namespace.runtime.link.default.allow_all_shared_libs = true ###############################################################################
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt index 45e80e1..b486411 100644 --- a/rootdir/etc/ld.config.txt +++ b/rootdir/etc/ld.config.txt
@@ -158,8 +158,10 @@ namespace.runtime.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.links = default -# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library -# when it exists. +# Need allow_all_shared_libs because libart.so can dlopen oat files in +# /system/framework and /data. +# TODO(b/130340935): Use a dynamically created linker namespace similar to +# classloader-namespace for oat files, and tighten this up. namespace.runtime.link.default.allow_all_shared_libs = true ############################################################################### @@ -436,8 +438,8 @@ namespace.runtime.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.links = system -# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library -# when it exists. +# TODO(b/130340935): Use a dynamically created linker namespace similar to +# classloader-namespace for oat files, and tighten this up. namespace.runtime.link.system.allow_all_shared_libs = true ############################################################################### @@ -601,8 +603,8 @@ namespace.runtime.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.links = default -# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library -# when it exists. +# TODO(b/130340935): Use a dynamically created linker namespace similar to +# classloader-namespace for oat files, and tighten this up. namespace.runtime.link.default.allow_all_shared_libs = true ###############################################################################
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt index a762ba8..12007dc 100644 --- a/rootdir/etc/ld.config.vndk_lite.txt +++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -100,8 +100,10 @@ namespace.runtime.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.links = default -# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library -# when it exists. +# Need allow_all_shared_libs because libart.so can dlopen oat files in +# /system/framework and /data. +# TODO(b/130340935): Use a dynamically created linker namespace similar to +# classloader-namespace for oat files, and tighten this up. namespace.runtime.link.default.allow_all_shared_libs = true ############################################################################### @@ -373,8 +375,8 @@ namespace.runtime.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.links = default -# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library -# when it exists. +# TODO(b/130340935): Use a dynamically created linker namespace similar to +# classloader-namespace for oat files, and tighten this up. namespace.runtime.link.default.allow_all_shared_libs = true ############################################################################### @@ -424,8 +426,8 @@ namespace.runtime.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.asan.search.paths = /apex/com.android.runtime/${LIB} namespace.runtime.links = default -# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library -# when it exists. +# TODO(b/130340935): Use a dynamically created linker namespace similar to +# classloader-namespace for oat files, and tighten this up. namespace.runtime.link.default.allow_all_shared_libs = true ###############################################################################
diff --git a/rootdir/init.rc b/rootdir/init.rc index 473cd8d..e94b8e2 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc
@@ -280,6 +280,11 @@ write /dev/cpu_variant:${ro.bionic.2nd_arch} ${ro.bionic.2nd_cpu_variant} chmod 0444 /dev/cpu_variant:${ro.bionic.2nd_arch} + # Allow system processes to read / write power state. + chown system system /sys/power/state + chown system system /sys/power/wakeup_count + chmod 0660 /sys/power/state + # Start logd before any other services run to ensure we capture all of their logs. start logd @@ -665,11 +670,8 @@ chown radio system /sys/android_power/acquire_partial_wake_lock chown radio system /sys/android_power/release_wake_lock chown system system /sys/power/autosleep - chown system system /sys/power/state - chown system system /sys/power/wakeup_count chown radio wakelock /sys/power/wake_lock chown radio wakelock /sys/power/wake_unlock - chmod 0660 /sys/power/state chmod 0660 /sys/power/wake_lock chmod 0660 /sys/power/wake_unlock
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp index f01a8c7..3bc3883 100644 --- a/shell_and_utilities/Android.bp +++ b/shell_and_utilities/Android.bp
@@ -10,6 +10,7 @@ phony { name: "shell_and_utilities_system", required: [ + "auditctl", "awk", "bzip2", "grep",