Merge "liblp: Add helpers for modifying groups."
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 4e6c879..c8d12cf 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -103,7 +103,7 @@
void reset(int new_value = -1) { reset(new_value, nullptr); }
int get() const { return fd_; }
- operator int() const { return get(); }
+ operator int() const { return get(); } // NOLINT
int release() __attribute__((warn_unused_result)) {
tag(fd_, this, nullptr);
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index 1616a61..bf58315 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -102,28 +102,3 @@
export_include_dirs: ["include_fstab"],
header_libs: ["libbase_headers"],
}
-
-cc_library_static {
- name: "libfs_avb",
- defaults: ["fs_mgr_defaults"],
- recovery_available: true,
- export_include_dirs: ["libfs_avb/include"],
- srcs: [
- "libfs_avb/avb_ops.cpp",
- "libfs_avb/fs_avb.cpp",
- ],
- static_libs: [
- "libavb",
- "libfstab",
- "libdm",
- ],
- export_static_lib_headers: [
- "libfstab",
- ],
- shared_libs: [
- "libcrypto",
- ],
- header_libs: [
- "libbase_headers",
- ],
-}
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 943fe10..9f6c550 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -523,13 +523,13 @@
}
// Mark the given block device as read-only, using the BLKROSET ioctl.
-bool fs_mgr_set_blk_ro(const std::string& blockdev) {
+bool fs_mgr_set_blk_ro(const std::string& blockdev, bool readonly) {
unique_fd fd(TEMP_FAILURE_RETRY(open(blockdev.c_str(), O_RDONLY | O_CLOEXEC)));
if (fd < 0) {
return false;
}
- int ON = 1;
+ int ON = readonly;
return ioctl(fd, BLKROSET, &ON) == 0;
}
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 7dae7f1..6364ca9 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -277,6 +277,9 @@
// Don't check entries that are managed by vold.
if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
+ // *_other doesn't want overlayfs.
+ if (entry->fs_mgr_flags.slot_select_other) return false;
+
// Only concerned with readonly partitions.
if (!(entry->flags & MS_RDONLY)) return false;
@@ -595,7 +598,11 @@
entry.mount_point = kScratchMountPoint;
entry.fs_type = mnt_type;
entry.flags = MS_RELATIME;
- if (readonly) entry.flags |= MS_RDONLY;
+ if (readonly) {
+ entry.flags |= MS_RDONLY;
+ } else {
+ fs_mgr_set_blk_ro(device_path, false);
+ }
auto save_errno = errno;
auto mounted = fs_mgr_do_mount_one(entry) == 0;
if (!mounted) {
@@ -653,6 +660,7 @@
return false;
}
command += " " + scratch_device;
+ fs_mgr_set_blk_ro(scratch_device, false);
auto ret = system(command.c_str());
if (ret) {
LERROR << "make " << mnt_type << " filesystem on " << scratch_device << " return=" << ret;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 7d1159b..7842ca2 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -134,7 +134,7 @@
const std::chrono::milliseconds relative_timeout,
FileWaitMode wait_mode = FileWaitMode::Exists);
-bool fs_mgr_set_blk_ro(const std::string& blockdev);
+bool fs_mgr_set_blk_ro(const std::string& blockdev, bool readonly = true);
bool fs_mgr_update_for_slotselect(Fstab* fstab);
bool fs_mgr_is_device_unlocked();
const std::string& get_android_dt_dir();
diff --git a/fs_mgr/libfs_avb/Android.bp b/fs_mgr/libfs_avb/Android.bp
new file mode 100644
index 0000000..d22eceb
--- /dev/null
+++ b/fs_mgr/libfs_avb/Android.bp
@@ -0,0 +1,100 @@
+//
+// 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.
+//
+
+cc_library_static {
+ name: "libfs_avb",
+ defaults: ["fs_mgr_defaults"],
+ recovery_available: true,
+ host_supported: true,
+ export_include_dirs: ["include"],
+ srcs: [
+ "avb_ops.cpp",
+ "avb_util.cpp",
+ "fs_avb.cpp",
+ "util.cpp",
+ ],
+ static_libs: [
+ "libavb",
+ "libdm",
+ "libfstab",
+ ],
+ export_static_lib_headers: [
+ "libfstab",
+ ],
+ shared_libs: [
+ "libcrypto",
+ ],
+ header_libs: [
+ "libbase_headers",
+ ],
+}
+
+cc_defaults {
+ name: "libfs_avb_host_test_defaults",
+ required: [
+ "avbtool",
+ ],
+ data: [
+ "tests/data/*",
+ ],
+ static_libs: [
+ "libgtest_host",
+ ],
+ shared_libs: [
+ "libbase",
+ "libchrome",
+ ],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+ cflags: [
+ "-DHOST_TEST",
+ ],
+}
+
+cc_library_host_static {
+ name: "libfs_avb_test_util",
+ defaults: ["libfs_avb_host_test_defaults"],
+ srcs: [
+ "tests/fs_avb_test_util.cpp",
+ ],
+}
+
+cc_test_host {
+ name: "libfs_avb_test",
+ defaults: ["libfs_avb_host_test_defaults"],
+ static_libs: [
+ "libfs_avb_test_util",
+ ],
+ srcs: [
+ "tests/basic_test.cpp",
+ ],
+}
+
+cc_test_host {
+ name: "libfs_avb_internal_test",
+ defaults: ["libfs_avb_host_test_defaults"],
+ static_libs: [
+ "libfs_avb_test_util",
+ "libfstab",
+ ],
+ srcs: [
+ "util.cpp",
+ "tests/util_test.cpp",
+ ],
+}
diff --git a/fs_mgr/libfs_avb/avb_ops.cpp b/fs_mgr/libfs_avb/avb_ops.cpp
index c985a97..3b0ef0b 100644
--- a/fs_mgr/libfs_avb/avb_ops.cpp
+++ b/fs_mgr/libfs_avb/avb_ops.cpp
@@ -37,7 +37,7 @@
#include <libavb/libavb.h>
#include <utils/Compat.h>
-#include "fs_mgr_priv.h"
+#include "util.h"
using namespace std::literals;
@@ -127,7 +127,7 @@
const std::string path = "/dev/block/by-name/"s + partition;
// Ensures the device path (a symlink created by init) is ready to access.
- if (!fs_mgr_wait_for_file(path, 1s)) {
+ if (!WaitForFile(path, 1s)) {
return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
}
diff --git a/fs_mgr/libfs_avb/avb_util.cpp b/fs_mgr/libfs_avb/avb_util.cpp
new file mode 100644
index 0000000..0ceb6ee
--- /dev/null
+++ b/fs_mgr/libfs_avb/avb_util.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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 "avb_util.h"
+
+#include <array>
+#include <sstream>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+
+#include "util.h"
+
+using android::base::unique_fd;
+
+namespace android {
+namespace fs_mgr {
+
+// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
+// See the following link for more details:
+// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
+bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt,
+ const std::string& root_digest, const std::string& blk_device,
+ android::dm::DmTable* table) {
+ // Loads androidboot.veritymode from kernel cmdline.
+ std::string verity_mode;
+ if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
+ verity_mode = "enforcing"; // Defaults to enforcing when it's absent.
+ }
+
+ // Converts veritymode to the format used in kernel.
+ std::string dm_verity_mode;
+ if (verity_mode == "enforcing") {
+ dm_verity_mode = "restart_on_corruption";
+ } else if (verity_mode == "logging") {
+ dm_verity_mode = "ignore_corruption";
+ } else if (verity_mode != "eio") { // Default dm_verity_mode is eio.
+ LERROR << "Unknown androidboot.veritymode: " << verity_mode;
+ return false;
+ }
+
+ std::ostringstream hash_algorithm;
+ hash_algorithm << hashtree_desc.hash_algorithm;
+
+ android::dm::DmTargetVerity target(0, hashtree_desc.image_size / 512,
+ hashtree_desc.dm_verity_version, blk_device, blk_device,
+ hashtree_desc.data_block_size, hashtree_desc.hash_block_size,
+ hashtree_desc.image_size / hashtree_desc.data_block_size,
+ hashtree_desc.tree_offset / hashtree_desc.hash_block_size,
+ hash_algorithm.str(), root_digest, salt);
+ if (hashtree_desc.fec_size > 0) {
+ target.UseFec(blk_device, hashtree_desc.fec_num_roots,
+ hashtree_desc.fec_offset / hashtree_desc.data_block_size,
+ hashtree_desc.fec_offset / hashtree_desc.data_block_size);
+ }
+ if (!dm_verity_mode.empty()) {
+ target.SetVerityMode(dm_verity_mode);
+ }
+ // Always use ignore_zero_blocks.
+ target.IgnoreZeroBlocks();
+
+ LINFO << "Built verity table: '" << target.GetParameterString() << "'";
+
+ return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target));
+}
+
+bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc,
+ const std::string& salt, const std::string& root_digest,
+ bool wait_for_verity_dev) {
+ android::dm::DmTable table;
+ if (!ConstructVerityTable(hashtree_desc, salt, root_digest, fstab_entry->blk_device, &table) ||
+ !table.valid()) {
+ LERROR << "Failed to construct verity table.";
+ return false;
+ }
+ table.set_readonly(true);
+
+ const std::string mount_point(basename(fstab_entry->mount_point.c_str()));
+ android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
+ if (!dm.CreateDevice(mount_point, table)) {
+ LERROR << "Couldn't create verity device!";
+ return false;
+ }
+
+ std::string dev_path;
+ if (!dm.GetDmDevicePathByName(mount_point, &dev_path)) {
+ LERROR << "Couldn't get verity device path!";
+ return false;
+ }
+
+ // Marks the underlying block device as read-only.
+ SetBlockDeviceReadOnly(fstab_entry->blk_device);
+
+ // Updates fstab_rec->blk_device to verity device name.
+ fstab_entry->blk_device = dev_path;
+
+ // Makes sure we've set everything up properly.
+ if (wait_for_verity_dev && !WaitForFile(dev_path, 1s)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool GetHashtreeDescriptor(const std::string& partition_name,
+ const std::vector<VBMetaData>& vbmeta_images,
+ AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt,
+ std::string* out_digest) {
+ bool found = false;
+ const uint8_t* desc_partition_name;
+
+ for (const auto& vbmeta : vbmeta_images) {
+ size_t num_descriptors;
+ std::unique_ptr<const AvbDescriptor* [], decltype(&avb_free)> descriptors(
+ avb_descriptor_get_all(vbmeta.data(), vbmeta.size(), &num_descriptors), avb_free);
+
+ if (!descriptors || num_descriptors < 1) {
+ continue;
+ }
+
+ for (size_t n = 0; n < num_descriptors && !found; n++) {
+ AvbDescriptor desc;
+ if (!avb_descriptor_validate_and_byteswap(descriptors[n], &desc)) {
+ LWARNING << "Descriptor[" << n << "] is invalid";
+ continue;
+ }
+ if (desc.tag == AVB_DESCRIPTOR_TAG_HASHTREE) {
+ desc_partition_name =
+ (const uint8_t*)descriptors[n] + sizeof(AvbHashtreeDescriptor);
+ if (!avb_hashtree_descriptor_validate_and_byteswap(
+ (AvbHashtreeDescriptor*)descriptors[n], out_hashtree_desc)) {
+ continue;
+ }
+ if (out_hashtree_desc->partition_name_len != partition_name.length()) {
+ continue;
+ }
+ // Notes that desc_partition_name is not NUL-terminated.
+ std::string hashtree_partition_name((const char*)desc_partition_name,
+ out_hashtree_desc->partition_name_len);
+ if (hashtree_partition_name == partition_name) {
+ found = true;
+ }
+ }
+ }
+
+ if (found) break;
+ }
+
+ if (!found) {
+ LERROR << "Partition descriptor not found: " << partition_name.c_str();
+ return false;
+ }
+
+ const uint8_t* desc_salt = desc_partition_name + out_hashtree_desc->partition_name_len;
+ *out_salt = BytesToHex(desc_salt, out_hashtree_desc->salt_len);
+
+ const uint8_t* desc_digest = desc_salt + out_hashtree_desc->salt_len;
+ *out_digest = BytesToHex(desc_digest, out_hashtree_desc->root_digest_len);
+
+ return true;
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/libfs_avb/avb_util.h b/fs_mgr/libfs_avb/avb_util.h
new file mode 100644
index 0000000..b81e931
--- /dev/null
+++ b/fs_mgr/libfs_avb/avb_util.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <libavb/libavb.h>
+#include <libdm/dm.h>
+
+#include "fs_avb/fs_avb.h"
+
+namespace android {
+namespace fs_mgr {
+
+// AvbHashtreeDescriptor to dm-verity table setup.
+bool GetHashtreeDescriptor(const std::string& partition_name,
+ const std::vector<VBMetaData>& vbmeta_images,
+ AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt,
+ std::string* out_digest);
+
+bool ConstructVerityTable(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt,
+ const std::string& root_digest, const std::string& blk_device,
+ android::dm::DmTable* table);
+
+bool HashtreeDmVeritySetup(FstabEntry* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc,
+ const std::string& salt, const std::string& root_digest,
+ bool wait_for_verity_dev);
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/libfs_avb/fs_avb.cpp b/fs_mgr/libfs_avb/fs_avb.cpp
index cf920f9..957aa87 100644
--- a/fs_mgr/libfs_avb/fs_avb.cpp
+++ b/fs_mgr/libfs_avb/fs_avb.cpp
@@ -28,84 +28,30 @@
#include <android-base/file.h>
#include <android-base/parseint.h>
-#include <android-base/properties.h>
#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
#include <libavb/libavb.h>
#include <libdm/dm.h>
#include "avb_ops.h"
-#include "fs_mgr_priv.h"
+#include "avb_util.h"
#include "sha.h"
+#include "util.h"
+
+using android::base::Basename;
+using android::base::ParseUint;
+using android::base::StringPrintf;
namespace android {
namespace fs_mgr {
-static inline bool nibble_value(const char& c, uint8_t* value) {
- FS_MGR_CHECK(value != nullptr);
-
- switch (c) {
- case '0' ... '9':
- *value = c - '0';
- break;
- case 'a' ... 'f':
- *value = c - 'a' + 10;
- break;
- case 'A' ... 'F':
- *value = c - 'A' + 10;
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-static bool hex_to_bytes(uint8_t* bytes, size_t bytes_len, const std::string& hex) {
- FS_MGR_CHECK(bytes != nullptr);
-
- if (hex.size() % 2 != 0) {
- return false;
- }
- if (hex.size() / 2 > bytes_len) {
- return false;
- }
- for (size_t i = 0, j = 0, n = hex.size(); i < n; i += 2, ++j) {
- uint8_t high;
- if (!nibble_value(hex[i], &high)) {
- return false;
- }
- uint8_t low;
- if (!nibble_value(hex[i + 1], &low)) {
- return false;
- }
- bytes[j] = (high << 4) | low;
- }
- return true;
-}
-
-static std::string bytes_to_hex(const uint8_t* bytes, size_t bytes_len) {
- FS_MGR_CHECK(bytes != nullptr);
-
- static const char* hex_digits = "0123456789abcdef";
- std::string hex;
-
- for (size_t i = 0; i < bytes_len; i++) {
- hex.push_back(hex_digits[(bytes[i] & 0xF0) >> 4]);
- hex.push_back(hex_digits[bytes[i] & 0x0F]);
- }
- return hex;
-}
-
template <typename Hasher>
-static std::pair<size_t, bool> verify_vbmeta_digest(const std::vector<VBMetaData>& vbmeta_images,
- const uint8_t* expected_digest) {
+std::pair<size_t, bool> VerifyVbmetaDigest(const std::vector<VBMetaData>& vbmeta_images,
+ const uint8_t* expected_digest) {
size_t total_size = 0;
Hasher hasher;
- for (size_t n = 0; n < vbmeta_images.size(); n++) {
- hasher.update(vbmeta_images[n].vbmeta_data(), vbmeta_images[n].vbmeta_size());
- total_size += vbmeta_images[n].vbmeta_size();
+ for (const auto& vbmeta : vbmeta_images) {
+ hasher.update(vbmeta.data(), vbmeta.size());
+ total_size += vbmeta.size();
}
bool matched = (memcmp(hasher.finalize(), expected_digest, Hasher::DIGEST_SIZE) == 0);
@@ -148,7 +94,7 @@
std::string value;
if (!fs_mgr_get_boot_config("vbmeta.size", &value) ||
- !android::base::ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) {
+ !ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) {
LERROR << "Invalid hash size: " << value.c_str();
return nullptr;
}
@@ -177,7 +123,7 @@
return nullptr;
}
- if (!hex_to_bytes(avb_verifier->digest_, sizeof(avb_verifier->digest_), digest)) {
+ if (!HexToBytes(avb_verifier->digest_, sizeof(avb_verifier->digest_), digest)) {
LERROR << "Hash digest contains non-hexidecimal character: " << digest.c_str();
return nullptr;
}
@@ -196,10 +142,10 @@
if (hash_alg_ == kSHA256) {
std::tie(total_size, digest_matched) =
- verify_vbmeta_digest<SHA256Hasher>(vbmeta_images, digest_);
+ VerifyVbmetaDigest<SHA256Hasher>(vbmeta_images, digest_);
} else if (hash_alg_ == kSHA512) {
std::tie(total_size, digest_matched) =
- verify_vbmeta_digest<SHA512Hasher>(vbmeta_images, digest_);
+ VerifyVbmetaDigest<SHA512Hasher>(vbmeta_images, digest_);
}
if (total_size != vbmeta_size_) {
@@ -216,155 +162,9 @@
return true;
}
-// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
-// See the following link for more details:
-// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
-static bool construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc,
- const std::string& salt, const std::string& root_digest,
- const std::string& blk_device, android::dm::DmTable* table) {
- // Loads androidboot.veritymode from kernel cmdline.
- std::string verity_mode;
- if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
- verity_mode = "enforcing"; // Defaults to enforcing when it's absent.
- }
-
- // Converts veritymode to the format used in kernel.
- std::string dm_verity_mode;
- if (verity_mode == "enforcing") {
- dm_verity_mode = "restart_on_corruption";
- } else if (verity_mode == "logging") {
- dm_verity_mode = "ignore_corruption";
- } else if (verity_mode != "eio") { // Default dm_verity_mode is eio.
- LERROR << "Unknown androidboot.veritymode: " << verity_mode;
- return false;
- }
-
- std::ostringstream hash_algorithm;
- hash_algorithm << hashtree_desc.hash_algorithm;
-
- android::dm::DmTargetVerity target(0, hashtree_desc.image_size / 512,
- hashtree_desc.dm_verity_version, blk_device, blk_device,
- hashtree_desc.data_block_size, hashtree_desc.hash_block_size,
- hashtree_desc.image_size / hashtree_desc.data_block_size,
- hashtree_desc.tree_offset / hashtree_desc.hash_block_size,
- hash_algorithm.str(), root_digest, salt);
- if (hashtree_desc.fec_size > 0) {
- target.UseFec(blk_device, hashtree_desc.fec_num_roots,
- hashtree_desc.fec_offset / hashtree_desc.data_block_size,
- hashtree_desc.fec_offset / hashtree_desc.data_block_size);
- }
- if (!dm_verity_mode.empty()) {
- target.SetVerityMode(dm_verity_mode);
- }
- // Always use ignore_zero_blocks.
- target.IgnoreZeroBlocks();
-
- LINFO << "Built verity table: '" << target.GetParameterString() << "'";
-
- return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target));
-}
-
-static bool hashtree_dm_verity_setup(FstabEntry* fstab_entry,
- const AvbHashtreeDescriptor& hashtree_desc,
- const std::string& salt, const std::string& root_digest,
- bool wait_for_verity_dev) {
- android::dm::DmTable table;
- if (!construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device,
- &table) ||
- !table.valid()) {
- LERROR << "Failed to construct verity table.";
- return false;
- }
- table.set_readonly(true);
-
- const std::string mount_point(basename(fstab_entry->mount_point.c_str()));
- android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
- if (!dm.CreateDevice(mount_point, table)) {
- LERROR << "Couldn't create verity device!";
- return false;
- }
-
- std::string dev_path;
- if (!dm.GetDmDevicePathByName(mount_point, &dev_path)) {
- LERROR << "Couldn't get verity device path!";
- return false;
- }
-
- // Marks the underlying block device as read-only.
- fs_mgr_set_blk_ro(fstab_entry->blk_device);
-
- // Updates fstab_rec->blk_device to verity device name.
- fstab_entry->blk_device = dev_path;
-
- // Makes sure we've set everything up properly.
- if (wait_for_verity_dev && !fs_mgr_wait_for_file(dev_path, 1s)) {
- return false;
- }
-
- return true;
-}
-
-static bool get_hashtree_descriptor(const std::string& partition_name,
- const std::vector<VBMetaData>& vbmeta_images,
- AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt,
- std::string* out_digest) {
- bool found = false;
- const uint8_t* desc_partition_name;
-
- for (size_t i = 0; i < vbmeta_images.size() && !found; i++) {
- // Get descriptors from vbmeta_images[i].
- size_t num_descriptors;
- std::unique_ptr<const AvbDescriptor* [], decltype(&avb_free)> descriptors(
- avb_descriptor_get_all(vbmeta_images[i].vbmeta_data(),
- vbmeta_images[i].vbmeta_size(), &num_descriptors),
- avb_free);
-
- if (!descriptors || num_descriptors < 1) {
- continue;
- }
-
- for (size_t j = 0; j < num_descriptors && !found; j++) {
- AvbDescriptor desc;
- if (!avb_descriptor_validate_and_byteswap(descriptors[j], &desc)) {
- LWARNING << "Descriptor[" << j << "] is invalid";
- continue;
- }
- if (desc.tag == AVB_DESCRIPTOR_TAG_HASHTREE) {
- desc_partition_name =
- (const uint8_t*)descriptors[j] + sizeof(AvbHashtreeDescriptor);
- if (!avb_hashtree_descriptor_validate_and_byteswap(
- (AvbHashtreeDescriptor*)descriptors[j], out_hashtree_desc)) {
- continue;
- }
- if (out_hashtree_desc->partition_name_len != partition_name.length()) {
- continue;
- }
- // Notes that desc_partition_name is not NUL-terminated.
- std::string hashtree_partition_name((const char*)desc_partition_name,
- out_hashtree_desc->partition_name_len);
- if (hashtree_partition_name == partition_name) {
- found = true;
- }
- }
- }
- }
-
- if (!found) {
- LERROR << "Partition descriptor not found: " << partition_name.c_str();
- return false;
- }
-
- const uint8_t* desc_salt = desc_partition_name + out_hashtree_desc->partition_name_len;
- *out_salt = bytes_to_hex(desc_salt, out_hashtree_desc->salt_len);
-
- const uint8_t* desc_digest = desc_salt + out_hashtree_desc->salt_len;
- *out_digest = bytes_to_hex(desc_digest, out_hashtree_desc->root_digest_len);
-
- return true;
-}
AvbUniquePtr AvbHandle::Open() {
- bool is_device_unlocked = fs_mgr_is_device_unlocked();
+ bool is_device_unlocked = IsDeviceUnlocked();
AvbUniquePtr avb_handle(new AvbHandle());
if (!avb_handle) {
@@ -407,8 +207,7 @@
}
// Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version".
- avb_handle->avb_version_ =
- android::base::StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
+ avb_handle->avb_version_ = StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR);
// Checks whether FLAGS_VERIFICATION_DISABLED is set:
// - Only the top-level vbmeta struct is read.
@@ -416,7 +215,7 @@
// and AVB HASHTREE descriptor(s).
AvbVBMetaImageHeader vbmeta_header;
avb_vbmeta_image_header_to_host_byte_order(
- (AvbVBMetaImageHeader*)avb_handle->vbmeta_images_[0].vbmeta_data(), &vbmeta_header);
+ (AvbVBMetaImageHeader*)avb_handle->vbmeta_images_[0].data(), &vbmeta_header);
bool verification_disabled = ((AvbVBMetaImageFlags)vbmeta_header.flags &
AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
@@ -462,7 +261,7 @@
if (fstab_entry->fs_mgr_flags.logical) {
partition_name = fstab_entry->logical_partition_name;
} else {
- partition_name = basename(fstab_entry->blk_device.c_str());
+ partition_name = Basename(fstab_entry->blk_device);
}
if (fstab_entry->fs_mgr_flags.slot_select) {
@@ -475,14 +274,14 @@
AvbHashtreeDescriptor hashtree_descriptor;
std::string salt;
std::string root_digest;
- if (!get_hashtree_descriptor(partition_name, vbmeta_images_, &hashtree_descriptor, &salt,
- &root_digest)) {
+ if (!GetHashtreeDescriptor(partition_name, vbmeta_images_, &hashtree_descriptor, &salt,
+ &root_digest)) {
return AvbHashtreeResult::kFail;
}
// Converts HASHTREE descriptor to verity_table_params.
- if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest,
- wait_for_verity_dev)) {
+ if (!HashtreeDmVeritySetup(fstab_entry, hashtree_descriptor, salt, root_digest,
+ wait_for_verity_dev)) {
return AvbHashtreeResult::kFail;
}
diff --git a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
index 0c2b231..eca6984 100644
--- a/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
+++ b/fs_mgr/libfs_avb/include/fs_avb/fs_avb.h
@@ -37,7 +37,7 @@
// Constructors
VBMetaData() : vbmeta_ptr_(nullptr), vbmeta_size_(0){};
- VBMetaData(uint8_t* data, size_t size)
+ VBMetaData(const uint8_t* data, size_t size)
: vbmeta_ptr_(new (std::nothrow) uint8_t[size]), vbmeta_size_(size) {
// The ownership of data is NOT transferred, i.e., the caller still
// needs to release the memory as we make a copy here.
@@ -49,8 +49,8 @@
// Get methods for each data member.
const std::string& device_path() const { return device_path_; }
- uint8_t* vbmeta_data() const { return vbmeta_ptr_.get(); }
- const size_t& vbmeta_size() const { return vbmeta_size_; }
+ uint8_t* data() const { return vbmeta_ptr_.get(); }
+ const size_t& size() const { return vbmeta_size_; }
// Maximum size of a vbmeta data - 64 KiB.
static const size_t kMaxVBMetaSize = 64 * 1024;
diff --git a/fs_mgr/libfs_avb/tests/Android.bp b/fs_mgr/libfs_avb/tests/Android.bp
deleted file mode 100644
index 24e1d76..0000000
--- a/fs_mgr/libfs_avb/tests/Android.bp
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// 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.
-//
-
-cc_test_host {
- name: "libfs_avb_host_unittest",
- required: [
- "avbtool",
- ],
- data: [
- "data/*",
- ],
- static_libs: [
- "libgtest_host",
- ],
- shared_libs: [
- "libbase",
- "libchrome",
- ],
- srcs: [
- "fs_avb_unittest_util.cpp",
- ],
- target: {
- darwin: {
- enabled: false,
- },
- },
-}
diff --git a/fs_mgr/libfs_avb/tests/basic_test.cpp b/fs_mgr/libfs_avb/tests/basic_test.cpp
new file mode 100644
index 0000000..5a1cd0d
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/basic_test.cpp
@@ -0,0 +1,273 @@
+/*
+ * 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 "fs_avb_test_util.h"
+
+#include <stdlib.h>
+
+#include <android-base/file.h>
+#include <base/files/file_util.h>
+#include <base/strings/string_util.h>
+
+namespace fs_avb_host_test {
+
+TEST_F(BaseFsAvbTest, GenerateImage) {
+ const size_t image_size = 5 * 1024 * 1024;
+ base::FilePath boot_path = GenerateImage("boot.img", image_size);
+ EXPECT_NE(0U, boot_path.value().size());
+
+ // Checks file size is as expected.
+ int64_t file_size;
+ ASSERT_TRUE(base::GetFileSize(boot_path, &file_size));
+ EXPECT_EQ(file_size, image_size);
+
+ // Checks file content is as expected.
+ std::vector<uint8_t> expected_content;
+ expected_content.resize(image_size);
+ for (size_t n = 0; n < image_size; n++) {
+ expected_content[n] = uint8_t(n);
+ }
+ std::vector<uint8_t> actual_content;
+ actual_content.resize(image_size);
+ EXPECT_TRUE(
+ base::ReadFile(boot_path, reinterpret_cast<char*>(actual_content.data()), image_size));
+ EXPECT_EQ(expected_content, actual_content);
+}
+
+TEST_F(BaseFsAvbTest, GenerateVBMetaImage) {
+ GenerateVBMetaImage("vbmeta.img", "SHA256_RSA2048", 0, data_dir_.Append("testkey_rsa2048.pem"),
+ {}, /* include_descriptor_image_paths */
+ {}, /* chain_partitions */
+ "--internal_release_string \"unit test\"");
+ EXPECT_EQ("5eba9ad4e775645e7eac441a563c200681ae868158d06f6a6cd36d06c07bd781",
+ CalcVBMetaDigest("vbmeta.img", "sha256"));
+ EXPECT_EQ(
+ "Minimum libavb version: 1.0\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 320 bytes\n"
+ "Auxiliary Block: 576 bytes\n"
+ "Algorithm: SHA256_RSA2048\n"
+ "Rollback Index: 0\n"
+ "Flags: 0\n"
+ "Release String: 'unit test'\n"
+ "Descriptors:\n"
+ " (none)\n",
+ InfoImage("vbmeta.img"));
+}
+
+TEST_F(BaseFsAvbTest, AddHashFooter) {
+ // Generates a raw boot.img
+ const size_t image_size = 5 * 1024 * 1024;
+ const size_t partition_size = 10 * 1024 * 1024;
+ base::FilePath boot_path = GenerateImage("boot.img", image_size);
+ EXPECT_NE(0U, boot_path.value().size());
+ // Checks file size is as expected.
+ int64_t file_size;
+ ASSERT_TRUE(base::GetFileSize(boot_path, &file_size));
+ EXPECT_EQ(file_size, image_size);
+ // Appends AVB Hash Footer.
+ AddAvbFooter(boot_path, "hash", "boot", partition_size, "SHA256_RSA4096", 10,
+ data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+ // Extracts boot vbmeta from boot.img into boot-vbmeta.img.
+ ExtractVBMetaImage(boot_path, "boot-vbmeta.img");
+ EXPECT_EQ(
+ "Minimum libavb version: 1.0\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 576 bytes\n"
+ "Auxiliary Block: 1216 bytes\n"
+ "Algorithm: SHA256_RSA4096\n"
+ "Rollback Index: 10\n"
+ "Flags: 0\n"
+ "Release String: 'unit test'\n"
+ "Descriptors:\n"
+ " Hash descriptor:\n"
+ " Image Size: 5242880 bytes\n"
+ " Hash Algorithm: sha256\n"
+ " Partition Name: boot\n"
+ " Salt: d00df00d\n"
+ " Digest: "
+ "222dd01e98284a1fcd7781f85d1392e43a530511a64eff96db197db90ebc4df1\n"
+ " Flags: 0\n",
+ InfoImage("boot-vbmeta.img"));
+}
+
+TEST_F(BaseFsAvbTest, AddHashtreeFooter) {
+ // Generates a raw system.img
+ const size_t image_size = 50 * 1024 * 1024;
+ const size_t partition_size = 60 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system.img", image_size);
+ EXPECT_NE(0U, system_path.value().size());
+ // Checks file size is as expected.
+ int64_t file_size;
+ ASSERT_TRUE(base::GetFileSize(system_path, &file_size));
+ EXPECT_EQ(file_size, image_size);
+ // Appends AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system", partition_size, "SHA512_RSA8192", 20,
+ data_dir_.Append("testkey_rsa8192.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+ // Extracts system vbmeta from system.img into system-vbmeta.img.
+ ExtractVBMetaImage(system_path, "system-vbmeta.img");
+ EXPECT_EQ(
+ "Minimum libavb version: 1.0\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 1088 bytes\n"
+ "Auxiliary Block: 2304 bytes\n"
+ "Algorithm: SHA512_RSA8192\n"
+ "Rollback Index: 20\n"
+ "Flags: 0\n"
+ "Release String: 'unit test'\n"
+ "Descriptors:\n"
+ " Hashtree descriptor:\n"
+ " Version of dm-verity: 1\n"
+ " Image Size: 52428800 bytes\n"
+ " Tree Offset: 52428800\n"
+ " Tree Size: 413696 bytes\n"
+ " Data Block Size: 4096 bytes\n"
+ " Hash Block Size: 4096 bytes\n"
+ " FEC num roots: 2\n"
+ " FEC offset: 52842496\n"
+ " FEC size: 417792 bytes\n"
+ " Hash Algorithm: sha1\n"
+ " Partition Name: system\n"
+ " Salt: d00df00d\n"
+ " Root Digest: d20d40c02298e385ab6d398a61a3b91dc9947d99\n"
+ " Flags: 0\n",
+ InfoImage("system-vbmeta.img"));
+}
+
+TEST_F(BaseFsAvbTest, GenerateVBMetaImageWithDescriptors) {
+ // Generates a raw boot.img
+ const size_t boot_image_size = 5 * 1024 * 1024;
+ const size_t boot_partition_size = 10 * 1024 * 1024;
+ base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
+ // Adds AVB Hash Footer.
+ AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA4096", 10,
+ data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Generates a raw system.img, use a smaller size to speed-up unit test.
+ const size_t system_image_size = 10 * 1024 * 1024;
+ const size_t system_partition_size = 15 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system.img", system_image_size);
+ // Adds AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA8192", 20,
+ data_dir_.Append("testkey_rsa8192.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Makes a vbmeta.img including both 'boot' and 'system' descriptors.
+ GenerateVBMetaImage("vbmeta.img", "SHA256_RSA2048", 0, data_dir_.Append("testkey_rsa2048.pem"),
+ {boot_path, system_path}, /* include_descriptor_image_paths */
+ {}, /* chain_partitions */
+ "--internal_release_string \"unit test\"");
+ EXPECT_EQ("a069cbfc30c816cddf3b53f1ad53b7ca5d61a3d93845eb596bbb1b40caa1c62f",
+ CalcVBMetaDigest("vbmeta.img", "sha256"));
+ EXPECT_EQ(
+ "Minimum libavb version: 1.0\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 320 bytes\n"
+ "Auxiliary Block: 960 bytes\n"
+ "Algorithm: SHA256_RSA2048\n"
+ "Rollback Index: 0\n"
+ "Flags: 0\n"
+ "Release String: 'unit test'\n"
+ "Descriptors:\n"
+ " Hash descriptor:\n"
+ " Image Size: 5242880 bytes\n"
+ " Hash Algorithm: sha256\n"
+ " Partition Name: boot\n"
+ " Salt: d00df00d\n"
+ " Digest: "
+ "222dd01e98284a1fcd7781f85d1392e43a530511a64eff96db197db90ebc4df1\n"
+ " Flags: 0\n"
+ " Hashtree descriptor:\n"
+ " Version of dm-verity: 1\n"
+ " Image Size: 10485760 bytes\n"
+ " Tree Offset: 10485760\n"
+ " Tree Size: 86016 bytes\n"
+ " Data Block Size: 4096 bytes\n"
+ " Hash Block Size: 4096 bytes\n"
+ " FEC num roots: 2\n"
+ " FEC offset: 10571776\n"
+ " FEC size: 90112 bytes\n"
+ " Hash Algorithm: sha1\n"
+ " Partition Name: system\n"
+ " Salt: d00df00d\n"
+ " Root Digest: a3d5dd307341393d85de356c384ff543ec1ed81b\n"
+ " Flags: 0\n",
+ InfoImage("vbmeta.img"));
+}
+
+TEST_F(BaseFsAvbTest, GenerateVBMetaImageWithChainDescriptors) {
+ // Generates a raw boot.img
+ const size_t boot_image_size = 5 * 1024 * 1024;
+ const size_t boot_partition_size = 10 * 1024 * 1024;
+ base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
+ // Adds AVB Hash Footer.
+ AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
+ data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Generates a raw system.img, use a smaller size to speed-up unit test.
+ const size_t system_image_size = 10 * 1024 * 1024;
+ const size_t system_partition_size = 15 * 1024 * 1024;
+ base::FilePath system_path = GenerateImage("system.img", system_image_size);
+ // Adds AVB Hashtree Footer.
+ AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
+ data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
+ "--internal_release_string \"unit test\"");
+
+ // Make a vbmeta image with chain partitions.
+ base::FilePath rsa2048_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
+ base::FilePath rsa4096_public_key =
+ ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
+ GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0, data_dir_.Append("testkey_rsa8192.pem"),
+ {}, /* include_descriptor_image_paths */
+ {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
+ {"system", 2, rsa4096_public_key}},
+ "--internal_release_string \"unit test\"");
+
+ // vbmeta digest calculation includes the chained vbmeta from boot.img and system.img.
+ EXPECT_EQ("abbe11b316901f3336e26630f64c4732dadbe14532186ac8640e4141a403721f",
+ CalcVBMetaDigest("vbmeta.img", "sha256"));
+ EXPECT_EQ(
+ "Minimum libavb version: 1.0\n"
+ "Header Block: 256 bytes\n"
+ "Authentication Block: 1088 bytes\n"
+ "Auxiliary Block: 3840 bytes\n"
+ "Algorithm: SHA256_RSA8192\n"
+ "Rollback Index: 0\n"
+ "Flags: 0\n"
+ "Release String: 'unit test'\n"
+ "Descriptors:\n"
+ " Chain Partition descriptor:\n"
+ " Partition Name: boot\n"
+ " Rollback Index Location: 1\n"
+ " Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
+ " Chain Partition descriptor:\n"
+ " Partition Name: system\n"
+ " Rollback Index Location: 2\n"
+ " Public key (sha1): 2597c218aae470a130f61162feaae70afd97f011\n",
+ InfoImage("vbmeta.img"));
+}
+
+} // namespace fs_avb_host_test
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp b/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
new file mode 100644
index 0000000..95b17d8
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
@@ -0,0 +1,220 @@
+/*
+ * 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 "fs_avb_test_util.h"
+
+#include <stdlib.h>
+
+#include <android-base/file.h>
+#include <base/files/file_util.h>
+#include <base/strings/string_util.h>
+
+namespace fs_avb_host_test {
+
+// Need to match the data setting in Android.bp:
+// data: ["tests/data/*"]
+base::FilePath BaseFsAvbTest::data_dir_ = base::FilePath("tests/data");
+
+void BaseFsAvbTest::SetUp() {
+ // Changes current directory to test executable directory so that relative path
+ // references to test dependencies don't rely on being manually run from
+ // the executable directory. With this, we can just open "./tests/data/testkey_rsa2048.pem"
+ // from the source.
+ base::SetCurrentDirectory(base::FilePath(android::base::GetExecutableDirectory()));
+
+ // Creates a temporary directory, e.g., /tmp/libfs_avb-tests.XXXXXX to stash images in.
+ base::FilePath tmp_dir;
+ ASSERT_TRUE(GetTempDir(&tmp_dir));
+ base::CreateTemporaryDirInDir(tmp_dir, "libfs_avb-tests.", &test_dir_);
+}
+
+void BaseFsAvbTest::TearDown() {
+ // Nukes temporary directory.
+ ASSERT_NE(std::string::npos, test_dir_.value().find("libfs_avb-tests"));
+ ASSERT_TRUE(base::DeleteFile(test_dir_, true /* recursive */));
+}
+
+std::string BaseFsAvbTest::CalcVBMetaDigest(const std::string& file_name,
+ const std::string& hash_algorithm) {
+ auto iter = vbmeta_images_.find(file_name);
+ EXPECT_NE(iter, vbmeta_images_.end()); // ensures file_name is generated before.
+
+ // Gets the image path from iterator->second.path: VBMetaImage.path.
+ base::FilePath image_path = iter->second.path;
+ base::FilePath vbmeta_digest_path = test_dir_.Append("vbmeta_digest");
+ EXPECT_COMMAND(0,
+ "avbtool calculate_vbmeta_digest --image %s --hash_algorithm %s"
+ " --output %s",
+ image_path.value().c_str(), hash_algorithm.c_str(),
+ vbmeta_digest_path.value().c_str());
+ // Reads the content of the output digest file.
+ std::string vbmeta_digest_data;
+ EXPECT_TRUE(base::ReadFileToString(vbmeta_digest_path, &vbmeta_digest_data));
+ // Returns the trimmed digest.
+ std::string trimmed_digest_data;
+ base::TrimString(vbmeta_digest_data, " \t\n", &trimmed_digest_data);
+ return trimmed_digest_data;
+}
+
+void BaseFsAvbTest::GenerateVBMetaImage(
+ const std::string& file_name, const std::string& avb_algorithm, uint64_t rollback_index,
+ const base::FilePath& key_path,
+ const std::vector<base::FilePath>& include_descriptor_image_paths,
+ const std::vector<ChainPartitionConfig>& chain_partitions,
+ const std::string& additional_options) {
+ // --algorithm and --key
+ std::string signing_options;
+ if (avb_algorithm == "") {
+ signing_options = " --algorithm NONE ";
+ } else {
+ signing_options =
+ std::string(" --algorithm ") + avb_algorithm + " --key " + key_path.value() + " ";
+ }
+ // --include_descriptors_from_image
+ std::string include_descriptor_options;
+ for (const auto& path : include_descriptor_image_paths) {
+ include_descriptor_options += " --include_descriptors_from_image " + path.value();
+ }
+ // --chain_partitions
+ std::string chain_partition_options;
+ for (const auto& partition : chain_partitions) {
+ chain_partition_options += base::StringPrintf(
+ " --chain_partition %s:%u:%s", partition.partition_name.c_str(),
+ partition.rollback_index_location, partition.key_blob_path.value().c_str());
+ }
+ // Starts to 'make_vbmeta_image'.
+ VBMetaImage vbmeta_image;
+ vbmeta_image.path = test_dir_.Append(file_name);
+ EXPECT_COMMAND(0,
+ "avbtool make_vbmeta_image"
+ " --rollback_index %" PRIu64
+ " %s %s %s %s"
+ " --output %s",
+ rollback_index, signing_options.c_str(), include_descriptor_options.c_str(),
+ chain_partition_options.c_str(), additional_options.c_str(),
+ vbmeta_image.path.value().c_str());
+ int64_t file_size;
+ ASSERT_TRUE(base::GetFileSize(vbmeta_image.path, &file_size));
+ vbmeta_image.content.resize(file_size);
+ ASSERT_TRUE(base::ReadFile(vbmeta_image.path,
+ reinterpret_cast<char*>(vbmeta_image.content.data()), file_size));
+ // Stores the generated vbmeta image into vbmeta_images_ member object.
+ vbmeta_images_.emplace(file_name, std::move(vbmeta_image));
+}
+
+void BaseFsAvbTest::ExtractVBMetaImage(const base::FilePath& image_path,
+ const std::string& output_file_name,
+ const size_t padding_size) {
+ VBMetaImage vbmeta_image;
+ vbmeta_image.path = test_dir_.Append(output_file_name);
+ EXPECT_COMMAND(0,
+ "avbtool extract_vbmeta_image"
+ " --image %s"
+ " --output %s"
+ " --padding_size %zu",
+ image_path.value().c_str(), vbmeta_image.path.value().c_str(), padding_size);
+ int64_t file_size;
+ ASSERT_TRUE(base::GetFileSize(vbmeta_image.path, &file_size));
+ vbmeta_image.content.resize(file_size);
+ ASSERT_TRUE(base::ReadFile(vbmeta_image.path,
+ reinterpret_cast<char*>(vbmeta_image.content.data()), file_size));
+ // Stores the extracted vbmeta image into vbmeta_images_ member object.
+ vbmeta_images_.emplace(output_file_name, std::move(vbmeta_image));
+}
+
+// Generates a file with name |file_name| of size |image_size| with
+// known content (0x00 0x01 0x02 .. 0xff 0x00 0x01 ..).
+base::FilePath BaseFsAvbTest::GenerateImage(const std::string& file_name, size_t image_size,
+ uint8_t start_byte) {
+ std::vector<uint8_t> image;
+ image.resize(image_size);
+ for (size_t n = 0; n < image_size; n++) {
+ image[n] = uint8_t(n + start_byte);
+ }
+ base::FilePath image_path = test_dir_.Append(file_name);
+ EXPECT_EQ(image_size,
+ static_cast<const size_t>(base::WriteFile(
+ image_path, reinterpret_cast<const char*>(image.data()), image.size())));
+ return image_path;
+}
+
+void BaseFsAvbTest::AddAvbFooter(const base::FilePath& image_path, const std::string& footer_type,
+ const std::string& partition_name, const uint64_t partition_size,
+ const std::string& avb_algorithm, uint64_t rollback_index,
+ const base::FilePath& key_path, const std::string& salt,
+ const std::string& additional_options) {
+ // 'add_hash_footer' or 'add_hashtree_footer'.
+ EXPECT_TRUE(footer_type == "hash" or footer_type == "hashtree");
+ std::string add_footer_option = "add_" + footer_type + "_footer";
+
+ std::string signing_options;
+ if (avb_algorithm == "") {
+ signing_options = " --algorithm NONE ";
+ } else {
+ signing_options =
+ std::string(" --algorithm ") + avb_algorithm + " --key " + key_path.value() + " ";
+ }
+ EXPECT_COMMAND(0,
+ "avbtool %s"
+ " --image %s"
+ " --partition_name %s "
+ " --partition_size %" PRIu64 " --rollback_index %" PRIu64
+ " --salt %s"
+ " %s %s",
+ add_footer_option.c_str(), image_path.value().c_str(), partition_name.c_str(),
+ partition_size, rollback_index, salt.c_str(), signing_options.c_str(),
+ additional_options.c_str());
+}
+
+std::string BaseFsAvbTest::InfoImage(const base::FilePath& image_path) {
+ base::FilePath tmp_path = test_dir_.Append("info_output.txt");
+ EXPECT_COMMAND(0, "avbtool info_image --image %s --output %s", image_path.value().c_str(),
+ tmp_path.value().c_str());
+ std::string info_data;
+ EXPECT_TRUE(base::ReadFileToString(tmp_path, &info_data));
+ return info_data;
+}
+
+std::string BaseFsAvbTest::InfoImage(const std::string& file_name) {
+ auto iter = vbmeta_images_.find(file_name);
+ EXPECT_NE(iter, vbmeta_images_.end()); // ensures file_name is generated before.
+ // Gets the image path from iterator->second.path: VBMetaImage.path.
+ base::FilePath image_path = iter->second.path;
+ return InfoImage(image_path);
+}
+
+base::FilePath BaseFsAvbTest::ExtractPublicKeyAvb(const base::FilePath& key_path) {
+ std::string file_name = key_path.RemoveExtension().BaseName().value();
+ base::FilePath tmp_path = test_dir_.Append(file_name + "public_key.bin");
+ EXPECT_COMMAND(0,
+ "avbtool extract_public_key --key %s"
+ " --output %s",
+ key_path.value().c_str(), tmp_path.value().c_str());
+ return tmp_path;
+}
+
+std::string BaseFsAvbTest::ExtractPublicKeyAvbBlob(const base::FilePath& key_path) {
+ base::FilePath tmp_path = test_dir_.Append("public_key.bin");
+ EXPECT_COMMAND(0,
+ "avbtool extract_public_key --key %s"
+ " --output %s",
+ key_path.value().c_str(), tmp_path.value().c_str());
+ std::string key_data;
+ EXPECT_TRUE(base::ReadFileToString(tmp_path, &key_data));
+ return key_data;
+}
+
+} // namespace fs_avb_host_test
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_unittest_util.h b/fs_mgr/libfs_avb/tests/fs_avb_test_util.h
similarity index 97%
rename from fs_mgr/libfs_avb/tests/fs_avb_unittest_util.h
rename to fs_mgr/libfs_avb/tests/fs_avb_test_util.h
index f329466..f80dc5f 100644
--- a/fs_mgr/libfs_avb/tests/fs_avb_unittest_util.h
+++ b/fs_mgr/libfs_avb/tests/fs_avb_test_util.h
@@ -79,7 +79,7 @@
// Generate a file with name |file_name| of size |image_size| with
// known content (0x00 0x01 0x02 .. 0xff 0x00 0x01 ..).
- base::FilePath GenerateImage(const std::string file_name, size_t image_size,
+ base::FilePath GenerateImage(const std::string& file_name, size_t image_size,
uint8_t start_byte = 0);
// Invokes 'avbtool add_hash_footer' or 'avbtool add_hashtree_footer' to sign
// the |image_path|. The |footer_type| can be either "hash" or "hashtree".
@@ -107,6 +107,8 @@
base::FilePath test_dir_;
// Maps vbmeta image name (e.g., vbmeta_a.img, system_a.img) to VBMetaImage.
std::map<std::string, VBMetaImage> vbmeta_images_;
+
+ static base::FilePath data_dir_;
};
} // namespace fs_avb_host_test
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_unittest_util.cpp b/fs_mgr/libfs_avb/tests/fs_avb_unittest_util.cpp
deleted file mode 100644
index 216d1cb..0000000
--- a/fs_mgr/libfs_avb/tests/fs_avb_unittest_util.cpp
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * 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 "fs_avb_unittest_util.h"
-
-#include <stdlib.h>
-
-#include <android-base/file.h>
-#include <base/files/file_util.h>
-#include <base/strings/string_util.h>
-
-namespace fs_avb_host_test {
-
-void BaseFsAvbTest::SetUp() {
- // Changes current directory to test executable directory so that relative path
- // references to test dependencies don't rely on being manually run from
- // the executable directory. With this, we can just open "./data/testkey_rsa2048.pem"
- // from the source.
- base::SetCurrentDirectory(base::FilePath(android::base::GetExecutableDirectory()));
-
- // Creates a temporary directory, e.g., /tmp/libfs_avb-tests.XXXXXX to stash images in.
- base::FilePath tmp_dir;
- ASSERT_TRUE(GetTempDir(&tmp_dir));
- base::CreateTemporaryDirInDir(tmp_dir, "libfs_avb-tests.", &test_dir_);
-}
-
-void BaseFsAvbTest::TearDown() {
- // Nukes temporary directory.
- ASSERT_NE(std::string::npos, test_dir_.value().find("libfs_avb-tests"));
- ASSERT_TRUE(base::DeleteFile(test_dir_, true /* recursive */));
-}
-
-std::string BaseFsAvbTest::CalcVBMetaDigest(const std::string& file_name,
- const std::string& hash_algorithm) {
- auto iter = vbmeta_images_.find(file_name);
- EXPECT_NE(iter, vbmeta_images_.end()); // ensures file_name is generated before.
-
- // Gets the image path from iterator->second.path: VBMetaImage.path.
- base::FilePath image_path = iter->second.path;
- base::FilePath vbmeta_digest_path = test_dir_.Append("vbmeta_digest");
- EXPECT_COMMAND(0,
- "avbtool calculate_vbmeta_digest --image %s --hash_algorithm %s"
- " --output %s",
- image_path.value().c_str(), hash_algorithm.c_str(),
- vbmeta_digest_path.value().c_str());
- // Reads the content of the output digest file.
- std::string vbmeta_digest_data;
- EXPECT_TRUE(base::ReadFileToString(vbmeta_digest_path, &vbmeta_digest_data));
- // Returns the trimmed digest.
- std::string trimmed_digest_data;
- base::TrimString(vbmeta_digest_data, " \t\n", &trimmed_digest_data);
- return trimmed_digest_data;
-}
-
-void BaseFsAvbTest::GenerateVBMetaImage(
- const std::string& file_name, const std::string& avb_algorithm, uint64_t rollback_index,
- const base::FilePath& key_path,
- const std::vector<base::FilePath>& include_descriptor_image_paths,
- const std::vector<ChainPartitionConfig>& chain_partitions,
- const std::string& additional_options) {
- // --algorithm and --key
- std::string signing_options;
- if (avb_algorithm == "") {
- signing_options = " --algorithm NONE ";
- } else {
- signing_options =
- std::string(" --algorithm ") + avb_algorithm + " --key " + key_path.value() + " ";
- }
- // --include_descriptors_from_image
- std::string include_descriptor_options;
- for (const auto& path : include_descriptor_image_paths) {
- include_descriptor_options += " --include_descriptors_from_image " + path.value();
- }
- // --chain_partitions
- std::string chain_partition_options;
- for (const auto& partition : chain_partitions) {
- chain_partition_options += base::StringPrintf(
- " --chain_partition %s:%u:%s", partition.partition_name.c_str(),
- partition.rollback_index_location, partition.key_blob_path.value().c_str());
- }
- // Starts to 'make_vbmeta_image'.
- VBMetaImage vbmeta_image;
- vbmeta_image.path = test_dir_.Append(file_name);
- EXPECT_COMMAND(0,
- "avbtool make_vbmeta_image"
- " --rollback_index %" PRIu64
- " %s %s %s %s"
- " --output %s",
- rollback_index, signing_options.c_str(), include_descriptor_options.c_str(),
- chain_partition_options.c_str(), additional_options.c_str(),
- vbmeta_image.path.value().c_str());
- int64_t file_size;
- ASSERT_TRUE(base::GetFileSize(vbmeta_image.path, &file_size));
- vbmeta_image.content.resize(file_size);
- ASSERT_TRUE(base::ReadFile(vbmeta_image.path,
- reinterpret_cast<char*>(vbmeta_image.content.data()), file_size));
- // Stores the generated vbmeta image into vbmeta_images_ member object.
- vbmeta_images_.emplace(file_name, std::move(vbmeta_image));
-}
-
-void BaseFsAvbTest::ExtractVBMetaImage(const base::FilePath& image_path,
- const std::string& output_file_name,
- const size_t padding_size) {
- VBMetaImage vbmeta_image;
- vbmeta_image.path = test_dir_.Append(output_file_name);
- EXPECT_COMMAND(0,
- "avbtool extract_vbmeta_image"
- " --image %s"
- " --output %s"
- " --padding_size %zu",
- image_path.value().c_str(), vbmeta_image.path.value().c_str(), padding_size);
- int64_t file_size;
- ASSERT_TRUE(base::GetFileSize(vbmeta_image.path, &file_size));
- vbmeta_image.content.resize(file_size);
- ASSERT_TRUE(base::ReadFile(vbmeta_image.path,
- reinterpret_cast<char*>(vbmeta_image.content.data()), file_size));
- // Stores the extracted vbmeta image into vbmeta_images_ member object.
- vbmeta_images_.emplace(output_file_name, std::move(vbmeta_image));
-}
-
-// Generates a file with name |file_name| of size |image_size| with
-// known content (0x00 0x01 0x02 .. 0xff 0x00 0x01 ..).
-base::FilePath BaseFsAvbTest::GenerateImage(const std::string file_name, size_t image_size,
- uint8_t start_byte) {
- std::vector<uint8_t> image;
- image.resize(image_size);
- for (size_t n = 0; n < image_size; n++) {
- image[n] = uint8_t(n + start_byte);
- }
- base::FilePath image_path = test_dir_.Append(file_name);
- EXPECT_EQ(image_size,
- static_cast<const size_t>(base::WriteFile(
- image_path, reinterpret_cast<const char*>(image.data()), image.size())));
- return image_path;
-}
-
-void BaseFsAvbTest::AddAvbFooter(const base::FilePath& image_path, const std::string& footer_type,
- const std::string& partition_name, const uint64_t partition_size,
- const std::string& avb_algorithm, uint64_t rollback_index,
- const base::FilePath& key_path, const std::string& salt,
- const std::string& additional_options) {
- // 'add_hash_footer' or 'add_hashtree_footer'.
- EXPECT_TRUE(footer_type == "hash" or footer_type == "hashtree");
- std::string add_footer_option = "add_" + footer_type + "_footer";
-
- std::string signing_options;
- if (avb_algorithm == "") {
- signing_options = " --algorithm NONE ";
- } else {
- signing_options =
- std::string(" --algorithm ") + avb_algorithm + " --key " + key_path.value() + " ";
- }
- EXPECT_COMMAND(0,
- "avbtool %s"
- " --image %s"
- " --partition_name %s "
- " --partition_size %" PRIu64 " --rollback_index %" PRIu64
- " --salt %s"
- " %s %s",
- add_footer_option.c_str(), image_path.value().c_str(), partition_name.c_str(),
- partition_size, rollback_index, salt.c_str(), signing_options.c_str(),
- additional_options.c_str());
-}
-
-std::string BaseFsAvbTest::InfoImage(const base::FilePath& image_path) {
- base::FilePath tmp_path = test_dir_.Append("info_output.txt");
- EXPECT_COMMAND(0, "avbtool info_image --image %s --output %s", image_path.value().c_str(),
- tmp_path.value().c_str());
- std::string info_data;
- EXPECT_TRUE(base::ReadFileToString(tmp_path, &info_data));
- return info_data;
-}
-
-std::string BaseFsAvbTest::InfoImage(const std::string& file_name) {
- auto iter = vbmeta_images_.find(file_name);
- EXPECT_NE(iter, vbmeta_images_.end()); // ensures file_name is generated before.
- // Gets the image path from iterator->second.path: VBMetaImage.path.
- base::FilePath image_path = iter->second.path;
- return InfoImage(image_path);
-}
-
-base::FilePath BaseFsAvbTest::ExtractPublicKeyAvb(const base::FilePath& key_path) {
- std::string file_name = key_path.RemoveExtension().BaseName().value();
- base::FilePath tmp_path = test_dir_.Append(file_name + "public_key.bin");
- EXPECT_COMMAND(0,
- "avbtool extract_public_key --key %s"
- " --output %s",
- key_path.value().c_str(), tmp_path.value().c_str());
- return tmp_path;
-}
-
-std::string BaseFsAvbTest::ExtractPublicKeyAvbBlob(const base::FilePath& key_path) {
- base::FilePath tmp_path = test_dir_.Append("public_key.bin");
- EXPECT_COMMAND(0,
- "avbtool extract_public_key --key %s"
- " --output %s",
- key_path.value().c_str(), tmp_path.value().c_str());
- std::string key_data;
- EXPECT_TRUE(base::ReadFileToString(tmp_path, &key_data));
- return key_data;
-}
-
-TEST_F(BaseFsAvbTest, GenerateImage) {
- const size_t image_size = 5 * 1024 * 1024;
- base::FilePath boot_path = GenerateImage("boot.img", image_size);
- EXPECT_NE(0U, boot_path.value().size());
-
- // Checks file size is as expected.
- int64_t file_size;
- ASSERT_TRUE(base::GetFileSize(boot_path, &file_size));
- EXPECT_EQ(file_size, image_size);
-
- // Checks file content is as expected.
- std::vector<uint8_t> expected_content;
- expected_content.resize(image_size);
- for (size_t n = 0; n < image_size; n++) {
- expected_content[n] = uint8_t(n);
- }
- std::vector<uint8_t> actual_content;
- actual_content.resize(image_size);
- EXPECT_TRUE(
- base::ReadFile(boot_path, reinterpret_cast<char*>(actual_content.data()), image_size));
- EXPECT_EQ(expected_content, actual_content);
-}
-
-TEST_F(BaseFsAvbTest, GenerateVBMetaImage) {
- GenerateVBMetaImage("vbmeta.img", "SHA256_RSA2048", 0,
- base::FilePath("data/testkey_rsa2048.pem"),
- {}, /* include_descriptor_image_paths */
- {}, /* chain_partitions */
- "--internal_release_string \"unit test\"");
- EXPECT_EQ("5eba9ad4e775645e7eac441a563c200681ae868158d06f6a6cd36d06c07bd781",
- CalcVBMetaDigest("vbmeta.img", "sha256"));
- EXPECT_EQ(
- "Minimum libavb version: 1.0\n"
- "Header Block: 256 bytes\n"
- "Authentication Block: 320 bytes\n"
- "Auxiliary Block: 576 bytes\n"
- "Algorithm: SHA256_RSA2048\n"
- "Rollback Index: 0\n"
- "Flags: 0\n"
- "Release String: 'unit test'\n"
- "Descriptors:\n"
- " (none)\n",
- InfoImage("vbmeta.img"));
-}
-
-TEST_F(BaseFsAvbTest, AddHashFooter) {
- // Generates a raw boot.img
- const size_t image_size = 5 * 1024 * 1024;
- const size_t partition_size = 10 * 1024 * 1024;
- base::FilePath boot_path = GenerateImage("boot.img", image_size);
- EXPECT_NE(0U, boot_path.value().size());
- // Checks file size is as expected.
- int64_t file_size;
- ASSERT_TRUE(base::GetFileSize(boot_path, &file_size));
- EXPECT_EQ(file_size, image_size);
- // Appends AVB Hash Footer.
- AddAvbFooter(boot_path, "hash", "boot", partition_size, "SHA256_RSA4096", 10,
- base::FilePath("data/testkey_rsa4096.pem"), "d00df00d",
- "--internal_release_string \"unit test\"");
- // Extracts boot vbmeta from boot.img into boot-vbmeta.img.
- ExtractVBMetaImage(boot_path, "boot-vbmeta.img");
- EXPECT_EQ(
- "Minimum libavb version: 1.0\n"
- "Header Block: 256 bytes\n"
- "Authentication Block: 576 bytes\n"
- "Auxiliary Block: 1216 bytes\n"
- "Algorithm: SHA256_RSA4096\n"
- "Rollback Index: 10\n"
- "Flags: 0\n"
- "Release String: 'unit test'\n"
- "Descriptors:\n"
- " Hash descriptor:\n"
- " Image Size: 5242880 bytes\n"
- " Hash Algorithm: sha256\n"
- " Partition Name: boot\n"
- " Salt: d00df00d\n"
- " Digest: "
- "222dd01e98284a1fcd7781f85d1392e43a530511a64eff96db197db90ebc4df1\n"
- " Flags: 0\n",
- InfoImage("boot-vbmeta.img"));
-}
-
-TEST_F(BaseFsAvbTest, AddHashtreeFooter) {
- // Generates a raw system.img
- const size_t image_size = 50 * 1024 * 1024;
- const size_t partition_size = 60 * 1024 * 1024;
- base::FilePath system_path = GenerateImage("system.img", image_size);
- EXPECT_NE(0U, system_path.value().size());
- // Checks file size is as expected.
- int64_t file_size;
- ASSERT_TRUE(base::GetFileSize(system_path, &file_size));
- EXPECT_EQ(file_size, image_size);
- // Appends AVB Hashtree Footer.
- AddAvbFooter(system_path, "hashtree", "system", partition_size, "SHA512_RSA8192", 20,
- base::FilePath("data/testkey_rsa8192.pem"), "d00df00d",
- "--internal_release_string \"unit test\"");
- // Extracts system vbmeta from system.img into system-vbmeta.img.
- ExtractVBMetaImage(system_path, "system-vbmeta.img");
- EXPECT_EQ(
- "Minimum libavb version: 1.0\n"
- "Header Block: 256 bytes\n"
- "Authentication Block: 1088 bytes\n"
- "Auxiliary Block: 2304 bytes\n"
- "Algorithm: SHA512_RSA8192\n"
- "Rollback Index: 20\n"
- "Flags: 0\n"
- "Release String: 'unit test'\n"
- "Descriptors:\n"
- " Hashtree descriptor:\n"
- " Version of dm-verity: 1\n"
- " Image Size: 52428800 bytes\n"
- " Tree Offset: 52428800\n"
- " Tree Size: 413696 bytes\n"
- " Data Block Size: 4096 bytes\n"
- " Hash Block Size: 4096 bytes\n"
- " FEC num roots: 2\n"
- " FEC offset: 52842496\n"
- " FEC size: 417792 bytes\n"
- " Hash Algorithm: sha1\n"
- " Partition Name: system\n"
- " Salt: d00df00d\n"
- " Root Digest: d20d40c02298e385ab6d398a61a3b91dc9947d99\n"
- " Flags: 0\n",
- InfoImage("system-vbmeta.img"));
-}
-
-TEST_F(BaseFsAvbTest, GenerateVBMetaImageWithDescriptors) {
- // Generates a raw boot.img
- const size_t boot_image_size = 5 * 1024 * 1024;
- const size_t boot_partition_size = 10 * 1024 * 1024;
- base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
- // Adds AVB Hash Footer.
- AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA4096", 10,
- base::FilePath("data/testkey_rsa4096.pem"), "d00df00d",
- "--internal_release_string \"unit test\"");
-
- // Generates a raw system.img, use a smaller size to speed-up unit test.
- const size_t system_image_size = 10 * 1024 * 1024;
- const size_t system_partition_size = 15 * 1024 * 1024;
- base::FilePath system_path = GenerateImage("system.img", system_image_size);
- // Adds AVB Hashtree Footer.
- AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA8192", 20,
- base::FilePath("data/testkey_rsa8192.pem"), "d00df00d",
- "--internal_release_string \"unit test\"");
-
- // Makes a vbmeta.img including both 'boot' and 'system' descriptors.
- GenerateVBMetaImage("vbmeta.img", "SHA256_RSA2048", 0,
- base::FilePath("data/testkey_rsa2048.pem"),
- {boot_path, system_path}, /* include_descriptor_image_paths */
- {}, /* chain_partitions */
- "--internal_release_string \"unit test\"");
- EXPECT_EQ("a069cbfc30c816cddf3b53f1ad53b7ca5d61a3d93845eb596bbb1b40caa1c62f",
- CalcVBMetaDigest("vbmeta.img", "sha256"));
- EXPECT_EQ(
- "Minimum libavb version: 1.0\n"
- "Header Block: 256 bytes\n"
- "Authentication Block: 320 bytes\n"
- "Auxiliary Block: 960 bytes\n"
- "Algorithm: SHA256_RSA2048\n"
- "Rollback Index: 0\n"
- "Flags: 0\n"
- "Release String: 'unit test'\n"
- "Descriptors:\n"
- " Hash descriptor:\n"
- " Image Size: 5242880 bytes\n"
- " Hash Algorithm: sha256\n"
- " Partition Name: boot\n"
- " Salt: d00df00d\n"
- " Digest: "
- "222dd01e98284a1fcd7781f85d1392e43a530511a64eff96db197db90ebc4df1\n"
- " Flags: 0\n"
- " Hashtree descriptor:\n"
- " Version of dm-verity: 1\n"
- " Image Size: 10485760 bytes\n"
- " Tree Offset: 10485760\n"
- " Tree Size: 86016 bytes\n"
- " Data Block Size: 4096 bytes\n"
- " Hash Block Size: 4096 bytes\n"
- " FEC num roots: 2\n"
- " FEC offset: 10571776\n"
- " FEC size: 90112 bytes\n"
- " Hash Algorithm: sha1\n"
- " Partition Name: system\n"
- " Salt: d00df00d\n"
- " Root Digest: a3d5dd307341393d85de356c384ff543ec1ed81b\n"
- " Flags: 0\n",
- InfoImage("vbmeta.img"));
-}
-
-TEST_F(BaseFsAvbTest, GenerateVBMetaImageWithChainDescriptors) {
- // Generates a raw boot.img
- const size_t boot_image_size = 5 * 1024 * 1024;
- const size_t boot_partition_size = 10 * 1024 * 1024;
- base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
- // Adds AVB Hash Footer.
- AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
- base::FilePath("data/testkey_rsa2048.pem"), "d00df00d",
- "--internal_release_string \"unit test\"");
-
- // Generates a raw system.img, use a smaller size to speed-up unit test.
- const size_t system_image_size = 10 * 1024 * 1024;
- const size_t system_partition_size = 15 * 1024 * 1024;
- base::FilePath system_path = GenerateImage("system.img", system_image_size);
- // Adds AVB Hashtree Footer.
- AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
- base::FilePath("data/testkey_rsa4096.pem"), "d00df00d",
- "--internal_release_string \"unit test\"");
-
- // Make a vbmeta image with chain partitions.
- base::FilePath rsa2048_public_key =
- ExtractPublicKeyAvb(base::FilePath("data/testkey_rsa2048.pem"));
- base::FilePath rsa4096_public_key =
- ExtractPublicKeyAvb(base::FilePath("data/testkey_rsa4096.pem"));
- GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
- base::FilePath("data/testkey_rsa8192.pem"),
- {}, /* include_descriptor_image_paths */
- {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
- {"system", 2, rsa4096_public_key}},
- "--internal_release_string \"unit test\"");
-
- // vbmeta digest calculation includes the chained vbmeta from boot.img and system.img.
- EXPECT_EQ("abbe11b316901f3336e26630f64c4732dadbe14532186ac8640e4141a403721f",
- CalcVBMetaDigest("vbmeta.img", "sha256"));
- EXPECT_EQ(
- "Minimum libavb version: 1.0\n"
- "Header Block: 256 bytes\n"
- "Authentication Block: 1088 bytes\n"
- "Auxiliary Block: 3840 bytes\n"
- "Algorithm: SHA256_RSA8192\n"
- "Rollback Index: 0\n"
- "Flags: 0\n"
- "Release String: 'unit test'\n"
- "Descriptors:\n"
- " Chain Partition descriptor:\n"
- " Partition Name: boot\n"
- " Rollback Index Location: 1\n"
- " Public key (sha1): cdbb77177f731920bbe0a0f94f84d9038ae0617d\n"
- " Chain Partition descriptor:\n"
- " Partition Name: system\n"
- " Rollback Index Location: 2\n"
- " Public key (sha1): 2597c218aae470a130f61162feaae70afd97f011\n",
- InfoImage("vbmeta.img"));
-}
-
-} // namespace fs_avb_host_test
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/fs_mgr/libfs_avb/tests/util_test.cpp b/fs_mgr/libfs_avb/tests/util_test.cpp
new file mode 100644
index 0000000..835e8fd
--- /dev/null
+++ b/fs_mgr/libfs_avb/tests/util_test.cpp
@@ -0,0 +1,211 @@
+/*
+ * 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 <unistd.h>
+#include <future>
+#include <string>
+#include <thread>
+
+#include <base/files/file_util.h>
+
+#include "fs_avb_test_util.h"
+#include "util.h"
+
+// Target functions to test:
+using android::fs_mgr::BytesToHex;
+using android::fs_mgr::HexToBytes;
+using android::fs_mgr::NibbleValue;
+using android::fs_mgr::WaitForFile;
+
+namespace fs_avb_host_test {
+
+TEST(BasicUtilTest, NibbleValue09) {
+ uint8_t value;
+
+ EXPECT_TRUE(NibbleValue('0', &value));
+ EXPECT_EQ(0, value);
+ EXPECT_TRUE(NibbleValue('1', &value));
+ EXPECT_EQ(1, value);
+ EXPECT_TRUE(NibbleValue('2', &value));
+ EXPECT_EQ(2, value);
+ EXPECT_TRUE(NibbleValue('3', &value));
+ EXPECT_EQ(3, value);
+ EXPECT_TRUE(NibbleValue('4', &value));
+ EXPECT_EQ(4, value);
+ EXPECT_TRUE(NibbleValue('5', &value));
+ EXPECT_EQ(5, value);
+ EXPECT_TRUE(NibbleValue('6', &value));
+ EXPECT_EQ(6, value);
+ EXPECT_TRUE(NibbleValue('7', &value));
+ EXPECT_EQ(7, value);
+ EXPECT_TRUE(NibbleValue('8', &value));
+ EXPECT_EQ(8, value);
+ EXPECT_TRUE(NibbleValue('9', &value));
+ EXPECT_EQ(9, value);
+}
+
+TEST(BasicUtilTest, NibbleValueAF) {
+ uint8_t value;
+
+ EXPECT_TRUE(NibbleValue('a', &value));
+ EXPECT_EQ(10, value);
+ EXPECT_TRUE(NibbleValue('b', &value));
+ EXPECT_EQ(11, value);
+ EXPECT_TRUE(NibbleValue('c', &value));
+ EXPECT_EQ(12, value);
+ EXPECT_TRUE(NibbleValue('d', &value));
+ EXPECT_EQ(13, value);
+ EXPECT_TRUE(NibbleValue('e', &value));
+ EXPECT_EQ(14, value);
+ EXPECT_TRUE(NibbleValue('f', &value));
+ EXPECT_EQ(15, value);
+
+ EXPECT_TRUE(NibbleValue('A', &value));
+ EXPECT_EQ(10, value);
+ EXPECT_TRUE(NibbleValue('B', &value));
+ EXPECT_EQ(11, value);
+ EXPECT_TRUE(NibbleValue('C', &value));
+ EXPECT_EQ(12, value);
+ EXPECT_TRUE(NibbleValue('D', &value));
+ EXPECT_EQ(13, value);
+ EXPECT_TRUE(NibbleValue('E', &value));
+ EXPECT_EQ(14, value);
+ EXPECT_TRUE(NibbleValue('F', &value));
+ EXPECT_EQ(15, value);
+}
+
+TEST(BasicUtilTest, NibbleValueInvalid) {
+ uint8_t value;
+
+ EXPECT_FALSE(NibbleValue('G', &value));
+ EXPECT_FALSE(NibbleValue('H', &value));
+ EXPECT_FALSE(NibbleValue('I', &value));
+ EXPECT_FALSE(NibbleValue('x', &value));
+ EXPECT_FALSE(NibbleValue('y', &value));
+ EXPECT_FALSE(NibbleValue('z', &value));
+}
+
+TEST(BasicUtilTest, HexToBytes) {
+ std::string hex = "000102030405060708090A0B0C0D0E0F";
+ uint8_t bytes[16];
+
+ EXPECT_TRUE(HexToBytes((uint8_t*)bytes, sizeof(bytes), hex));
+ for (size_t i = 0; i < sizeof(bytes); i++) {
+ EXPECT_EQ(i, bytes[i]);
+ }
+}
+
+TEST(BasicUtilTest, HexToBytes2) {
+ std::string hex = "101112131415161718191A1B1C1D1E1F";
+ uint8_t bytes[16];
+
+ EXPECT_TRUE(HexToBytes((uint8_t*)bytes, sizeof(bytes), hex));
+ for (size_t i = 0; i < sizeof(bytes); i++) {
+ EXPECT_EQ(16 + i, bytes[i]);
+ }
+}
+
+TEST(BasicUtilTest, BytesToHex) {
+ const uint8_t bytes[16]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+
+ EXPECT_EQ("0102", BytesToHex((uint8_t*)bytes, 2));
+ EXPECT_EQ("01020304", BytesToHex((uint8_t*)bytes, 4));
+ EXPECT_EQ("0102030405060708", BytesToHex((uint8_t*)bytes, 8));
+ EXPECT_EQ("0102030405060708090a0b0c0d0e0f10", BytesToHex((uint8_t*)bytes, 16));
+
+ EXPECT_EQ("01", BytesToHex((uint8_t*)bytes, 1));
+ EXPECT_EQ("010203", BytesToHex((uint8_t*)bytes, 3));
+ EXPECT_EQ("0102030405", BytesToHex((uint8_t*)bytes, 5));
+}
+
+TEST(BasicUtilTest, HexToBytesInValidOddLenHex) {
+ std::string hex = "12345";
+ uint8_t bytes[16];
+
+ EXPECT_FALSE(HexToBytes((uint8_t*)bytes, sizeof(bytes), hex));
+}
+
+TEST(BasicUtilTest, HexToBytesInsufficientByteLen) {
+ std::string hex = "101112131415161718191A1B1C1D1E1F";
+ uint8_t bytes[8];
+
+ EXPECT_FALSE(HexToBytes((uint8_t*)bytes, sizeof(bytes), hex));
+}
+
+TEST(BasicUtilTest, WaitForFile) {
+ // Gets system tmp dir.
+ base::FilePath tmp_dir;
+ ASSERT_TRUE(GetTempDir(&tmp_dir));
+
+ // Waits this path.
+ base::FilePath wait_path = tmp_dir.Append("libfs_avb-test-exist-dir");
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+
+ EXPECT_TRUE(base::CreateDirectory(wait_path));
+ EXPECT_TRUE(WaitForFile(wait_path.value(), 1s));
+
+ // Removes the wait_path.
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+}
+
+TEST(BasicUtilTest, WaitForFileNonExist) {
+ base::FilePath wait_path("/path/not/exist");
+ EXPECT_FALSE(WaitForFile(wait_path.value(), 200ms));
+}
+
+TEST(BasicUtilTest, WaitForFileDeferCreation) {
+ // Gets system tmp dir.
+ base::FilePath tmp_dir;
+ ASSERT_TRUE(GetTempDir(&tmp_dir));
+
+ // Waits this path.
+ base::FilePath wait_path = tmp_dir.Append("libfs_avb-test-exist-dir");
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+ auto wait_file = std::async(WaitForFile, wait_path.value(), 500ms);
+
+ // Sleeps 100ms before creating the wait_path.
+ std::this_thread::sleep_for(100ms);
+ EXPECT_TRUE(base::CreateDirectory(wait_path));
+
+ // Checks WaitForFile() returns success.
+ EXPECT_TRUE(wait_file.get());
+
+ // Removes the wait_path.
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+}
+
+TEST(BasicUtilTest, WaitForFileDeferCreationFailure) {
+ // Gets system tmp dir.
+ base::FilePath tmp_dir;
+ ASSERT_TRUE(GetTempDir(&tmp_dir));
+
+ // Waits this path.
+ base::FilePath wait_path = tmp_dir.Append("libfs_avb-test-exist-dir");
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+ auto wait_file = std::async(WaitForFile, wait_path.value(), 50ms);
+
+ // Sleeps 100ms before creating the wait_path.
+ std::this_thread::sleep_for(100ms);
+ EXPECT_TRUE(base::CreateDirectory(wait_path));
+
+ // Checks WaitForFile() returns failure, because it only waits 50ms.
+ EXPECT_FALSE(wait_file.get());
+
+ // Removes the wait_path.
+ ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */));
+}
+
+} // namespace fs_avb_host_test
diff --git a/fs_mgr/libfs_avb/util.cpp b/fs_mgr/libfs_avb/util.cpp
new file mode 100644
index 0000000..17d47d9
--- /dev/null
+++ b/fs_mgr/libfs_avb/util.cpp
@@ -0,0 +1,120 @@
+/*
+ * 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 "util.h"
+
+#include <sys/ioctl.h>
+#include <thread>
+
+#include <android-base/unique_fd.h>
+#include <linux/fs.h>
+
+namespace android {
+namespace fs_mgr {
+
+bool NibbleValue(const char& c, uint8_t* value) {
+ CHECK(value != nullptr);
+
+ switch (c) {
+ case '0' ... '9':
+ *value = c - '0';
+ break;
+ case 'a' ... 'f':
+ *value = c - 'a' + 10;
+ break;
+ case 'A' ... 'F':
+ *value = c - 'A' + 10;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool HexToBytes(uint8_t* bytes, size_t bytes_len, const std::string& hex) {
+ CHECK(bytes != nullptr);
+
+ if (hex.size() % 2 != 0) {
+ return false;
+ }
+ if (hex.size() / 2 > bytes_len) {
+ return false;
+ }
+ for (size_t i = 0, j = 0, n = hex.size(); i < n; i += 2, ++j) {
+ uint8_t high;
+ if (!NibbleValue(hex[i], &high)) {
+ return false;
+ }
+ uint8_t low;
+ if (!NibbleValue(hex[i + 1], &low)) {
+ return false;
+ }
+ bytes[j] = (high << 4) | low;
+ }
+ return true;
+}
+
+std::string BytesToHex(const uint8_t* bytes, size_t bytes_len) {
+ CHECK(bytes != nullptr);
+
+ static const char* hex_digits = "0123456789abcdef";
+ std::string hex;
+
+ for (size_t i = 0; i < bytes_len; i++) {
+ hex.push_back(hex_digits[(bytes[i] & 0xF0) >> 4]);
+ hex.push_back(hex_digits[bytes[i] & 0x0F]);
+ }
+ return hex;
+}
+
+bool WaitForFile(const std::string& filename, const std::chrono::milliseconds relative_timeout) {
+ auto start_time = std::chrono::steady_clock::now();
+
+ while (true) {
+ if (0 == access(filename.c_str(), F_OK) || errno != ENOENT) {
+ return true;
+ }
+
+ std::this_thread::sleep_for(50ms);
+
+ auto now = std::chrono::steady_clock::now();
+ auto time_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
+ if (time_elapsed > relative_timeout) return false;
+ }
+}
+
+bool IsDeviceUnlocked() {
+ std::string verified_boot_state;
+
+ if (fs_mgr_get_boot_config("verifiedbootstate", &verified_boot_state)) {
+ return verified_boot_state == "orange";
+ }
+ return false;
+}
+
+bool SetBlockDeviceReadOnly(const std::string& blockdev) {
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blockdev.c_str(), O_RDONLY | O_CLOEXEC)));
+ if (fd < 0) {
+ return false;
+ }
+
+ int ON = 1;
+ return ioctl(fd, BLKROSET, &ON) == 0;
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/libfs_avb/util.h b/fs_mgr/libfs_avb/util.h
new file mode 100644
index 0000000..cb861f4
--- /dev/null
+++ b/fs_mgr/libfs_avb/util.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <chrono>
+#include <string>
+
+#ifdef HOST_TEST
+#include <base/logging.h>
+#else
+#include <android-base/logging.h>
+#endif
+
+#define FS_AVB_TAG "[libfs_avb]"
+
+// Logs a message to kernel
+#define LINFO LOG(INFO) << FS_AVB_TAG
+#define LWARNING LOG(WARNING) << FS_AVB_TAG
+#define LERROR LOG(ERROR) << FS_AVB_TAG
+#define LFATAL LOG(FATAL) << FS_AVB_TAG
+
+// Logs a message with strerror(errno) at the end
+#define PINFO PLOG(INFO) << FS_AVB_TAG
+#define PWARNING PLOG(WARNING) << FS_AVB_TAG
+#define PERROR PLOG(ERROR) << FS_AVB_TAG
+#define PFATAL PLOG(FATAL) << FS_AVB_TAG
+
+extern bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val);
+
+using namespace std::chrono_literals;
+
+namespace android {
+namespace fs_mgr {
+
+bool NibbleValue(const char& c, uint8_t* value);
+
+bool HexToBytes(uint8_t* bytes, size_t bytes_len, const std::string& hex);
+
+std::string BytesToHex(const uint8_t* bytes, size_t bytes_len);
+
+bool WaitForFile(const std::string& filename, const std::chrono::milliseconds relative_timeout);
+
+bool IsDeviceUnlocked();
+
+bool SetBlockDeviceReadOnly(const std::string& blockdev);
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/utility.cpp b/fs_mgr/liblp/utility.cpp
index 9ccabe9..ecf94a4 100644
--- a/fs_mgr/liblp/utility.cpp
+++ b/fs_mgr/liblp/utility.cpp
@@ -19,6 +19,11 @@
#include <sys/stat.h>
#include <unistd.h>
+#if defined(__linux__)
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#endif
+
#include <android-base/file.h>
#include <ext4_utils/ext4_utils.h>
#include <openssl/sha.h>
@@ -155,5 +160,16 @@
return true;
}
+bool SetBlockReadonly(int fd, bool readonly) {
+#if defined(__linux__)
+ int val = readonly;
+ return ioctl(fd, BLKROSET, &val) == 0;
+#else
+ (void)fd;
+ (void)readonly;
+ return true;
+#endif
+}
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/utility.h b/fs_mgr/liblp/utility.h
index 8b70919..e8b2ca9 100644
--- a/fs_mgr/liblp/utility.h
+++ b/fs_mgr/liblp/utility.h
@@ -29,6 +29,7 @@
#define LWARN LOG(WARNING) << LP_TAG
#define LINFO LOG(INFO) << LP_TAG
#define LERROR LOG(ERROR) << LP_TAG
+#define PWARNING PLOG(WARNING) << LP_TAG
#define PERROR PLOG(ERROR) << LP_TAG
namespace android {
@@ -88,6 +89,9 @@
bool UpdateBlockDevicePartitionName(LpMetadataBlockDevice* device, const std::string& name);
bool UpdatePartitionGroupName(LpMetadataPartitionGroup* group, const std::string& name);
+// Call BLKROSET ioctl on fd so that fd is readonly / read-writable.
+bool SetBlockReadonly(int fd, bool readonly);
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index 454258b..54a1883 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -259,6 +259,12 @@
return false;
}
+ // On retrofit devices, super_partition is system_other and might be set to readonly by
+ // fs_mgr_set_blk_ro(). Unset readonly so that fd can be written to.
+ if (!SetBlockReadonly(fd.get(), false)) {
+ PWARNING << __PRETTY_FUNCTION__ << " BLKROSET 0 failed: " << super_partition;
+ }
+
// Write zeroes to the first block.
std::string zeroes(LP_PARTITION_RESERVED_BYTES, 0);
if (SeekFile64(fd, 0, SEEK_SET) < 0) {
diff --git a/init/Android.bp b/init/Android.bp
index e7b8516..c920dc2 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -85,6 +85,7 @@
"libselinux",
"libutils",
],
+ bootstrap: true,
}
cc_library_static {
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 7fd4e27..52828c0 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -100,6 +100,9 @@
}
static Result<Success> do_class_start(const BuiltinArguments& args) {
+ // Do not start a class if it has a property persist.dont_start_class.CLASS set to 1.
+ if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false))
+ return Success();
// Starting a class does not start services which are explicitly disabled.
// They must be started individually.
for (const auto& service : ServiceList::GetInstance()) {
@@ -124,6 +127,9 @@
}
static Result<Success> do_class_restart(const BuiltinArguments& args) {
+ // Do not restart a class if it has a property persist.dont_start_class.CLASS set to 1.
+ if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false))
+ return Success();
ForEachServiceInClass(args[1], &Service::Restart);
return Success();
}
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index b5ff658..71fe401 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -414,16 +414,32 @@
return entry.mount_point == "/system";
});
- if (system_partition != fstab_.end()) {
- if (!MountPartition(&(*system_partition))) {
- return false;
+ if (system_partition == fstab_.end()) return true;
+
+ bool mounted = false;
+ bool no_fail = false;
+ for (auto it = system_partition; it != fstab_.end();) {
+ if (it->mount_point != "/system") {
+ break;
}
-
- SwitchRoot((*system_partition).mount_point);
-
- fstab_.erase(system_partition);
+ no_fail |= (it->fs_mgr_flags).no_fail;
+ if (MountPartition(&(*it))) {
+ mounted = true;
+ SwitchRoot("/system");
+ break;
+ }
+ it++;
}
+ if (!mounted && !no_fail) {
+ LOG(ERROR) << "Failed to mount /system";
+ return false;
+ }
+
+ auto it = std::remove_if(fstab_.begin(), fstab_.end(),
+ [](const auto& entry) { return entry.mount_point == "/system"; });
+ fstab_.erase(it, fstab_.end());
+
return true;
}
@@ -444,14 +460,12 @@
if (skip_mount_point.empty()) {
continue;
}
- auto removing_entry =
- std::find_if(fstab_.begin(), fstab_.end(), [&skip_mount_point](const auto& entry) {
- return entry.mount_point == skip_mount_point;
- });
- if (removing_entry != fstab_.end()) {
- fstab_.erase(removing_entry);
- LOG(INFO) << "Skip mounting partition: " << skip_mount_point;
- }
+ auto it = std::remove_if(fstab_.begin(), fstab_.end(),
+ [&skip_mount_point](const auto& entry) {
+ return entry.mount_point == skip_mount_point;
+ });
+ fstab_.erase(it, fstab_.end());
+ LOG(INFO) << "Skip mounting partition: " << skip_mount_point;
}
return true;
@@ -462,8 +476,21 @@
if (!TrySkipMountingPartitions()) return false;
- for (auto& fstab_entry : fstab_) {
- if (!MountPartition(&fstab_entry) && !fstab_entry.fs_mgr_flags.no_fail) {
+ for (auto it = fstab_.begin(); it != fstab_.end();) {
+ bool mounted = false;
+ bool no_fail = false;
+ auto start_mount_point = it->mount_point;
+ do {
+ no_fail |= (it->fs_mgr_flags).no_fail;
+ if (!mounted)
+ mounted = MountPartition(&(*it));
+ else
+ LOG(INFO) << "Skip already-mounted partition: " << start_mount_point;
+ it++;
+ } while (it != fstab_.end() && it->mount_point == start_mount_point);
+
+ if (!mounted && !no_fail) {
+ LOG(ERROR) << start_mount_point << " mounted unsuccessfully but it is required!";
return false;
}
}
diff --git a/init/main.cpp b/init/main.cpp
index 868c409..2ce46ef 100644
--- a/init/main.cpp
+++ b/init/main.cpp
@@ -57,27 +57,22 @@
return ueventd_main(argc, argv);
}
- if (argc < 2) {
- return FirstStageMain(argc, argv);
+ if (argc > 1) {
+ if (!strcmp(argv[1], "subcontext")) {
+ android::base::InitLogging(argv, &android::base::KernelLogger);
+ const BuiltinFunctionMap function_map;
+
+ return SubcontextMain(argc, argv, &function_map);
+ }
+
+ if (!strcmp(argv[1], "selinux_setup")) {
+ return SetupSelinux(argv);
+ }
+
+ if (!strcmp(argv[1], "second_stage")) {
+ return SecondStageMain(argc, argv);
+ }
}
- if (!strcmp(argv[1], "subcontext")) {
- android::base::InitLogging(argv, &android::base::KernelLogger);
- const BuiltinFunctionMap function_map;
-
- return SubcontextMain(argc, argv, &function_map);
- }
-
- if (!strcmp(argv[1], "selinux_setup")) {
- return SetupSelinux(argv);
- }
-
- if (!strcmp(argv[1], "second_stage")) {
- return SecondStageMain(argc, argv);
- }
-
- android::base::InitLogging(argv, &android::base::KernelLogger);
-
- LOG(ERROR) << "Unknown argument passed to init '" << argv[1] << "'";
- return 1;
+ return FirstStageMain(argc, argv);
}
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 04ca207..e4da52c 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -432,24 +432,6 @@
selinux_android_restorecon("/dev/urandom", 0);
selinux_android_restorecon("/dev/__properties__", 0);
- selinux_android_restorecon("/plat_file_contexts", 0);
- selinux_android_restorecon("/nonplat_file_contexts", 0);
- selinux_android_restorecon("/vendor_file_contexts", 0);
- selinux_android_restorecon("/plat_property_contexts", 0);
- selinux_android_restorecon("/nonplat_property_contexts", 0);
- selinux_android_restorecon("/vendor_property_contexts", 0);
- selinux_android_restorecon("/plat_seapp_contexts", 0);
- selinux_android_restorecon("/nonplat_seapp_contexts", 0);
- selinux_android_restorecon("/vendor_seapp_contexts", 0);
- selinux_android_restorecon("/plat_service_contexts", 0);
- selinux_android_restorecon("/nonplat_service_contexts", 0);
- selinux_android_restorecon("/vendor_service_contexts", 0);
- selinux_android_restorecon("/plat_hwservice_contexts", 0);
- selinux_android_restorecon("/nonplat_hwservice_contexts", 0);
- selinux_android_restorecon("/vendor_hwservice_contexts", 0);
- selinux_android_restorecon("/sepolicy", 0);
- selinux_android_restorecon("/vndservice_contexts", 0);
-
selinux_android_restorecon("/dev/block", SELINUX_ANDROID_RESTORECON_RECURSE);
selinux_android_restorecon("/dev/device-mapper", 0);
diff --git a/liblog/.clang-format b/liblog/.clang-format
deleted file mode 100644
index 9db87a8..0000000
--- a/liblog/.clang-format
+++ /dev/null
@@ -1,9 +0,0 @@
-BasedOnStyle: Google
-AllowShortFunctionsOnASingleLine: false
-
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-PointerAlignment: Left
-PenaltyExcessCharacter: 32
-
-Cpp11BracedListStyle: false
diff --git a/liblog/.clang-format b/liblog/.clang-format
new file mode 120000
index 0000000..fd0645f
--- /dev/null
+++ b/liblog/.clang-format
@@ -0,0 +1 @@
+../.clang-format-2
\ No newline at end of file
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 4a165a0..619a94b 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -17,7 +17,6 @@
liblog_sources = [
"config_read.c",
"config_write.c",
- "local_logger.c",
"log_event_list.c",
"log_event_write.c",
"log_ratelimit.cpp",
diff --git a/liblog/README b/liblog/README
deleted file mode 100644
index 5a845be..0000000
--- a/liblog/README
+++ /dev/null
@@ -1,209 +0,0 @@
-LIBLOG(3) Android Internal NDK Programming Manual LIBLOG(3)
-
-
-
-NAME
- liblog - Android Internal NDK logger interfaces
-
-SYNOPSIS
- /*
- * Please limit to 24 characters for runtime is loggable,
- * 16 characters for persist is loggable, and logcat pretty
- * alignment with limit of 7 characters.
- */
- #define LOG_TAG "yourtag"
- #include <log/log.h>
-
- ALOG(android_priority, tag, format, ...)
- IF_ALOG(android_priority, tag)
- LOG_PRI(priority, tag, format, ...)
- LOG_PRI_VA(priority, tag, format, args)
- #define LOG_TAG NULL
- ALOGV(format, ...)
- SLOGV(format, ...)
- RLOGV(format, ...)
- ALOGV_IF(cond, format, ...)
- SLOGV_IF(cond, format, ...)
- RLOGV_IF(cond, format, ...)
- IF_ALOGC()
- ALOGD(format, ...)
- SLOGD(format, ...)
- RLOGD(format, ...)
- ALOGD_IF(cond, format, ...)
- SLOGD_IF(cond, format, ...)
- RLOGD_IF(cond, format, ...)
- IF_ALOGD()
- ALOGI(format, ...)
- SLOGI(format, ...)
- RLOGI(format, ...)
- ALOGI_IF(cond, format, ...)
- SLOGI_IF(cond, format, ...)
- RLOGI_IF(cond, format, ...)
- IF_ALOGI()
- ALOGW(format, ...)
- SLOGW(format, ...)
- RLOGW(format, ...)
- ALOGW_IF(cond, format, ...)
- SLOGW_IF(cond, format, ...)
- RLOGW_IF(cond, format, ...)
- IF_ALOGW()
- ALOGE(format, ...)
- SLOGE(format, ...)
- RLOGE(format, ...)
- ALOGE_IF(cond, format, ...)
- SLOGE_IF(cond, format, ...)
- RLOGE_IF(cond, format, ...)
- IF_ALOGE()
- LOG_FATAL(format, ...)
- LOG_ALWAYS_FATAL(format, ...)
- LOG_FATAL_IF(cond, format, ...)
- LOG_ALWAYS_FATAL_IF(cond, format, ...)
- ALOG_ASSERT(cond, format, ...)
- LOG_EVENT_INT(tag, value)
- LOG_EVENT_LONG(tag, value)
-
- clockid_t android_log_clockid()
-
- log_id_t android_logger_get_id(struct logger *logger)
- int android_logger_clear(struct logger *logger)
- int android_logger_get_log_size(struct logger *logger)
- int android_logger_get_log_readable_size(struct logger *logger)
- int android_logger_get_log_version(struct logger *logger)
-
- struct logger_list *android_logger_list_alloc(int mode,
- unsigned int tail,
- pid_t pid)
- struct logger *android_logger_open(struct logger_list *logger_list,
- log_id_t id)
- struct logger_list *android_logger_list_open(log_id_t id, int mode,
- unsigned int tail,
- pid_t pid)
- int android_logger_list_read(struct logger_list *logger_list,
- struct log_msg *log_msg)
- void android_logger_list_free(struct logger_list *logger_list)
-
- log_id_t android_name_to_log_id(const char *logName)
- const char *android_log_id_to_name(log_id_t log_id)
-
- android_log_context create_android_logger(uint32_t tag)
-
- int android_log_write_list_begin(android_log_context ctx)
- int android_log_write_list_end(android_log_context ctx)
-
- int android_log_write_int32(android_log_context ctx, int32_t value)
- int android_log_write_int64(android_log_context ctx, int64_t value)
- int android_log_write_string8(android_log_context ctx,
- const char *value)
- int android_log_write_string8_len(android_log_context ctx,
- const char *value, size_t maxlen)
- int android_log_write_float32(android_log_context ctx, float value)
-
- int android_log_write_list(android_log_context ctx,
- log_id_t id = LOG_ID_EVENTS)
-
- android_log_context create_android_log_parser(const char *msg,
- size_t len)
- android_log_list_element android_log_read_next(android_log_context ctx)
- android_log_list_element android_log_peek_next(android_log_context ctx)
-
- int android_log_destroy(android_log_context *ctx)
-
- #include <log/log_transport.h>
-
- int android_set_log_transport(int transport_flag)
- int android_get_log_transport()
-
- Link with -llog
-
-DESCRIPTION
- liblog represents an interface to the volatile Android Logging system
- for NDK (Native) applications and libraries. Interfaces for either
- writing or reading logs. The log buffers are divided up in Main, Sys‐
- tem, Radio and Events sub-logs.
-
- The logging interfaces are a series of macros, all of which can be
- overridden individually in order to control the verbosity of the appli‐
- cation or library. [ASR]LOG[VDIWE] calls are used to log to BAsic,
- System or Radio sub-logs in either the Verbose, Debug, Info, Warning or
- Error priorities. [ASR]LOG[VDIWE]_IF calls are used to perform thus
- based on a condition being true. IF_ALOG[VDIWE] calls are true if the
- current LOG_TAG is enabled at the specified priority. LOG_ALWAYS_FATAL
- is used to ALOG a message, then kill the process. LOG_FATAL call is a
- variant of LOG_ALWAYS_FATAL, only enabled in engineering, and not
- release builds. ALOG_ASSERT is used to ALOG a message if the condition
- is false; the condition is part of the logged message.
- LOG_EVENT_(INT|LONG) is used to drop binary content into the Events
- sub-log.
-
- The log reading interfaces permit opening the logs either singly or
- multiply, retrieving a log entry at a time in time sorted order,
- optionally limited to a specific pid and tail of the log(s) and finally
- a call closing the logs. A single log can be opened with android_log‐
- ger_list_open; or multiple logs can be opened with android_log‐
- ger_list_alloc, calling in turn the android_logger_open for each log
- id. Each entry can be retrieved with android_logger_list_read. The
- log(s) can be closed with android_logger_list_free. The logs should be
- opened with an ANDROID_LOG_RDONLY mode. ANDROID_LOG_NONBLOCK mode
- will report when the log reading is done with an EAGAIN error return
- code, otherwise the android_logger_list_read call will block for new
- entries.
-
- The ANDROID_LOG_WRAP mode flag to the android_logger_list_alloc_time
- signals logd to quiesce the reader until the buffer is about to prune
- at the start time then proceed to dumping content.
-
- The ANDROID_LOG_PSTORE mode flag to the android_logger_open is used to
- switch from the active logs to the persistent logs from before the last
- reboot.
-
- The value returned by android_logger_open can be used as a parameter to
- the android_logger_clear function to empty the sub-log. It is recom‐
- mended to only open log ANDROID_LOG_WRONLY in that case.
-
- The value returned by android_logger_open can be used as a parameter to
- the android_logger_get_log_(size|readable_size|version) to retrieve the
- sub-log maximum size, readable size and log buffer format protocol ver‐
- sion respectively. android_logger_get_id returns the id that was used
- when opening the sub-log. It is recommended to open the log
- ANDROID_LOG_RDONLY in these cases.
-
- android_set_log_transport() selects transport filters. Argument is
- either LOGGER_DEFAULT, LOGGER_LOGD, LOGGER_NULL or LOGGER_LOCAL. Log to
- logger daemon for default or logd, drop contents on floor, or log into
- local memory respectively. Both android_set_log_transport()
- and android_get_log_transport() return the current transport mask, or
- a negative errno for any problems.
-
-ERRORS
- If messages fail, a negative error code will be returned to the caller.
-
- The -ENOTCONN return code indicates that the logger daemon is stopped.
-
- The -EBADF return code indicates that the log access point can not be
- opened, or the log buffer id is out of range.
-
- For the -EAGAIN return code, this means that the logging message was
- temporarily backed-up either because of Denial Of Service (DOS) logging
- pressure from some chatty application or service in the Android system,
- or if too small of a value is set in /proc/sys/net/unix/max_dgram_qlen.
- To aid in diagnosing the occurence of this, a binary event from liblog
- will be sent to the log daemon once a new message can get through
- indicating how many messages were dropped as a result. Please take
- action to resolve the structural problems at the source.
-
- It is generally not advised for the caller to retry the -EAGAIN return
- code as this will only make the problem(s) worse and cause your
- application to temporarily drop to the logger daemon priority, BATCH
- scheduling policy and background task cgroup. If you require a group of
- messages to be passed atomically, merge them into one message with
- embedded newlines to the maximum length LOGGER_ENTRY_MAX_PAYLOAD.
-
- Other return codes from writing operation can be returned. Since the
- library retries on EINTR, -EINTR should never be returned.
-
-SEE ALSO
- syslogd(8), klogd, auditd(8)
-
-
-
- 08 Feb 2017 LIBLOG(3)
diff --git a/liblog/README.md b/liblog/README.md
new file mode 100644
index 0000000..98bee9f
--- /dev/null
+++ b/liblog/README.md
@@ -0,0 +1,176 @@
+Android liblog
+--------------
+
+Public Functions and Macros
+---------------------------
+
+ /*
+ * Please limit to 24 characters for runtime is loggable,
+ * 16 characters for persist is loggable, and logcat pretty
+ * alignment with limit of 7 characters.
+ */
+ #define LOG_TAG "yourtag"
+ #include <log/log.h>
+
+ ALOG(android_priority, tag, format, ...)
+ IF_ALOG(android_priority, tag)
+ LOG_PRI(priority, tag, format, ...)
+ LOG_PRI_VA(priority, tag, format, args)
+ #define LOG_TAG NULL
+ ALOGV(format, ...)
+ SLOGV(format, ...)
+ RLOGV(format, ...)
+ ALOGV_IF(cond, format, ...)
+ SLOGV_IF(cond, format, ...)
+ RLOGV_IF(cond, format, ...)
+ IF_ALOGC()
+ ALOGD(format, ...)
+ SLOGD(format, ...)
+ RLOGD(format, ...)
+ ALOGD_IF(cond, format, ...)
+ SLOGD_IF(cond, format, ...)
+ RLOGD_IF(cond, format, ...)
+ IF_ALOGD()
+ ALOGI(format, ...)
+ SLOGI(format, ...)
+ RLOGI(format, ...)
+ ALOGI_IF(cond, format, ...)
+ SLOGI_IF(cond, format, ...)
+ RLOGI_IF(cond, format, ...)
+ IF_ALOGI()
+ ALOGW(format, ...)
+ SLOGW(format, ...)
+ RLOGW(format, ...)
+ ALOGW_IF(cond, format, ...)
+ SLOGW_IF(cond, format, ...)
+ RLOGW_IF(cond, format, ...)
+ IF_ALOGW()
+ ALOGE(format, ...)
+ SLOGE(format, ...)
+ RLOGE(format, ...)
+ ALOGE_IF(cond, format, ...)
+ SLOGE_IF(cond, format, ...)
+ RLOGE_IF(cond, format, ...)
+ IF_ALOGE()
+ LOG_FATAL(format, ...)
+ LOG_ALWAYS_FATAL(format, ...)
+ LOG_FATAL_IF(cond, format, ...)
+ LOG_ALWAYS_FATAL_IF(cond, format, ...)
+ ALOG_ASSERT(cond, format, ...)
+ LOG_EVENT_INT(tag, value)
+ LOG_EVENT_LONG(tag, value)
+
+ clockid_t android_log_clockid()
+
+ log_id_t android_logger_get_id(struct logger *logger)
+ int android_logger_clear(struct logger *logger)
+ int android_logger_get_log_size(struct logger *logger)
+ int android_logger_get_log_readable_size(struct logger *logger)
+ int android_logger_get_log_version(struct logger *logger)
+
+ struct logger_list *android_logger_list_alloc(int mode, unsigned int tail, pid_t pid)
+ struct logger *android_logger_open(struct logger_list *logger_list, log_id_t id)
+ struct logger_list *android_logger_list_open(log_id_t id, int mode, unsigned int tail, pid_t pid)
+ int android_logger_list_read(struct logger_list *logger_list, struct log_msg *log_msg)
+ void android_logger_list_free(struct logger_list *logger_list)
+
+ log_id_t android_name_to_log_id(const char *logName)
+ const char *android_log_id_to_name(log_id_t log_id)
+
+ android_log_context create_android_logger(uint32_t tag)
+
+ int android_log_write_list_begin(android_log_context ctx)
+ int android_log_write_list_end(android_log_context ctx)
+
+ int android_log_write_int32(android_log_context ctx, int32_t value)
+ int android_log_write_int64(android_log_context ctx, int64_t value)
+ int android_log_write_string8(android_log_context ctx, const char *value)
+ int android_log_write_string8_len(android_log_context ctx, const char *value, size_t maxlen)
+ int android_log_write_float32(android_log_context ctx, float value)
+
+ int android_log_write_list(android_log_context ctx, log_id_t id = LOG_ID_EVENTS)
+
+ android_log_context create_android_log_parser(const char *msg, size_t len)
+ android_log_list_element android_log_read_next(android_log_context ctx)
+ android_log_list_element android_log_peek_next(android_log_context ctx)
+
+ int android_log_destroy(android_log_context *ctx)
+
+ #include <log/log_transport.h>
+
+ int android_set_log_transport(int transport_flag)
+ int android_get_log_transport()
+
+Description
+-----------
+
+liblog represents an interface to the volatile Android Logging system for NDK (Native) applications
+and libraries. Interfaces for either writing or reading logs. The log buffers are divided up in
+Main, System, Radio and Events sub-logs.
+
+The logging interfaces are a series of macros, all of which can be overridden individually in order
+to control the verbosity of the application or library. `[ASR]LOG[VDIWE]` calls are used to log to
+BAsic, System or Radio sub-logs in either the Verbose, Debug, Info, Warning or Error priorities.
+`[ASR]LOG[VDIWE]_IF` calls are used to perform thus based on a condition being true.
+`IF_ALOG[VDIWE]` calls are true if the current `LOG_TAG` is enabled at the specified priority.
+`LOG_ALWAYS_FATAL` is used to `ALOG` a message, then kill the process. `LOG_FATAL` call is a
+variant of `LOG_ALWAYS_FATAL`, only enabled in engineering, and not release builds. `ALOG_ASSERT`
+is used to `ALOG` a message if the condition is false; the condition is part of the logged message.
+`LOG_EVENT_(INT|LONG)` is used to drop binary content into the Events sub-log.
+
+The log reading interfaces permit opening the logs either singly or multiply, retrieving a log entry
+at a time in time sorted order, optionally limited to a specific pid and tail of the log(s) and
+finally a call closing the logs. A single log can be opened with `android_logger_list_open()`; or
+multiple logs can be opened with `android_logger_list_alloc()`, calling in turn the
+`android_logger_open()` for each log id. Each entry can be retrieved with
+`android_logger_list_read()`. The log(s) can be closed with `android_logger_list_free()`. The logs
+should be opened with an `ANDROID_LOG_RDONLY` mode. `ANDROID_LOG_NONBLOCK` mode will report when
+the log reading is done with an `EAGAIN` error return code, otherwise the
+`android_logger_list_read()` call will block for new entries.
+
+The `ANDROID_LOG_WRAP` mode flag to the `android_logger_list_alloc_time()` signals logd to quiesce
+the reader until the buffer is about to prune at the start time then proceed to dumping content.
+
+The `ANDROID_LOG_PSTORE` mode flag to the `android_logger_open()` is used to switch from the active
+logs to the persistent logs from before the last reboot.
+
+The value returned by `android_logger_open()` can be used as a parameter to the
+`android_logger_clear()` function to empty the sub-log. It is recommended to only open log
+`ANDROID_LOG_WRONLY` in that case.
+
+The value returned by `android_logger_open()` can be used as a parameter to the
+`android_logger_get_log_(size|readable_size|version)` to retrieve the sub-log maximum size, readable
+size and log buffer format protocol version respectively. `android_logger_get_id()` returns the id
+that was used when opening the sub-log. It is recommended to open the log `ANDROID_LOG_RDONLY` in
+these cases.
+
+`android_set_log_transport()` selects transport filters. Argument is either `LOGGER_DEFAULT`,
+`LOGGER_LOGD`, or `LOGGER_NULL`. Log to logger daemon for default or logd, or drop contents on floor
+respectively. `Both android_set_log_transport()` and `android_get_log_transport()` return the
+current transport mask, or a negative errno for any problems.
+
+Errors
+------
+
+If messages fail, a negative error code will be returned to the caller.
+
+The `-ENOTCONN` return code indicates that the logger daemon is stopped.
+
+The `-EBADF` return code indicates that the log access point can not be opened, or the log buffer id
+is out of range.
+
+For the `-EAGAIN` return code, this means that the logging message was temporarily backed-up either
+because of Denial Of Service (DOS) logging pressure from some chatty application or service in the
+Android system, or if too small of a value is set in /proc/sys/net/unix/max_dgram_qlen. To aid in
+diagnosing the occurence of this, a binary event from liblog will be sent to the log daemon once a
+new message can get through indicating how many messages were dropped as a result. Please take
+action to resolve the structural problems at the source.
+
+It is generally not advised for the caller to retry the `-EAGAIN` return code as this will only make
+the problem(s) worse and cause your application to temporarily drop to the logger daemon priority,
+BATCH scheduling policy and background task cgroup. If you require a group of messages to be passed
+atomically, merge them into one message with embedded newlines to the maximum length
+`LOGGER_ENTRY_MAX_PAYLOAD`.
+
+Other return codes from writing operation can be returned. Since the library retries on `EINTR`,
+`-EINTR` should never be returned.
diff --git a/liblog/config_read.c b/liblog/config_read.c
index ca80c80..51ffff6 100644
--- a/liblog/config_read.c
+++ b/liblog/config_read.c
@@ -55,12 +55,6 @@
}
LIBLOG_HIDDEN void __android_log_config_read() {
- if (__android_log_transport & LOGGER_LOCAL) {
- extern struct android_log_transport_read localLoggerRead;
-
- __android_log_add_transport(&__android_log_transport_read, &localLoggerRead);
- }
-
#if (FAKE_LOG_DEVICE == 0)
if ((__android_log_transport == LOGGER_DEFAULT) ||
(__android_log_transport & LOGGER_LOGD)) {
diff --git a/liblog/config_write.c b/liblog/config_write.c
index 0a8b52f..003ec8f 100644
--- a/liblog/config_write.c
+++ b/liblog/config_write.c
@@ -55,13 +55,6 @@
}
LIBLOG_HIDDEN void __android_log_config_write() {
- if (__android_log_transport & LOGGER_LOCAL) {
- extern struct android_log_transport_write localLoggerWrite;
-
- __android_log_add_transport(&__android_log_transport_write,
- &localLoggerWrite);
- }
-
if ((__android_log_transport == LOGGER_DEFAULT) ||
(__android_log_transport & LOGGER_LOGD)) {
#if (FAKE_LOG_DEVICE == 0)
diff --git a/liblog/include/log/log_transport.h b/liblog/include/log/log_transport.h
index 80b30db..8b02995 100644
--- a/liblog/include/log/log_transport.h
+++ b/liblog/include/log/log_transport.h
@@ -22,7 +22,7 @@
#define LOGGER_LOGD 0x01
#define LOGGER_KERNEL 0x02 /* Reserved/Deprecated */
#define LOGGER_NULL 0x04 /* Does not release resources of other selections */
-#define LOGGER_LOCAL 0x08 /* logs sent to local memory */
+#define LOGGER_RESERVED 0x08 /* Reserved, previously for logging to local memory */
#define LOGGER_STDERR 0x10 /* logs sent to stderr */
/* clang-format on */
diff --git a/liblog/local_logger.c b/liblog/local_logger.c
deleted file mode 100644
index 563cb3f..0000000
--- a/liblog/local_logger.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/*
- * Copyright (C) 2017 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 <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#if !defined(__MINGW32__)
-#include <pwd.h>
-#endif
-#include <log/uio.h>
-#include <sched.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <cutils/list.h> /* template, no library dependency */
-#include <log/log_transport.h>
-#include <private/android_filesystem_config.h>
-#include <private/android_logger.h>
-#include <system/thread_defs.h>
-
-#include "config_read.h"
-#include "config_write.h"
-#include "log_portability.h"
-#include "logger.h"
-
-static const char baseServiceName[] = "android.logd";
-
-static int writeToLocalInit();
-static int writeToLocalAvailable(log_id_t logId);
-static void writeToLocalReset();
-static int writeToLocalWrite(log_id_t logId, struct timespec* ts,
- struct iovec* vec, size_t nr);
-
-LIBLOG_HIDDEN struct android_log_transport_write localLoggerWrite = {
- .node = { &localLoggerWrite.node, &localLoggerWrite.node },
- .context.priv = NULL,
- .name = "local",
- .available = writeToLocalAvailable,
- .open = writeToLocalInit,
- .close = writeToLocalReset,
- .write = writeToLocalWrite,
-};
-
-static int writeToLocalVersion(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static int writeToLocalRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg);
-static int writeToLocalPoll(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp);
-static void writeToLocalClose(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp);
-static int writeToLocalClear(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static ssize_t writeToLocalGetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-static ssize_t writeToLocalSetSize(
- struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused, size_t size);
-static ssize_t writeToLocalGetReadbleSize(
- struct android_log_logger* logger,
- struct android_log_transport_context* transp);
-
-struct android_log_transport_read localLoggerRead = {
- .node = { &localLoggerRead.node, &localLoggerRead.node },
- .name = "local",
- .available = writeToLocalAvailable,
- .version = writeToLocalVersion,
- .read = writeToLocalRead,
- .poll = writeToLocalPoll,
- .close = writeToLocalClose,
- .clear = writeToLocalClear,
- .getSize = writeToLocalGetSize,
- .setSize = writeToLocalSetSize,
- .getReadableSize = writeToLocalGetReadbleSize,
- .getPrune = NULL,
- .setPrune = NULL,
- .getStats = NULL,
-};
-
-struct LogBufferElement {
- struct listnode node;
- log_id_t logId;
- pid_t tid;
- log_time timestamp;
- unsigned short len;
- char msg[];
-};
-
-static const size_t MAX_SIZE_DEFAULT = 32768;
-
-/*
- * Number of log buffers we support with the following assumption:
- * . . .
- * LOG_ID_SECURITY = 5, // security logs go to the system logs only
- * LOG_ID_KERNEL = 6, // place last, third-parties can not use it
- * LOG_ID_MAX
- * } log_id_t;
- *
- * Confirm the following should <log/log_id.h> be adjusted in the future.
- */
-#define NUMBER_OF_LOG_BUFFERS \
- ((LOG_ID_SECURITY == (LOG_ID_MAX - 2)) ? LOG_ID_SECURITY : LOG_ID_KERNEL)
-#define BLOCK_LOG_BUFFERS(id) \
- (((id) == LOG_ID_SECURITY) || ((id) == LOG_ID_KERNEL))
-
-static struct LogBuffer {
- struct listnode head;
- pthread_rwlock_t listLock;
- char* serviceName; /* Also indicates ready by having a value */
- /* Order and proximity important for memset */
- size_t number[NUMBER_OF_LOG_BUFFERS]; /* clear memset */
- size_t size[NUMBER_OF_LOG_BUFFERS]; /* clear memset */
- size_t totalSize[NUMBER_OF_LOG_BUFFERS]; /* init memset */
- size_t maxSize[NUMBER_OF_LOG_BUFFERS]; /* init MAX_SIZE_DEFAULT */
- struct listnode* last[NUMBER_OF_LOG_BUFFERS]; /* init &head */
-} logbuf = {
- .head = { &logbuf.head, &logbuf.head }, .listLock = PTHREAD_RWLOCK_INITIALIZER,
-};
-
-static void LogBufferInit(struct LogBuffer* log) {
- size_t i;
-
- pthread_rwlock_wrlock(&log->listLock);
- list_init(&log->head);
- memset(log->number, 0,
- sizeof(log->number) + sizeof(log->size) + sizeof(log->totalSize));
- for (i = 0; i < NUMBER_OF_LOG_BUFFERS; ++i) {
- log->maxSize[i] = MAX_SIZE_DEFAULT;
- log->last[i] = &log->head;
- }
-#ifdef __BIONIC__
- asprintf(&log->serviceName, "%s@%d:%d", baseServiceName, __android_log_uid(),
- getpid());
-#else
- char buffer[sizeof(baseServiceName) + 1 + 5 + 1 + 5 + 8];
- snprintf(buffer, sizeof(buffer), "%s@%d:%d", baseServiceName,
- __android_log_uid(), getpid());
- log->serviceName = strdup(buffer);
-#endif
- pthread_rwlock_unlock(&log->listLock);
-}
-
-static void LogBufferClear(struct LogBuffer* log) {
- size_t i;
- struct listnode* node;
-
- pthread_rwlock_wrlock(&log->listLock);
- memset(log->number, 0, sizeof(log->number) + sizeof(log->size));
- for (i = 0; i < NUMBER_OF_LOG_BUFFERS; ++i) {
- log->last[i] = &log->head;
- }
- while ((node = list_head(&log->head)) != &log->head) {
- struct LogBufferElement* element;
-
- element = node_to_item(node, struct LogBufferElement, node);
- list_remove(node);
- free(element);
- }
- pthread_rwlock_unlock(&log->listLock);
-}
-
-static inline void LogBufferFree(struct LogBuffer* log) {
- pthread_rwlock_wrlock(&log->listLock);
- free(log->serviceName);
- log->serviceName = NULL;
- pthread_rwlock_unlock(&log->listLock);
- LogBufferClear(log);
-}
-
-static int LogBufferLog(struct LogBuffer* log,
- struct LogBufferElement* element) {
- log_id_t logId = element->logId;
-
- pthread_rwlock_wrlock(&log->listLock);
- log->number[logId]++;
- log->size[logId] += element->len;
- log->totalSize[logId] += element->len;
- /* prune entry(s) until enough space is available */
- if (log->last[logId] == &log->head) {
- log->last[logId] = list_tail(&log->head);
- }
- while (log->size[logId] > log->maxSize[logId]) {
- struct listnode* node = log->last[logId];
- struct LogBufferElement* e;
- struct android_log_logger_list* logger_list;
-
- e = node_to_item(node, struct LogBufferElement, node);
- log->number[logId]--;
- log->size[logId] -= e->len;
- logger_list_rdlock();
- logger_list_for_each(logger_list) {
- struct android_log_transport_context* transp;
-
- transport_context_for_each(transp, logger_list) {
- if ((transp->transport == &localLoggerRead) &&
- (transp->context.node == node)) {
- if (node == &log->head) {
- transp->context.node = &log->head;
- } else {
- transp->context.node = node->next;
- }
- }
- }
- }
- logger_list_unlock();
- if (node != &log->head) {
- log->last[logId] = node->prev;
- }
- list_remove(node);
- LOG_ALWAYS_FATAL_IF(node == log->last[logId], "corrupted list");
- free(e);
- }
- /* add entry to list */
- list_add_head(&log->head, &element->node);
- /* ToDo: wake up all readers */
- pthread_rwlock_unlock(&log->listLock);
-
- return element->len;
-}
-
-/*
- * return zero if permitted to log directly to logd,
- * return 1 if binder server started and
- * return negative error number if failed to start binder server.
- */
-static int writeToLocalInit() {
- pthread_attr_t attr;
- struct LogBuffer* log;
-
- if (writeToLocalAvailable(LOG_ID_MAIN) < 0) {
- return -EPERM;
- }
-
- log = &logbuf;
- if (!log->serviceName) {
- LogBufferInit(log);
- }
-
- if (!log->serviceName) {
- LogBufferFree(log);
- return -ENOMEM;
- }
-
- return EPERM; /* successful local-only logging */
-}
-
-static void writeToLocalReset() {
- LogBufferFree(&logbuf);
-}
-
-static int writeToLocalAvailable(log_id_t logId) {
-#if !defined(__MINGW32__)
- uid_t uid;
-#endif
-
- if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
- return -EINVAL;
- }
-
-/* Android hard coded permitted, system goes to logd */
-#if !defined(__MINGW32__)
- if (__android_log_transport == LOGGER_DEFAULT) {
- uid = __android_log_uid();
- if ((uid < AID_APP) && (getpwuid(uid) != NULL)) {
- return -EPERM;
- }
- }
-#endif
-
- /* ToDo: Ask package manager for LOGD permissions */
- /* Assume we do _not_ have permissions to go to LOGD, so must go local */
- return 0;
-}
-
-static int writeToLocalWrite(log_id_t logId, struct timespec* ts,
- struct iovec* vec, size_t nr) {
- size_t len, i;
- struct LogBufferElement* element;
-
- if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
- return -EINVAL;
- }
-
- len = 0;
- for (i = 0; i < nr; ++i) {
- len += vec[i].iov_len;
- }
-
- if (len > LOGGER_ENTRY_MAX_PAYLOAD) {
- len = LOGGER_ENTRY_MAX_PAYLOAD;
- }
- element = (struct LogBufferElement*)calloc(
- 1, sizeof(struct LogBufferElement) + len + 1);
- if (!element) {
- return errno ? -errno : -ENOMEM;
- }
- element->timestamp.tv_sec = ts->tv_sec;
- element->timestamp.tv_nsec = ts->tv_nsec;
-#ifdef __BIONIC__
- element->tid = gettid();
-#else
- element->tid = getpid();
-#endif
- element->logId = logId;
- element->len = len;
-
- char* cp = element->msg;
- for (i = 0; i < nr; ++i) {
- size_t iov_len = vec[i].iov_len;
- if (iov_len > len) {
- iov_len = len;
- }
- memcpy(cp, vec[i].iov_base, iov_len);
- len -= iov_len;
- if (len == 0) {
- break;
- }
- cp += iov_len;
- }
-
- return LogBufferLog(&logbuf, element);
-}
-
-static int writeToLocalVersion(struct android_log_logger* logger __unused,
- struct android_log_transport_context* transp
- __unused) {
- return 3;
-}
-
-/* within reader lock, serviceName already validated */
-static struct listnode* writeToLocalNode(
- struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp) {
- struct listnode* node;
- unsigned logMask;
- unsigned int tail;
-
- node = transp->context.node;
- if (node) {
- return node;
- }
-
- if (!logger_list->tail) {
- return transp->context.node = &logbuf.head;
- }
-
- logMask = transp->logMask;
- tail = logger_list->tail;
-
- for (node = list_head(&logbuf.head); node != &logbuf.head; node = node->next) {
- struct LogBufferElement* element;
- log_id_t logId;
-
- element = node_to_item(node, struct LogBufferElement, node);
- logId = element->logId;
-
- if ((logMask & (1 << logId)) && !--tail) {
- node = node->next;
- break;
- }
- }
- return transp->context.node = node;
-}
-
-static int writeToLocalRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg) {
- int ret;
- struct listnode* node;
- unsigned logMask;
-
- pthread_rwlock_rdlock(&logbuf.listLock);
- if (!logbuf.serviceName) {
- pthread_rwlock_unlock(&logbuf.listLock);
- return (logger_list->mode & ANDROID_LOG_NONBLOCK) ? -ENODEV : 0;
- }
-
- logMask = transp->logMask;
-
- node = writeToLocalNode(logger_list, transp);
-
- ret = 0;
-
- while (node != list_head(&logbuf.head)) {
- struct LogBufferElement* element;
- log_id_t logId;
-
- node = node->prev;
- element = node_to_item(node, struct LogBufferElement, node);
- logId = element->logId;
-
- if (logMask & (1 << logId)) {
- ret = log_msg->entry_v3.len = element->len;
- log_msg->entry_v3.hdr_size = sizeof(log_msg->entry_v3);
- log_msg->entry_v3.pid = getpid();
- log_msg->entry_v3.tid = element->tid;
- log_msg->entry_v3.sec = element->timestamp.tv_sec;
- log_msg->entry_v3.nsec = element->timestamp.tv_nsec;
- log_msg->entry_v3.lid = logId;
- memcpy(log_msg->entry_v3.msg, element->msg, ret);
- ret += log_msg->entry_v3.hdr_size;
- break;
- }
- }
-
- transp->context.node = node;
-
- /* ToDo: if blocking, and no entry, put reader to sleep */
- pthread_rwlock_unlock(&logbuf.listLock);
- return ret;
-}
-
-static int writeToLocalPoll(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp) {
- int ret = (logger_list->mode & ANDROID_LOG_NONBLOCK) ? -ENODEV : 0;
-
- pthread_rwlock_rdlock(&logbuf.listLock);
-
- if (logbuf.serviceName) {
- unsigned logMask = transp->logMask;
- struct listnode* node = writeToLocalNode(logger_list, transp);
-
- ret = (node != list_head(&logbuf.head));
- if (ret) {
- do {
- ret = !!(logMask &
- (1 << (node_to_item(node->prev, struct LogBufferElement, node))
- ->logId));
- } while (!ret && ((node = node->prev) != list_head(&logbuf.head)));
- }
-
- transp->context.node = node;
- }
-
- pthread_rwlock_unlock(&logbuf.listLock);
-
- return ret;
-}
-
-static void writeToLocalClose(struct android_log_logger_list* logger_list
- __unused,
- struct android_log_transport_context* transp) {
- pthread_rwlock_wrlock(&logbuf.listLock);
- transp->context.node = list_head(&logbuf.head);
- pthread_rwlock_unlock(&logbuf.listLock);
-}
-
-static int writeToLocalClear(struct android_log_logger* logger,
- struct android_log_transport_context* unused
- __unused) {
- log_id_t logId = logger->logId;
- struct listnode *node, *n;
-
- if ((logId >= NUMBER_OF_LOG_BUFFERS) || BLOCK_LOG_BUFFERS(logId)) {
- return -EINVAL;
- }
-
- pthread_rwlock_wrlock(&logbuf.listLock);
- logbuf.number[logId] = 0;
- logbuf.last[logId] = &logbuf.head;
- list_for_each_safe(node, n, &logbuf.head) {
- struct LogBufferElement* element;
- element = node_to_item(node, struct LogBufferElement, node);
-
- if (logId == element->logId) {
- struct android_log_logger_list* logger_list;
-
- logger_list_rdlock();
- logger_list_for_each(logger_list) {
- struct android_log_transport_context* transp;
-
- transport_context_for_each(transp, logger_list) {
- if ((transp->transport == &localLoggerRead) &&
- (transp->context.node == node)) {
- transp->context.node = node->next;
- }
- }
- }
- logger_list_unlock();
- list_remove(node);
- free(element);
- }
- }
-
- pthread_rwlock_unlock(&logbuf.listLock);
-
- return 0;
-}
-
-static ssize_t writeToLocalGetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp
- __unused) {
- ssize_t ret = -EINVAL;
- log_id_t logId = logger->logId;
-
- if ((logId < NUMBER_OF_LOG_BUFFERS) && !BLOCK_LOG_BUFFERS(logId)) {
- pthread_rwlock_rdlock(&logbuf.listLock);
- ret = logbuf.maxSize[logId];
- pthread_rwlock_unlock(&logbuf.listLock);
- }
-
- return ret;
-}
-
-static ssize_t writeToLocalSetSize(
- struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused, size_t size) {
- ssize_t ret = -EINVAL;
-
- if ((size > LOGGER_ENTRY_MAX_LEN) || (size < (4 * 1024 * 1024))) {
- log_id_t logId = logger->logId;
- if ((logId < NUMBER_OF_LOG_BUFFERS) || !BLOCK_LOG_BUFFERS(logId)) {
- pthread_rwlock_wrlock(&logbuf.listLock);
- ret = logbuf.maxSize[logId] = size;
- pthread_rwlock_unlock(&logbuf.listLock);
- }
- }
-
- return ret;
-}
-
-static ssize_t writeToLocalGetReadbleSize(
- struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused) {
- ssize_t ret = -EINVAL;
- log_id_t logId = logger->logId;
-
- if ((logId < NUMBER_OF_LOG_BUFFERS) && !BLOCK_LOG_BUFFERS(logId)) {
- pthread_rwlock_rdlock(&logbuf.listLock);
- ret = logbuf.serviceName ? (ssize_t)logbuf.size[logId] : -EBADF;
- pthread_rwlock_unlock(&logbuf.listLock);
- }
-
- return ret;
-}
diff --git a/liblog/logger.h b/liblog/logger.h
index 246b33c..af83228 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -98,7 +98,6 @@
};
struct android_log_logger_list {
- struct listnode node;
struct listnode logger;
struct listnode transport;
int mode;
@@ -144,37 +143,6 @@
(logp) = \
node_to_item((logp)->node.next, struct android_log_logger, node))
-/*
- * Global list of log readers.
- *
- * Usage case: search out transport contexts for all readers
- */
-
-LIBLOG_HIDDEN struct listnode __android_log_readers;
-
-#if defined(_WIN32)
-#define logger_list_rdlock()
-#define logger_list_wrlock()
-#define logger_list_unlock()
-#else
-LIBLOG_HIDDEN pthread_rwlock_t __android_log_readers_lock;
-
-#define logger_list_rdlock() pthread_rwlock_rdlock(&__android_log_readers_lock)
-#define logger_list_wrlock() pthread_rwlock_wrlock(&__android_log_readers_lock)
-#define logger_list_unlock() pthread_rwlock_unlock(&__android_log_readers_lock)
-#endif
-
-/* Must be called with logger_list_rdlock() or logger_list_wrlock() held */
-#define logger_list_for_each(logger_list) \
- for ((logger_list) = node_to_item(&__android_log_readers, \
- struct android_log_logger_list, node); \
- (logger_list) != node_to_item(&__android_log_readers, \
- struct android_log_logger_list, node) && \
- (logger_list) != node_to_item((logger_list)->node.next, \
- struct android_log_logger_list, node); \
- (logger_list) = node_to_item((logger_list)->node.next, \
- struct android_log_logger_list, node))
-
/* OS specific dribs and drabs */
#if defined(_WIN32)
diff --git a/liblog/logger_read.c b/liblog/logger_read.c
index 0fd6efa..29ebaf7 100644
--- a/liblog/logger_read.c
+++ b/liblog/logger_read.c
@@ -213,13 +213,6 @@
LOGGER_LIST_FUNCTION(logger_list, -ENODEV, setPrune, buf, len);
}
-LIBLOG_HIDDEN struct listnode __android_log_readers = { &__android_log_readers,
- &__android_log_readers };
-#if !defined(_WIN32)
-LIBLOG_HIDDEN pthread_rwlock_t __android_log_readers_lock =
- PTHREAD_RWLOCK_INITIALIZER;
-#endif
-
LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc(
int mode, unsigned int tail, pid_t pid) {
struct android_log_logger_list* logger_list;
@@ -235,10 +228,6 @@
logger_list->tail = tail;
logger_list->pid = pid;
- logger_list_wrlock();
- list_add_tail(&__android_log_readers, &logger_list->node);
- logger_list_unlock();
-
return (struct logger_list*)logger_list;
}
@@ -257,10 +246,6 @@
logger_list->start = start;
logger_list->pid = pid;
- logger_list_wrlock();
- list_add_tail(&__android_log_readers, &logger_list->node);
- logger_list_unlock();
-
return (struct logger_list*)logger_list;
}
@@ -472,10 +457,6 @@
return;
}
- logger_list_wrlock();
- list_remove(&logger_list_internal->node);
- logger_list_unlock();
-
while (!list_empty(&logger_list_internal->transport)) {
struct listnode* node = list_head(&logger_list_internal->transport);
struct android_log_transport_context* transp =
diff --git a/liblog/logger_write.c b/liblog/logger_write.c
index 2754e6e..6dcda9b 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.c
@@ -684,9 +684,9 @@
return retval;
}
- __android_log_transport &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
+ __android_log_transport &= LOGGER_LOGD | LOGGER_STDERR;
- transport_flag &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
+ transport_flag &= LOGGER_LOGD | LOGGER_STDERR;
if (__android_log_transport != transport_flag) {
__android_log_transport = transport_flag;
@@ -714,7 +714,7 @@
if (write_to_log == __write_to_log_null) {
ret = LOGGER_NULL;
} else {
- __android_log_transport &= LOGGER_LOCAL | LOGGER_LOGD | LOGGER_STDERR;
+ __android_log_transport &= LOGGER_LOGD | LOGGER_STDERR;
ret = __android_log_transport;
if ((write_to_log != __write_to_log_init) &&
(write_to_log != __write_to_log_daemon)) {
diff --git a/liblog/tests/Android.bp b/liblog/tests/Android.bp
index e6a9c0c..2c47fd6 100644
--- a/liblog/tests/Android.bp
+++ b/liblog/tests/Android.bp
@@ -54,9 +54,7 @@
srcs: [
"libc_test.cpp",
"liblog_test_default.cpp",
- "liblog_test_local.cpp",
"liblog_test_stderr.cpp",
- "liblog_test_stderr_local.cpp",
"log_id_test.cpp",
"log_radio_test.cpp",
"log_read_test.cpp",
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 383d0e7..2d0fc9b 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -52,22 +52,6 @@
#endif
#endif
-#if (!defined(USING_LOGGER_DEFAULT) || !defined(USING_LOGGER_LOCAL) || \
- !defined(USING_LOGGER_STDERR))
-#ifdef liblog // a binary clue that we are overriding the test names
-// Does not support log reading blocking feature yet
-// Does not support LOG_ID_SECURITY (unless we set LOGGER_LOCAL | LOGGER_LOGD)
-// Assume some common aspects are tested by USING_LOGGER_DEFAULT:
-// Does not need to _retest_ pmsg functionality
-// Does not need to _retest_ property handling as it is a higher function
-// Does not need to _retest_ event mapping functionality
-// Does not need to _retest_ ratelimit
-// Does not need to _retest_ logprint
-#define USING_LOGGER_LOCAL
-#else
-#define USING_LOGGER_DEFAULT
-#endif
-#endif
#ifdef USING_LOGGER_STDERR
#define SUPPORTS_END_TO_END 0
#else
@@ -175,7 +159,7 @@
#endif
TEST(liblog, __android_log_btwrite__android_logger_list_read) {
-#if (defined(__ANDROID__) || defined(USING_LOGGER_LOCAL))
+#ifdef __ANDROID__
#ifdef TEST_PREFIX
TEST_PREFIX
#endif
@@ -269,7 +253,7 @@
#endif
}
-#if (defined(__ANDROID__) || defined(USING_LOGGER_LOCAL))
+#ifdef __ANDROID__
static void print_transport(const char* prefix, int logger) {
static const char orstr[] = " | ";
@@ -297,16 +281,11 @@
fprintf(stderr, "%sLOGGER_NULL", prefix);
prefix = orstr;
}
- if (logger & LOGGER_LOCAL) {
- fprintf(stderr, "%sLOGGER_LOCAL", prefix);
- prefix = orstr;
- }
if (logger & LOGGER_STDERR) {
fprintf(stderr, "%sLOGGER_STDERR", prefix);
prefix = orstr;
}
- logger &= ~(LOGGER_LOGD | LOGGER_KERNEL | LOGGER_NULL | LOGGER_LOCAL |
- LOGGER_STDERR);
+ logger &= ~(LOGGER_LOGD | LOGGER_KERNEL | LOGGER_NULL | LOGGER_STDERR);
if (logger) {
fprintf(stderr, "%s0x%x", prefix, logger);
prefix = orstr;
@@ -321,7 +300,7 @@
// and behind us, to make us whole. We could incorporate a prefix and
// suffix test to make this standalone, but opted to not complicate this.
TEST(liblog, android_set_log_transport) {
-#if (defined(__ANDROID__) || defined(USING_LOGGER_LOCAL))
+#ifdef __ANDROID__
#ifdef TEST_PREFIX
TEST_PREFIX
#endif
@@ -632,7 +611,7 @@
buf_write_test("\n Hello World \n");
}
-#ifndef USING_LOGGER_LOCAL // requires blocking reader functionality
+#ifdef USING_LOGGER_DEFAULT // requires blocking reader functionality
#ifdef TEST_PREFIX
static unsigned signaled;
static log_time signal_time;
@@ -944,7 +923,7 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // !USING_LOGGER_LOCAL
+#endif // USING_LOGGER_DEFAULT
#ifdef TEST_PREFIX
static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
@@ -2417,7 +2396,7 @@
}
// Do not retest logger list handling
-#if (defined(TEST_PREFIX) || !defined(USING_LOGGER_LOCAL))
+#ifdef TEST_PREFIX
static int is_real_element(int type) {
return ((type == EVENT_TYPE_INT) || (type == EVENT_TYPE_LONG) ||
(type == EVENT_TYPE_STRING) || (type == EVENT_TYPE_FLOAT));
@@ -2572,7 +2551,7 @@
return 0;
}
-#endif // TEST_PREFIX || !USING_LOGGER_LOCAL
+#endif // TEST_PREFIX
#ifdef TEST_PREFIX
static const char* event_test_int32(uint32_t tag, size_t& expected_len) {
diff --git a/liblog/tests/liblog_test_local.cpp b/liblog/tests/liblog_test_local.cpp
deleted file mode 100644
index 451beca..0000000
--- a/liblog/tests/liblog_test_local.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-#include <log/log_transport.h>
-#define liblog liblog_local
-#define TEST_LOGGER LOGGER_LOCAL
-#include "liblog_test.cpp"
diff --git a/liblog/tests/liblog_test_stderr_local.cpp b/liblog/tests/liblog_test_stderr_local.cpp
deleted file mode 100644
index bb5c7ae..0000000
--- a/liblog/tests/liblog_test_stderr_local.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-#include <log/log_transport.h>
-#define liblog liblog_stderr_local
-#define TEST_LOGGER (LOGGER_LOCAL | LOGGER_STDERR)
-#include "liblog_test.cpp"
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 3c295b5..b26ad4d 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -525,7 +525,7 @@
// NOTREACHED
return;
}
- ::sync();
+ // Wish could ::sync() here, if storage is locked up, we will not continue.
if (dump) {
// Show all locks that are held
android::base::WriteStringToFd("d", sysrqTriggerFd);