Merge "crash_dump: properly dump when we can't talk to tombstoned."
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 3f8bc8f..f970e68 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -358,7 +358,7 @@
" devices [-l] List all connected devices [with\n"
" device paths].\n"
" continue Continue with autoboot.\n"
- " reboot [bootloader] Reboot device [into bootloader].\n"
+ " reboot [bootloader|emergency] Reboot device [into bootloader or emergency mode].\n"
" reboot-bootloader Reboot device into bootloader.\n"
" help Show this help message.\n"
"\n"
@@ -1397,6 +1397,7 @@
bool wants_wipe = false;
bool wants_reboot = false;
bool wants_reboot_bootloader = false;
+ bool wants_reboot_emergency = false;
bool skip_reboot = false;
bool wants_set_active = false;
bool skip_secondary = false;
@@ -1648,6 +1649,11 @@
wants_reboot_bootloader = true;
skip(1);
}
+ if (!strcmp(*argv, "emergency")) {
+ wants_reboot = false;
+ wants_reboot_emergency = true;
+ skip(1);
+ }
}
require(0);
} else if(!strcmp(*argv, "reboot-bootloader")) {
@@ -1807,6 +1813,9 @@
} else if (wants_reboot_bootloader) {
fb_queue_command("reboot-bootloader", "rebooting into bootloader");
fb_queue_wait_for_disconnect();
+ } else if (wants_reboot_emergency) {
+ fb_queue_command("reboot-emergency", "rebooting into emergency download (EDL) mode");
+ fb_queue_wait_for_disconnect();
}
return fb_execute_queue(transport) ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 8d5b51b..e321c17 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -11,7 +11,8 @@
libcrypto \
libext4_utils \
libsquashfs_utils \
- libselinux
+ libselinux \
+ libavb
include $(CLEAR_VARS)
LOCAL_CLANG := true
@@ -22,7 +23,9 @@
fs_mgr_format.c \
fs_mgr_fstab.c \
fs_mgr_slotselect.c \
- fs_mgr_verity.cpp
+ fs_mgr_verity.cpp \
+ fs_mgr_avb.cpp \
+ fs_mgr_avb_ops.cpp
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
system/vold \
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index e699b71..43fb9ea 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -46,6 +46,7 @@
#include <private/android_logger.h>
#include "fs_mgr_priv.h"
+#include "fs_mgr_priv_avb.h"
#include "fs_mgr_priv_verity.h"
#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
@@ -670,11 +671,17 @@
int mret = -1;
int mount_errno = 0;
int attempted_idx = -1;
+ int avb_ret = FS_MGR_SETUP_AVB_FAIL;
if (!fstab) {
return -1;
}
+ if (fs_mgr_is_avb_used() &&
+ (avb_ret = fs_mgr_load_vbmeta_images(fstab)) == FS_MGR_SETUP_AVB_FAIL) {
+ return -1;
+ }
+
for (i = 0; i < fstab->num_entries; i++) {
/* Don't mount entries that are managed by vold or not for the mount mode*/
if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) ||
@@ -713,7 +720,22 @@
wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
}
- if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+ if (fs_mgr_is_avb_used() && (fstab->recs[i].fs_mgr_flags & MF_AVB)) {
+ /* If HASHTREE_DISABLED is set (cf. 'adb disable-verity'), we
+ * should set up the device without using dm-verity.
+ * The actual mounting still take place in the following
+ * mount_with_alternatives().
+ */
+ if (avb_ret == FS_MGR_SETUP_AVB_HASHTREE_DISABLED) {
+ INFO("AVB HASHTREE disabled\n");
+ } else if (fs_mgr_setup_avb(&fstab->recs[i]) !=
+ FS_MGR_SETUP_AVB_SUCCESS) {
+ ERROR("Failed to set up AVB on partition: %s, skipping!\n",
+ fstab->recs[i].mount_point);
+ /* Skips mounting the device. */
+ continue;
+ }
+ } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
INFO("Verity disabled");
@@ -722,6 +744,7 @@
continue;
}
}
+
int last_idx_inspected;
int top_idx = i;
@@ -825,6 +848,10 @@
}
}
+ if (fs_mgr_is_avb_used()) {
+ fs_mgr_unload_vbmeta_images();
+ }
+
if (error_count) {
return -1;
} else {
@@ -845,11 +872,17 @@
int mount_errors = 0;
int first_mount_errno = 0;
char *m;
+ int avb_ret = FS_MGR_SETUP_AVB_FAIL;
if (!fstab) {
return ret;
}
+ if (fs_mgr_is_avb_used() &&
+ (avb_ret = fs_mgr_load_vbmeta_images(fstab)) == FS_MGR_SETUP_AVB_FAIL) {
+ return ret;
+ }
+
for (i = 0; i < fstab->num_entries; i++) {
if (!fs_match(fstab->recs[i].mount_point, n_name)) {
continue;
@@ -882,7 +915,22 @@
do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i]);
}
- if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+ if (fs_mgr_is_avb_used() && (fstab->recs[i].fs_mgr_flags & MF_AVB)) {
+ /* If HASHTREE_DISABLED is set (cf. 'adb disable-verity'), we
+ * should set up the device without using dm-verity.
+ * The actual mounting still take place in the following
+ * mount_with_alternatives().
+ */
+ if (avb_ret == FS_MGR_SETUP_AVB_HASHTREE_DISABLED) {
+ INFO("AVB HASHTREE disabled\n");
+ } else if (fs_mgr_setup_avb(&fstab->recs[i]) !=
+ FS_MGR_SETUP_AVB_SUCCESS) {
+ ERROR("Failed to set up AVB on partition: %s, skipping!\n",
+ fstab->recs[i].mount_point);
+ /* Skips mounting the device. */
+ continue;
+ }
+ } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
INFO("Verity disabled");
@@ -921,6 +969,9 @@
}
out:
+ if (fs_mgr_is_avb_used()) {
+ fs_mgr_unload_vbmeta_images();
+ }
return ret;
}
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
new file mode 100644
index 0000000..51632cf
--- /dev/null
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2016 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 <inttypes.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <cutils/properties.h>
+#include <libavb/libavb.h>
+#include <openssl/sha.h>
+#include <sys/ioctl.h>
+#include <utils/Compat.h>
+
+#include "fs_mgr.h"
+#include "fs_mgr_avb_ops.h"
+#include "fs_mgr_priv.h"
+#include "fs_mgr_priv_avb.h"
+#include "fs_mgr_priv_dm_ioctl.h"
+#include "fs_mgr_priv_sha.h"
+
+/* The format of dm-verity construction parameters:
+ * <version> <dev> <hash_dev> <data_block_size> <hash_block_size>
+ * <num_data_blocks> <hash_start_block> <algorithm> <digest> <salt>
+ */
+#define VERITY_TABLE_FORMAT \
+ "%u %s %s %u %u " \
+ "%" PRIu64 " %" PRIu64 " %s %s %s "
+
+#define VERITY_TABLE_PARAMS(hashtree_desc, blk_device, digest, salt) \
+ 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, /* num_data_blocks. */ \
+ hashtree_desc.tree_offset / \
+ hashtree_desc.hash_block_size, /* hash_start_block. */ \
+ (char *)hashtree_desc.hash_algorithm, digest, salt
+
+#define VERITY_TABLE_OPT_RESTART "restart_on_corruption"
+#define VERITY_TABLE_OPT_IGNZERO "ignore_zero_blocks"
+
+/* The default format of dm-verity optional parameters:
+ * <#opt_params> ignore_zero_blocks restart_on_corruption
+ */
+#define VERITY_TABLE_OPT_DEFAULT_FORMAT "2 %s %s"
+#define VERITY_TABLE_OPT_DEFAULT_PARAMS \
+ VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART
+
+/* The FEC (forward error correction) format of dm-verity optional parameters:
+ * <#opt_params> use_fec_from_device <fec_dev>
+ * fec_roots <num> fec_blocks <num> fec_start <offset>
+ * ignore_zero_blocks restart_on_corruption
+ */
+#define VERITY_TABLE_OPT_FEC_FORMAT \
+ "10 use_fec_from_device %s fec_roots %u fec_blocks %" PRIu64 \
+ " fec_start %" PRIu64 " %s %s"
+
+/* Note that fec_blocks is the size that FEC covers, *not* the
+ * size of the FEC data. Since we use FEC for everything up until
+ * the FEC data, it's the same as the offset (fec_start).
+ */
+#define VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device) \
+ blk_device, hashtree_desc.fec_num_roots, \
+ hashtree_desc.fec_offset / \
+ hashtree_desc.data_block_size, /* fec_blocks */ \
+ hashtree_desc.fec_offset / \
+ hashtree_desc.data_block_size, /* fec_start */ \
+ VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART
+
+AvbSlotVerifyData *fs_mgr_avb_verify_data = nullptr;
+AvbOps *fs_mgr_avb_ops = nullptr;
+
+enum HashAlgorithm {
+ kInvalid = 0,
+ kSHA256 = 1,
+ kSHA512 = 2,
+};
+
+struct androidboot_vbmeta {
+ HashAlgorithm hash_alg;
+ uint8_t digest[SHA512_DIGEST_LENGTH];
+ size_t vbmeta_size;
+ bool allow_verification_error;
+};
+
+androidboot_vbmeta fs_mgr_vbmeta_prop;
+
+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;
+}
+
+static bool load_vbmeta_prop(androidboot_vbmeta *vbmeta_prop)
+{
+ FS_MGR_CHECK(vbmeta_prop != nullptr);
+
+ std::string cmdline;
+ android::base::ReadFileToString("/proc/cmdline", &cmdline);
+
+ std::string hash_alg;
+ std::string digest;
+
+ for (const auto &entry :
+ android::base::Split(android::base::Trim(cmdline), " ")) {
+ std::vector<std::string> pieces = android::base::Split(entry, "=");
+ const std::string &key = pieces[0];
+ const std::string &value = pieces[1];
+
+ if (key == "androidboot.vbmeta.device_state") {
+ vbmeta_prop->allow_verification_error = (value == "unlocked");
+ } else if (key == "androidboot.vbmeta.hash_alg") {
+ hash_alg = value;
+ } else if (key == "androidboot.vbmeta.size") {
+ if (!android::base::ParseUint(value.c_str(),
+ &vbmeta_prop->vbmeta_size)) {
+ return false;
+ }
+ } else if (key == "androidboot.vbmeta.digest") {
+ digest = value;
+ }
+ }
+
+ // Reads hash algorithm.
+ size_t expected_digest_size = 0;
+ if (hash_alg == "sha256") {
+ expected_digest_size = SHA256_DIGEST_LENGTH * 2;
+ vbmeta_prop->hash_alg = kSHA256;
+ } else if (hash_alg == "sha512") {
+ expected_digest_size = SHA512_DIGEST_LENGTH * 2;
+ vbmeta_prop->hash_alg = kSHA512;
+ } else {
+ ERROR("Unknown hash algorithm: %s\n", hash_alg.c_str());
+ return false;
+ }
+
+ // Reads digest.
+ if (digest.size() != expected_digest_size) {
+ ERROR("Unexpected digest size: %zu (expected %zu)\n", digest.size(),
+ expected_digest_size);
+ return false;
+ }
+
+ if (!hex_to_bytes(vbmeta_prop->digest, sizeof(vbmeta_prop->digest),
+ digest)) {
+ ERROR("Hash digest contains non-hexidecimal character: %s\n",
+ digest.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+template <typename Hasher>
+static std::pair<size_t, bool> verify_vbmeta_digest(
+ const AvbSlotVerifyData &verify_data, const androidboot_vbmeta &vbmeta_prop)
+{
+ size_t total_size = 0;
+ Hasher hasher;
+ for (size_t n = 0; n < verify_data.num_vbmeta_images; n++) {
+ hasher.update(verify_data.vbmeta_images[n].vbmeta_data,
+ verify_data.vbmeta_images[n].vbmeta_size);
+ total_size += verify_data.vbmeta_images[n].vbmeta_size;
+ }
+
+ bool matched = (memcmp(hasher.finalize(), vbmeta_prop.digest,
+ Hasher::DIGEST_SIZE) == 0);
+
+ return std::make_pair(total_size, matched);
+}
+
+static bool verify_vbmeta_images(const AvbSlotVerifyData &verify_data,
+ const androidboot_vbmeta &vbmeta_prop)
+{
+ if (verify_data.num_vbmeta_images == 0) {
+ ERROR("No vbmeta images\n");
+ return false;
+ }
+
+ size_t total_size = 0;
+ bool digest_matched = false;
+
+ if (vbmeta_prop.hash_alg == kSHA256) {
+ std::tie(total_size, digest_matched) =
+ verify_vbmeta_digest<SHA256Hasher>(verify_data, vbmeta_prop);
+ } else if (vbmeta_prop.hash_alg == kSHA512) {
+ std::tie(total_size, digest_matched) =
+ verify_vbmeta_digest<SHA512Hasher>(verify_data, vbmeta_prop);
+ }
+
+ if (total_size != vbmeta_prop.vbmeta_size) {
+ ERROR("total vbmeta size mismatch: %zu (expected: %zu)\n", total_size,
+ vbmeta_prop.vbmeta_size);
+ return false;
+ }
+
+ if (!digest_matched) {
+ ERROR("vbmeta digest mismatch\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool hashtree_load_verity_table(
+ struct dm_ioctl *io,
+ const std::string &dm_device_name,
+ int fd,
+ const std::string &blk_device,
+ const AvbHashtreeDescriptor &hashtree_desc,
+ const std::string &salt,
+ const std::string &root_digest)
+{
+ fs_mgr_verity_ioctl_init(io, dm_device_name, DM_STATUS_TABLE_FLAG);
+
+ // The buffer consists of [dm_ioctl][dm_target_spec][verity_params].
+ char *buffer = (char *)io;
+
+ // Builds the dm_target_spec arguments.
+ struct dm_target_spec *dm_target =
+ (struct dm_target_spec *)&buffer[sizeof(struct dm_ioctl)];
+ io->target_count = 1;
+ dm_target->status = 0;
+ dm_target->sector_start = 0;
+ dm_target->length = hashtree_desc.image_size / 512;
+ strcpy(dm_target->target_type, "verity");
+
+ // Builds the verity params.
+ char *verity_params =
+ buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
+ size_t bufsize = DM_BUF_SIZE - (verity_params - buffer);
+
+ int res = 0;
+ if (hashtree_desc.fec_size > 0) {
+ res = snprintf(
+ verity_params, bufsize,
+ VERITY_TABLE_FORMAT VERITY_TABLE_OPT_FEC_FORMAT,
+ VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(),
+ root_digest.c_str(), salt.c_str()),
+ VERITY_TABLE_OPT_FEC_PARAMS(hashtree_desc, blk_device.c_str()));
+ } else {
+ res = snprintf(verity_params, bufsize,
+ VERITY_TABLE_FORMAT VERITY_TABLE_OPT_DEFAULT_FORMAT,
+ VERITY_TABLE_PARAMS(hashtree_desc, blk_device.c_str(),
+ root_digest.c_str(), salt.c_str()),
+ VERITY_TABLE_OPT_DEFAULT_PARAMS);
+ }
+
+ if (res < 0 || (size_t)res >= bufsize) {
+ ERROR("Error building verity table; insufficient buffer size?\n");
+ return false;
+ }
+
+ INFO("loading verity table: '%s'", verity_params);
+
+ // Sets ext target boundary.
+ verity_params += strlen(verity_params) + 1;
+ verity_params = (char *)(((unsigned long)verity_params + 7) & ~7);
+ dm_target->next = verity_params - buffer;
+
+ // Sends the ioctl to load the verity table.
+ if (ioctl(fd, DM_TABLE_LOAD, io)) {
+ ERROR("Error loading verity table (%s)\n", strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+static bool hashtree_dm_verity_setup(struct fstab_rec *fstab_entry,
+ const AvbHashtreeDescriptor &hashtree_desc,
+ const std::string &salt,
+ const std::string &root_digest)
+{
+ // Gets the device mapper fd.
+ android::base::unique_fd fd(open("/dev/device-mapper", O_RDWR));
+ if (fd < 0) {
+ ERROR("Error opening device mapper (%s)\n", strerror(errno));
+ return false;
+ }
+
+ // Creates the device.
+ alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
+ struct dm_ioctl *io = (struct dm_ioctl *)buffer;
+ const std::string mount_point(basename(fstab_entry->mount_point));
+ if (!fs_mgr_create_verity_device(io, mount_point, fd)) {
+ ERROR("Couldn't create verity device!\n");
+ return false;
+ }
+
+ // Gets the name of the device file.
+ std::string verity_blk_name;
+ if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) {
+ ERROR("Couldn't get verity device number!\n");
+ return false;
+ }
+
+ // Loads the verity mapping table.
+ if (!hashtree_load_verity_table(io, mount_point, fd,
+ std::string(fstab_entry->blk_device),
+ hashtree_desc, salt, root_digest)) {
+ ERROR("Couldn't load verity table!\n");
+ return false;
+ }
+
+ // Activates the device.
+ if (!fs_mgr_resume_verity_table(io, mount_point, fd)) {
+ return false;
+ }
+
+ // Marks the underlying block device as read-only.
+ fs_mgr_set_blk_ro(fstab_entry->blk_device);
+
+ // TODO(bowgotsai): support verified all partition at boot.
+ // Updates fstab_rec->blk_device to verity device name.
+ free(fstab_entry->blk_device);
+ fstab_entry->blk_device = strdup(verity_blk_name.c_str());
+
+ // Makes sure we've set everything up properly.
+ if (fs_mgr_test_access(verity_blk_name.c_str()) < 0) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool get_hashtree_descriptor(const std::string &partition_name,
+ const AvbSlotVerifyData &verify_data,
+ 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 < verify_data.num_vbmeta_images && !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(verify_data.vbmeta_images[i].vbmeta_data,
+ verify_data.vbmeta_images[i].vbmeta_size,
+ &num_descriptors),
+ avb_free);
+
+ if (!descriptors || num_descriptors < 1) {
+ continue;
+ }
+
+ // Ensures that hashtree descriptor is either in /vbmeta or in
+ // the same partition for verity setup.
+ std::string vbmeta_partition_name(
+ verify_data.vbmeta_images[i].partition_name);
+ if (vbmeta_partition_name != "vbmeta" &&
+ vbmeta_partition_name != partition_name) {
+ WARNING("Skip vbmeta image at %s for partition: %s\n",
+ verify_data.vbmeta_images[i].partition_name,
+ partition_name.c_str());
+ continue;
+ }
+
+ for (size_t j = 0; j < num_descriptors && !found; j++) {
+ AvbDescriptor desc;
+ if (!avb_descriptor_validate_and_byteswap(descriptors[j], &desc)) {
+ WARNING("Descriptor is invalid.\n");
+ 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) {
+ ERROR("Partition descriptor not found: %s\n", 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;
+}
+
+static inline bool polling_vbmeta_blk_device(struct fstab *fstab)
+{
+ // It needs the block device symlink: fstab_rec->blk_device to read
+ // /vbmeta partition. However, the symlink created by ueventd might
+ // not be ready at this point. Use test_access() to poll it before
+ // trying to read the partition.
+ struct fstab_rec *fstab_entry =
+ fs_mgr_get_entry_for_mount_point(fstab, "/vbmeta");
+
+ // Makes sure /vbmeta block device is ready to access.
+ if (fs_mgr_test_access(fstab_entry->blk_device) < 0) {
+ return false;
+ }
+ return true;
+}
+
+static bool init_is_avb_used()
+{
+ // When AVB is used, boot loader should set androidboot.vbmeta.{hash_alg,
+ // size, digest} in kernel cmdline. They will then be imported by init
+ // process to system properties: ro.boot.vbmeta.{hash_alg, size, digest}.
+ //
+ // Checks hash_alg as an indicator for whether AVB is used.
+ // We don't have to parse and check all of them here. The check will
+ // be done in fs_mgr_load_vbmeta_images() and FS_MGR_SETUP_AVB_FAIL will
+ // be returned when there is an error.
+
+ std::string hash_alg =
+ android::base::GetProperty("ro.boot.vbmeta.hash_alg", "");
+
+ if (hash_alg == "sha256" || hash_alg == "sha512") {
+ return true;
+ }
+
+ return false;
+}
+
+bool fs_mgr_is_avb_used()
+{
+ static bool result = init_is_avb_used();
+ return result;
+}
+
+int fs_mgr_load_vbmeta_images(struct fstab *fstab)
+{
+ FS_MGR_CHECK(fstab != nullptr);
+
+ if (!polling_vbmeta_blk_device(fstab)) {
+ ERROR("Failed to find block device of /vbmeta\n");
+ return FS_MGR_SETUP_AVB_FAIL;
+ }
+
+ // Gets the expected hash value of vbmeta images from
+ // kernel cmdline.
+ if (!load_vbmeta_prop(&fs_mgr_vbmeta_prop)) {
+ return FS_MGR_SETUP_AVB_FAIL;
+ }
+
+ fs_mgr_avb_ops = fs_mgr_dummy_avb_ops_new(fstab);
+ if (fs_mgr_avb_ops == nullptr) {
+ ERROR("Failed to allocate dummy avb_ops\n");
+ return FS_MGR_SETUP_AVB_FAIL;
+ }
+
+ // Invokes avb_slot_verify() to load and verify all vbmeta images.
+ // Sets requested_partitions to nullptr as it's to copy the contents
+ // of HASH partitions into fs_mgr_avb_verify_data, which is not required as
+ // fs_mgr only deals with HASHTREE partitions.
+ const char *requested_partitions[] = {nullptr};
+ const char *ab_suffix =
+ android::base::GetProperty("ro.boot.slot_suffix", "").c_str();
+ AvbSlotVerifyResult verify_result = avb_slot_verify(
+ fs_mgr_avb_ops, requested_partitions, ab_suffix,
+ fs_mgr_vbmeta_prop.allow_verification_error, &fs_mgr_avb_verify_data);
+
+ // Only allow two verify results:
+ // - AVB_SLOT_VERIFY_RESULT_OK.
+ // - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state).
+ if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION) {
+ if (!fs_mgr_vbmeta_prop.allow_verification_error) {
+ ERROR("ERROR_VERIFICATION isn't allowed\n");
+ goto fail;
+ }
+ } else if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) {
+ ERROR("avb_slot_verify failed, result: %d\n", verify_result);
+ goto fail;
+ }
+
+ // Verifies vbmeta images against the digest passed from bootloader.
+ if (!verify_vbmeta_images(*fs_mgr_avb_verify_data, fs_mgr_vbmeta_prop)) {
+ ERROR("verify_vbmeta_images failed\n");
+ goto fail;
+ } else {
+ // Checks whether FLAGS_HASHTREE_DISABLED is set.
+ AvbVBMetaImageHeader vbmeta_header;
+ avb_vbmeta_image_header_to_host_byte_order(
+ (AvbVBMetaImageHeader *)fs_mgr_avb_verify_data->vbmeta_images[0]
+ .vbmeta_data,
+ &vbmeta_header);
+
+ bool hashtree_disabled = ((AvbVBMetaImageFlags)vbmeta_header.flags &
+ AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
+ if (hashtree_disabled) {
+ return FS_MGR_SETUP_AVB_HASHTREE_DISABLED;
+ }
+ }
+
+ if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) {
+ return FS_MGR_SETUP_AVB_SUCCESS;
+ }
+
+fail:
+ fs_mgr_unload_vbmeta_images();
+ return FS_MGR_SETUP_AVB_FAIL;
+}
+
+void fs_mgr_unload_vbmeta_images()
+{
+ if (fs_mgr_avb_verify_data != nullptr) {
+ avb_slot_verify_data_free(fs_mgr_avb_verify_data);
+ }
+
+ if (fs_mgr_avb_ops != nullptr) {
+ fs_mgr_dummy_avb_ops_free(fs_mgr_avb_ops);
+ }
+}
+
+int fs_mgr_setup_avb(struct fstab_rec *fstab_entry)
+{
+ if (!fstab_entry || !fs_mgr_avb_verify_data ||
+ fs_mgr_avb_verify_data->num_vbmeta_images < 1) {
+ return FS_MGR_SETUP_AVB_FAIL;
+ }
+
+ std::string partition_name(basename(fstab_entry->mount_point));
+ if (!avb_validate_utf8((const uint8_t *)partition_name.c_str(),
+ partition_name.length())) {
+ ERROR("Partition name: %s is not valid UTF-8.\n",
+ partition_name.c_str());
+ return FS_MGR_SETUP_AVB_FAIL;
+ }
+
+ AvbHashtreeDescriptor hashtree_descriptor;
+ std::string salt;
+ std::string root_digest;
+ if (!get_hashtree_descriptor(partition_name, *fs_mgr_avb_verify_data,
+ &hashtree_descriptor, &salt, &root_digest)) {
+ return FS_MGR_SETUP_AVB_FAIL;
+ }
+
+ // Converts HASHTREE descriptor to verity_table_params.
+ if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt,
+ root_digest)) {
+ return FS_MGR_SETUP_AVB_FAIL;
+ }
+
+ return FS_MGR_SETUP_AVB_SUCCESS;
+}
diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp
new file mode 100644
index 0000000..f3030eb
--- /dev/null
+++ b/fs_mgr/fs_mgr_avb_ops.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <string>
+
+#include <android-base/macros.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <libavb/libavb.h>
+#include <utils/Compat.h>
+
+#include "fs_mgr.h"
+#include "fs_mgr_avb_ops.h"
+#include "fs_mgr_priv.h"
+
+static struct fstab *fs_mgr_fstab = nullptr;
+
+static AvbIOResult read_from_partition(AvbOps *ops ATTRIBUTE_UNUSED,
+ const char *partition,
+ int64_t offset,
+ size_t num_bytes,
+ void *buffer,
+ size_t *out_num_read)
+{
+ // The input |partition| name is with ab_suffix, e.g. system_a.
+ // Slot suffix (e.g. _a) will be appended to the device file path
+ // for partitions having 'slotselect' optin in fstab file, but it
+ // won't be appended to the mount point.
+ //
+ // In AVB, we can assume that there's an entry for the /misc mount
+ // point and use that to get the device file for the misc partition.
+ // From there we'll assume that a by-name scheme is used
+ // so we can just replace the trailing "misc" by the given
+ // |partition|, e.g.
+ //
+ // - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
+ // - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a
+
+ struct fstab_rec *fstab_entry =
+ fs_mgr_get_entry_for_mount_point(fs_mgr_fstab, "/misc");
+
+ if (fstab_entry == nullptr) {
+ ERROR("Partition (%s) not found in fstab\n", partition);
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ std::string partition_name(partition);
+ std::string path(fstab_entry->blk_device);
+ // Replaces the last field of device file if it's not misc.
+ if (!android::base::StartsWith(partition_name, "misc")) {
+ size_t end_slash = path.find_last_of("/");
+ std::string by_name_prefix(path.substr(0, end_slash + 1));
+ path = by_name_prefix + partition_name;
+ }
+
+ android::base::unique_fd fd(
+ TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
+
+ if (fd < 0) {
+ ERROR("Failed to open %s (%s)\n", path.c_str(), strerror(errno));
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ // If offset is negative, interprets its absolute value as the
+ // number of bytes from the end of the partition.
+ if (offset < 0) {
+ off64_t total_size = lseek64(fd, 0, SEEK_END);
+ if (total_size == -1) {
+ ERROR("Failed to lseek64 to end of the partition\n");
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ offset = total_size + offset;
+ // Repositions the offset to the beginning.
+ if (lseek64(fd, 0, SEEK_SET) == -1) {
+ ERROR("Failed to lseek64 to the beginning of the partition\n");
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ }
+
+ // On Linux, we never get partial reads from block devices (except
+ // for EOF).
+ ssize_t num_read =
+ TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset));
+
+ if (num_read < 0 || (size_t)num_read != num_bytes) {
+ ERROR("Failed to read %zu bytes from %s offset %" PRId64 " (%s)\n",
+ num_bytes, path.c_str(), offset, strerror(errno));
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ if (out_num_read != nullptr) {
+ *out_num_read = num_read;
+ }
+
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult dummy_read_rollback_index(AvbOps *ops ATTRIBUTE_UNUSED,
+ size_t rollback_index_location
+ ATTRIBUTE_UNUSED,
+ uint64_t *out_rollback_index)
+{
+ // rollback_index has been checked in bootloader phase.
+ // In user-space, returns the smallest value 0 to pass the check.
+ *out_rollback_index = 0;
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult dummy_validate_vbmeta_public_key(
+ AvbOps *ops ATTRIBUTE_UNUSED,
+ const uint8_t *public_key_data ATTRIBUTE_UNUSED,
+ size_t public_key_length ATTRIBUTE_UNUSED,
+ const uint8_t *public_key_metadata ATTRIBUTE_UNUSED,
+ size_t public_key_metadata_length ATTRIBUTE_UNUSED,
+ bool *out_is_trusted)
+{
+ // vbmeta public key has been checked in bootloader phase.
+ // In user-space, returns true to pass the check.
+ //
+ // Addtionally, user-space should check
+ // androidboot.vbmeta.{hash_alg, size, digest} against the digest
+ // of all vbmeta images after invoking avb_slot_verify().
+
+ *out_is_trusted = true;
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult dummy_read_is_device_unlocked(AvbOps *ops ATTRIBUTE_UNUSED,
+ bool *out_is_unlocked)
+{
+ // The function is for bootloader to update the value into
+ // androidboot.vbmeta.device_state in kernel cmdline.
+ // In user-space, returns true as we don't need to update it anymore.
+ *out_is_unlocked = true;
+ return AVB_IO_RESULT_OK;
+}
+
+static AvbIOResult dummy_get_unique_guid_for_partition(
+ AvbOps *ops ATTRIBUTE_UNUSED,
+ const char *partition ATTRIBUTE_UNUSED,
+ char *guid_buf,
+ size_t guid_buf_size)
+{
+ // The function is for bootloader to set the correct UUID
+ // for a given partition in kernel cmdline.
+ // In user-space, returns a faking one as we don't need to update
+ // it anymore.
+ snprintf(guid_buf, guid_buf_size, "1234-fake-guid-for:%s", partition);
+ return AVB_IO_RESULT_OK;
+}
+
+AvbOps *fs_mgr_dummy_avb_ops_new(struct fstab *fstab)
+{
+ AvbOps *ops;
+
+ // Assigns the fstab to the static variable for later use.
+ fs_mgr_fstab = fstab;
+
+ ops = (AvbOps *)calloc(1, sizeof(AvbOps));
+ if (ops == nullptr) {
+ ERROR("Error allocating memory for AvbOps.\n");
+ return nullptr;
+ }
+
+ // We only need these operations since that's all what is being used
+ // by the avb_slot_verify(); Most of them are dummy operations because
+ // they're only required in bootloader but not required in user-space.
+ ops->read_from_partition = read_from_partition;
+ ops->read_rollback_index = dummy_read_rollback_index;
+ ops->validate_vbmeta_public_key = dummy_validate_vbmeta_public_key;
+ ops->read_is_device_unlocked = dummy_read_is_device_unlocked;
+ ops->get_unique_guid_for_partition = dummy_get_unique_guid_for_partition;
+
+ return ops;
+}
+
+void fs_mgr_dummy_avb_ops_free(AvbOps *ops)
+{
+ free(ops);
+}
diff --git a/fs_mgr/fs_mgr_avb_ops.h b/fs_mgr/fs_mgr_avb_ops.h
new file mode 100644
index 0000000..9f99be8
--- /dev/null
+++ b/fs_mgr/fs_mgr_avb_ops.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef __CORE_FS_MGR_AVB_OPS_H
+#define __CORE_FS_MGR_AVB_OPS_H
+
+#include <libavb/libavb.h>
+
+#include "fs_mgr.h"
+
+__BEGIN_DECLS
+
+/* Allocates a "dummy" AvbOps instance solely for use in user-space.
+ * Returns nullptr on OOM.
+ *
+ * It mainly provides read_from_partitions() for user-space to get
+ * AvbSlotVerifyData.vbmeta_images[] and the caller MUST check their
+ * integrity against the androidboot.vbmeta.{hash_alg, size, digest}
+ * values from /proc/cmdline, e.g. verify_vbmeta_images()
+ * in fs_mgr_avb.cpp.
+ *
+ * Other I/O operations are only required in boot loader so we set
+ * them as dummy operations here.
+ * - Will allow any public key for signing.
+ * - returns 0 for any rollback index location.
+ * - returns device is unlocked regardless of the actual state.
+ * - returns a dummy guid for any partition.
+ *
+ * Frees with fs_mgr_dummy_avb_ops_free().
+ */
+AvbOps *fs_mgr_dummy_avb_ops_new(struct fstab *fstab);
+
+/* Frees an AvbOps instance previously allocated with fs_mgr_avb_ops_new(). */
+void fs_mgr_dummy_avb_ops_free(AvbOps *ops);
+
+__END_DECLS
+
+#endif /* __CORE_FS_MGR_AVB_OPS_H */
diff --git a/fs_mgr/fs_mgr_dm_ioctl.cpp b/fs_mgr/fs_mgr_dm_ioctl.cpp
index 75ce621..939657e 100644
--- a/fs_mgr/fs_mgr_dm_ioctl.cpp
+++ b/fs_mgr/fs_mgr_dm_ioctl.cpp
@@ -68,7 +68,7 @@
int fd,
std::string *out_dev_name)
{
- CHECK(out_dev_name != nullptr);
+ FS_MGR_CHECK(out_dev_name != nullptr);
fs_mgr_verity_ioctl_init(io, name, 0);
if (ioctl(fd, DM_DEV_STATUS, io)) {
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 41fb746..b9d5617 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -35,6 +35,8 @@
unsigned int zram_size;
uint64_t reserved_size;
unsigned int file_encryption_mode;
+ unsigned int erase_blk_size;
+ unsigned int logical_blk_size;
};
struct flag_list {
@@ -77,6 +79,7 @@
{ "max_comp_streams=", MF_MAX_COMP_STREAMS },
{ "verifyatboot", MF_VERIFYATBOOT },
{ "verify", MF_VERIFY },
+ { "avb", MF_AVB },
{ "noemulatedsd", MF_NOEMULATEDSD },
{ "notrim", MF_NOTRIM },
{ "formattable", MF_FORMATTABLE },
@@ -85,6 +88,8 @@
{ "latemount", MF_LATEMOUNT },
{ "reservedsize=", MF_RESERVEDSIZE },
{ "quota", MF_QUOTA },
+ { "eraseblk=", MF_ERASEBLKSIZE },
+ { "logicalblk=", MF_LOGICALBLKSIZE },
{ "defaults", 0 },
{ 0, 0 },
};
@@ -239,6 +244,22 @@
* reserved size of the partition. Get it and return it.
*/
flag_vals->reserved_size = parse_size(strchr(p, '=') + 1);
+ } else if ((fl[i].flag == MF_ERASEBLKSIZE) && flag_vals) {
+ /* The erase block size flag is followed by an = and the flash
+ * erase block size. Get it, check that it is a power of 2 and
+ * at least 4096, and return it.
+ */
+ unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
+ if (val >= 4096 && (val & (val - 1)) == 0)
+ flag_vals->erase_blk_size = val;
+ } else if ((fl[i].flag == MF_LOGICALBLKSIZE) && flag_vals) {
+ /* The logical block size flag is followed by an = and the flash
+ * logical block size. Get it, check that it is a power of 2 and
+ * at least 4096, and return it.
+ */
+ unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
+ if (val >= 4096 && (val & (val - 1)) == 0)
+ flag_vals->logical_blk_size = val;
}
break;
}
@@ -385,6 +406,8 @@
fstab->recs[cnt].zram_size = flag_vals.zram_size;
fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
fstab->recs[cnt].file_encryption_mode = flag_vals.file_encryption_mode;
+ fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size;
+ fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size;
cnt++;
}
/* If an A/B partition, modify block device to be the real block device */
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 7f917d9..0a27c7a 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -20,6 +20,17 @@
#include <cutils/klog.h>
#include <fs_mgr.h>
+#ifdef __cplusplus
+#include <android-base/logging.h>
+/* The CHECK() in logging.h will use program invocation name as the tag.
+ * Thus, the log will have prefix "init: " when libfs_mgr is statically
+ * linked in the init process. This might be opaque when debugging.
+ * Appends "in libfs_mgr" at the end of the abort message to explicitly
+ * indicate the check happens in fs_mgr.
+ */
+#define FS_MGR_CHECK(x) CHECK(x) << "in libfs_mgr "
+#endif
+
__BEGIN_DECLS
#define INFO(x...) KLOG_INFO("fs_mgr", x)
@@ -89,6 +100,9 @@
#define MF_MAX_COMP_STREAMS 0x100000
#define MF_RESERVEDSIZE 0x200000
#define MF_QUOTA 0x400000
+#define MF_ERASEBLKSIZE 0x800000
+#define MF_LOGICALBLKSIZE 0X1000000
+#define MF_AVB 0X2000000
#define DM_BUF_SIZE 4096
diff --git a/fs_mgr/fs_mgr_priv_avb.h b/fs_mgr/fs_mgr_priv_avb.h
new file mode 100644
index 0000000..6d0171c
--- /dev/null
+++ b/fs_mgr/fs_mgr_priv_avb.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef __CORE_FS_MGR_PRIV_AVB_H
+#define __CORE_FS_MGR_PRIV_AVB_H
+
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+#include "fs_mgr.h"
+
+__BEGIN_DECLS
+
+#define FS_MGR_SETUP_AVB_HASHTREE_DISABLED (-2)
+#define FS_MGR_SETUP_AVB_FAIL (-1)
+#define FS_MGR_SETUP_AVB_SUCCESS 0
+
+bool fs_mgr_is_avb_used();
+
+/* Gets AVB metadata through external/avb/libavb for all partitions:
+ * AvbSlotVerifyData.vbmeta_images[] and checks their integrity
+ * against the androidboot.vbmeta.{hash_alg, size, digest} values
+ * from /proc/cmdline.
+ *
+ * Return values:
+ * - FS_MGR_SETUP_AVB_SUCCESS: the metadata cab be trusted.
+ * - FS_MGR_SETUP_AVB_FAIL: any error when reading and verifying the
+ * metadata, e.g. I/O error, digest value mismatch, size mismatch.
+ * - FS_MGR_SETUP_AVB_HASHTREE_DISABLED: to support the existing
+ * 'adb disable-verity' feature in Android. It's very helpful for
+ * developers to make the filesystem writable to allow replacing
+ * binaries on the device.
+ */
+int fs_mgr_load_vbmeta_images(struct fstab *fstab);
+
+void fs_mgr_unload_vbmeta_images();
+
+int fs_mgr_setup_avb(struct fstab_rec *fstab_entry);
+
+__END_DECLS
+
+#endif /* __CORE_FS_MGR_PRIV_AVB_H */
diff --git a/fs_mgr/fs_mgr_priv_sha.h b/fs_mgr/fs_mgr_priv_sha.h
new file mode 100644
index 0000000..1abc273
--- /dev/null
+++ b/fs_mgr/fs_mgr_priv_sha.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef __CORE_FS_MGR_PRIV_SHA_H
+#define __CORE_FS_MGR_PRIV_SHA_H
+
+#include <openssl/sha.h>
+
+class SHA256Hasher
+{
+ private:
+ SHA256_CTX sha256_ctx;
+ uint8_t hash[SHA256_DIGEST_LENGTH];
+
+ public:
+ enum { DIGEST_SIZE = SHA256_DIGEST_LENGTH };
+
+ SHA256Hasher()
+ {
+ SHA256_Init(&sha256_ctx);
+ }
+
+ void update(const void *data, size_t data_size)
+ {
+ SHA256_Update(&sha256_ctx, data, data_size);
+ }
+
+ const uint8_t *finalize()
+ {
+ SHA256_Final(hash, &sha256_ctx);
+ return hash;
+ }
+};
+
+class SHA512Hasher
+{
+ private:
+ SHA512_CTX sha512_ctx;
+ uint8_t hash[SHA512_DIGEST_LENGTH];
+
+ public:
+ enum { DIGEST_SIZE = SHA512_DIGEST_LENGTH };
+
+ SHA512Hasher()
+ {
+ SHA512_Init(&sha512_ctx);
+ }
+
+ void update(const uint8_t *data, size_t data_size)
+ {
+ SHA512_Update(&sha512_ctx, data, data_size);
+ }
+
+ const uint8_t *finalize()
+ {
+ SHA512_Final(hash, &sha512_ctx);
+ return hash;
+ }
+};
+
+#endif /* __CORE_FS_MGR_PRIV_SHA_H */
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index ef7fdd3..d959798 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -77,6 +77,8 @@
unsigned int zram_size;
uint64_t reserved_size;
unsigned int file_encryption_mode;
+ unsigned int erase_blk_size;
+ unsigned int logical_blk_size;
};
// Callback function for verity status
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 36c4664..2f69372 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -30,6 +30,8 @@
#include <time.h>
#include <unistd.h>
+#include <functional>
+
#include <android-base/file.h>
#include <android-base/stringprintf.h>
@@ -42,6 +44,7 @@
#include <cutils/misc.h>
#include <cutils/uevent.h>
#include <cutils/properties.h>
+#include <minui/minui.h>
#ifdef CHARGER_ENABLE_SUSPEND
#include <suspend/autosuspend.h>
@@ -49,7 +52,6 @@
#include "animation.h"
#include "AnimationParser.h"
-#include "minui/minui.h"
#include <healthd/healthd.h>
@@ -563,9 +565,8 @@
}
}
-static int set_key_callback(int code, int value, void *data)
+static int set_key_callback(struct charger *charger, int code, int value)
{
- struct charger *charger = (struct charger *)data;
int64_t now = curr_time_ms();
int down = !!value;
@@ -600,7 +601,7 @@
{
if (ev->type != EV_KEY)
return;
- set_key_callback(ev->code, ev->value, charger);
+ set_key_callback(charger, ev->code, ev->value);
}
static void set_next_key_check(struct charger *charger,
@@ -757,9 +758,8 @@
return (int)timeout;
}
-static int input_callback(int fd, unsigned int epevents, void *data)
+static int input_callback(struct charger *charger, int fd, unsigned int epevents)
{
- struct charger *charger = (struct charger *)data;
struct input_event ev;
int ret;
@@ -836,7 +836,8 @@
LOGW("--------------- STARTING CHARGER MODE ---------------\n");
- ret = ev_init(input_callback, charger);
+ ret = ev_init(std::bind(&input_callback, charger, std::placeholders::_1,
+ std::placeholders::_2));
if (!ret) {
epollfd = ev_get_epollfd();
healthd_register_event(epollfd, charger_event_handler);
@@ -875,7 +876,8 @@
anim->frames[i].surface = scale_frames[i];
}
}
- ev_sync_key_state(set_key_callback, charger);
+ ev_sync_key_state(std::bind(&set_key_callback, charger, std::placeholders::_1,
+ std::placeholders::_2));
charger->next_screen_transition = -1;
charger->next_key_check = -1;
diff --git a/include/cutils b/include/cutils
deleted file mode 120000
index ac2ed40..0000000
--- a/include/cutils
+++ /dev/null
@@ -1 +0,0 @@
-../libcutils/include/cutils/
\ No newline at end of file
diff --git a/libcutils/include/cutils/android_get_control_file.h b/include/cutils/android_get_control_file.h
similarity index 100%
rename from libcutils/include/cutils/android_get_control_file.h
rename to include/cutils/android_get_control_file.h
diff --git a/libcutils/include/cutils/android_reboot.h b/include/cutils/android_reboot.h
similarity index 100%
rename from libcutils/include/cutils/android_reboot.h
rename to include/cutils/android_reboot.h
diff --git a/libcutils/include/cutils/ashmem.h b/include/cutils/ashmem.h
similarity index 100%
rename from libcutils/include/cutils/ashmem.h
rename to include/cutils/ashmem.h
diff --git a/libcutils/include/cutils/atomic.h b/include/cutils/atomic.h
similarity index 100%
rename from libcutils/include/cutils/atomic.h
rename to include/cutils/atomic.h
diff --git a/libcutils/include/cutils/bitops.h b/include/cutils/bitops.h
similarity index 100%
rename from libcutils/include/cutils/bitops.h
rename to include/cutils/bitops.h
diff --git a/libcutils/include/cutils/compiler.h b/include/cutils/compiler.h
similarity index 100%
rename from libcutils/include/cutils/compiler.h
rename to include/cutils/compiler.h
diff --git a/libcutils/include/cutils/config_utils.h b/include/cutils/config_utils.h
similarity index 100%
rename from libcutils/include/cutils/config_utils.h
rename to include/cutils/config_utils.h
diff --git a/libcutils/include/cutils/fs.h b/include/cutils/fs.h
similarity index 100%
rename from libcutils/include/cutils/fs.h
rename to include/cutils/fs.h
diff --git a/libcutils/include/cutils/hashmap.h b/include/cutils/hashmap.h
similarity index 100%
rename from libcutils/include/cutils/hashmap.h
rename to include/cutils/hashmap.h
diff --git a/libcutils/include/cutils/iosched_policy.h b/include/cutils/iosched_policy.h
similarity index 100%
rename from libcutils/include/cutils/iosched_policy.h
rename to include/cutils/iosched_policy.h
diff --git a/libcutils/include/cutils/jstring.h b/include/cutils/jstring.h
similarity index 100%
rename from libcutils/include/cutils/jstring.h
rename to include/cutils/jstring.h
diff --git a/libcutils/include/cutils/klog.h b/include/cutils/klog.h
similarity index 97%
rename from libcutils/include/cutils/klog.h
rename to include/cutils/klog.h
index e7cd300..5ae6216 100644
--- a/libcutils/include/cutils/klog.h
+++ b/include/cutils/klog.h
@@ -23,7 +23,6 @@
__BEGIN_DECLS
-int klog_get_level(void);
void klog_set_level(int level);
void klog_write(int level, const char *fmt, ...)
diff --git a/libcutils/include/cutils/list.h b/include/cutils/list.h
similarity index 100%
rename from libcutils/include/cutils/list.h
rename to include/cutils/list.h
diff --git a/libcutils/include/cutils/log.h b/include/cutils/log.h
similarity index 100%
rename from libcutils/include/cutils/log.h
rename to include/cutils/log.h
diff --git a/libcutils/include/cutils/memory.h b/include/cutils/memory.h
similarity index 100%
rename from libcutils/include/cutils/memory.h
rename to include/cutils/memory.h
diff --git a/libcutils/include/cutils/misc.h b/include/cutils/misc.h
similarity index 100%
rename from libcutils/include/cutils/misc.h
rename to include/cutils/misc.h
diff --git a/libcutils/include/cutils/multiuser.h b/include/cutils/multiuser.h
similarity index 100%
rename from libcutils/include/cutils/multiuser.h
rename to include/cutils/multiuser.h
diff --git a/libcutils/include/cutils/native_handle.h b/include/cutils/native_handle.h
similarity index 100%
rename from libcutils/include/cutils/native_handle.h
rename to include/cutils/native_handle.h
diff --git a/libcutils/include/cutils/open_memstream.h b/include/cutils/open_memstream.h
similarity index 100%
rename from libcutils/include/cutils/open_memstream.h
rename to include/cutils/open_memstream.h
diff --git a/libcutils/include/cutils/partition_utils.h b/include/cutils/partition_utils.h
similarity index 100%
rename from libcutils/include/cutils/partition_utils.h
rename to include/cutils/partition_utils.h
diff --git a/libcutils/include/cutils/properties.h b/include/cutils/properties.h
similarity index 100%
rename from libcutils/include/cutils/properties.h
rename to include/cutils/properties.h
diff --git a/libcutils/include/cutils/qtaguid.h b/include/cutils/qtaguid.h
similarity index 100%
rename from libcutils/include/cutils/qtaguid.h
rename to include/cutils/qtaguid.h
diff --git a/libcutils/include/cutils/record_stream.h b/include/cutils/record_stream.h
similarity index 100%
rename from libcutils/include/cutils/record_stream.h
rename to include/cutils/record_stream.h
diff --git a/libcutils/include/cutils/sched_policy.h b/include/cutils/sched_policy.h
similarity index 100%
rename from libcutils/include/cutils/sched_policy.h
rename to include/cutils/sched_policy.h
diff --git a/libcutils/include/cutils/sockets.h b/include/cutils/sockets.h
similarity index 100%
rename from libcutils/include/cutils/sockets.h
rename to include/cutils/sockets.h
diff --git a/libcutils/include/cutils/str_parms.h b/include/cutils/str_parms.h
similarity index 100%
rename from libcutils/include/cutils/str_parms.h
rename to include/cutils/str_parms.h
diff --git a/libcutils/include/cutils/threads.h b/include/cutils/threads.h
similarity index 100%
rename from libcutils/include/cutils/threads.h
rename to include/cutils/threads.h
diff --git a/libcutils/include/cutils/trace.h b/include/cutils/trace.h
similarity index 100%
rename from libcutils/include/cutils/trace.h
rename to include/cutils/trace.h
diff --git a/libcutils/include/cutils/uevent.h b/include/cutils/uevent.h
similarity index 100%
rename from libcutils/include/cutils/uevent.h
rename to include/cutils/uevent.h
diff --git a/include/log b/include/log
deleted file mode 120000
index 714065f..0000000
--- a/include/log
+++ /dev/null
@@ -1 +0,0 @@
-../liblog/include/log
\ No newline at end of file
diff --git a/liblog/include/log/event_tag_map.h b/include/log/event_tag_map.h
similarity index 100%
rename from liblog/include/log/event_tag_map.h
rename to include/log/event_tag_map.h
diff --git a/liblog/include/log/log.h b/include/log/log.h
similarity index 100%
rename from liblog/include/log/log.h
rename to include/log/log.h
diff --git a/liblog/include/log/log_event_list.h b/include/log/log_event_list.h
similarity index 100%
rename from liblog/include/log/log_event_list.h
rename to include/log/log_event_list.h
diff --git a/libcutils/include/cutils/log.h b/include/log/logd.h
similarity index 100%
copy from libcutils/include/cutils/log.h
copy to include/log/logd.h
diff --git a/libcutils/include/cutils/log.h b/include/log/logger.h
similarity index 100%
copy from libcutils/include/cutils/log.h
copy to include/log/logger.h
diff --git a/liblog/include/log/logprint.h b/include/log/logprint.h
similarity index 100%
rename from liblog/include/log/logprint.h
rename to include/log/logprint.h
diff --git a/liblog/include/log/uio.h b/include/log/uio.h
similarity index 100%
rename from liblog/include/log/uio.h
rename to include/log/uio.h
diff --git a/include/private/android_logger.h b/include/private/android_logger.h
deleted file mode 120000
index f187a6d..0000000
--- a/include/private/android_logger.h
+++ /dev/null
@@ -1 +0,0 @@
-../../liblog/include/private/android_logger.h
\ No newline at end of file
diff --git a/liblog/include/private/android_logger.h b/include/private/android_logger.h
similarity index 100%
rename from liblog/include/private/android_logger.h
rename to include/private/android_logger.h
diff --git a/init/Android.mk b/init/Android.mk
index 35e6f4f..759be52 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -107,6 +107,7 @@
libz \
libprocessgroup \
libnl \
+ libavb
# Create symlinks.
LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 72fcb5b..d323425 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -27,6 +27,7 @@
#include <sys/poll.h>
#include <memory>
+#include <vector>
#include <cutils/misc.h>
#include <cutils/sockets.h>
@@ -48,6 +49,7 @@
#include <fs_mgr.h>
#include <android-base/file.h>
+#include <android-base/strings.h>
#include "bootimg.h"
#include "property_service.h"
@@ -70,30 +72,30 @@
}
}
-static int check_mac_perms(const char *name, char *sctx, struct ucred *cr)
-{
- char *tctx = NULL;
- int result = 0;
+static bool check_mac_perms(const std::string& name, char* sctx, struct ucred* cr) {
+
+ if (!sctx) {
+ return false;
+ }
+
+ if (!sehandle_prop) {
+ return false;
+ }
+
+ char* tctx = nullptr;
+ if (selabel_lookup(sehandle_prop, &tctx, name.c_str(), 1) != 0) {
+ return false;
+ }
+
property_audit_data audit_data;
- if (!sctx)
- goto err;
-
- if (!sehandle_prop)
- goto err;
-
- if (selabel_lookup(sehandle_prop, &tctx, name, 1) != 0)
- goto err;
-
- audit_data.name = name;
+ audit_data.name = name.c_str();
audit_data.cr = cr;
- if (selinux_check_access(sctx, tctx, "property_service", "set", reinterpret_cast<void*>(&audit_data)) == 0)
- result = 1;
+ bool has_access = (selinux_check_access(sctx, tctx, "property_service", "set", &audit_data) == 0);
freecon(tctx);
- err:
- return result;
+ return has_access;
}
static int check_control_mac_perms(const char *name, char *sctx, struct ucred *cr)
@@ -142,11 +144,9 @@
}
}
-bool is_legal_property_name(const std::string &name)
-{
+bool is_legal_property_name(const std::string& name) {
size_t namelen = name.size();
- if (namelen >= PROP_NAME_MAX) return false;
if (namelen < 1) return false;
if (name[0] == '.') return false;
if (name[namelen - 1] == '.') return false;
@@ -169,60 +169,219 @@
return true;
}
-int property_set(const char* name, const char* value) {
- size_t valuelen = strlen(value);
+uint32_t property_set(const std::string& name, const std::string& value) {
+ size_t valuelen = value.size();
if (!is_legal_property_name(name)) {
LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: bad name";
- return -1;
+ return PROP_ERROR_INVALID_NAME;
}
+
if (valuelen >= PROP_VALUE_MAX) {
LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
<< "value too long";
- return -1;
+ return PROP_ERROR_INVALID_VALUE;
}
- if (strcmp("selinux.restorecon_recursive", name) == 0 && valuelen > 0) {
- if (restorecon(value, SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
+ if (name == "selinux.restorecon_recursive" && valuelen > 0) {
+ if (restorecon(value.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
LOG(ERROR) << "Failed to restorecon_recursive " << value;
}
}
- prop_info* pi = (prop_info*) __system_property_find(name);
+ prop_info* pi = (prop_info*) __system_property_find(name.c_str());
if (pi != nullptr) {
// ro.* properties are actually "write-once".
- if (!strncmp(name, "ro.", 3)) {
+ if (android::base::StartsWith(name, "ro.")) {
LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
<< "property already set";
- return -1;
+ return PROP_ERROR_READ_ONLY_PROPERTY;
}
- __system_property_update(pi, value, valuelen);
+ __system_property_update(pi, value.c_str(), valuelen);
} else {
- int rc = __system_property_add(name, strlen(name), value, valuelen);
+ int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
if (rc < 0) {
LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
<< "__system_property_add failed";
- return rc;
+ return PROP_ERROR_SET_FAILED;
}
}
// Don't write properties to disk until after we have read all default
// properties to prevent them from being overwritten by default values.
- if (persistent_properties_loaded && strncmp("persist.", name, strlen("persist.")) == 0) {
- write_persistent_property(name, value);
+ if (persistent_properties_loaded && android::base::StartsWith(name, "persist.")) {
+ write_persistent_property(name.c_str(), value.c_str());
}
- property_changed(name, value);
- return 0;
+ property_changed(name.c_str(), value.c_str());
+ return PROP_SUCCESS;
}
-static void handle_property_set_fd()
-{
- prop_msg msg;
- int r;
- char * source_ctx = NULL;
+class SocketConnection {
+ public:
+ SocketConnection(int socket, const struct ucred& cred)
+ : socket_(socket), cred_(cred) {}
- int s = accept(property_set_fd, nullptr, nullptr);
+ ~SocketConnection() {
+ close(socket_);
+ }
+
+ bool RecvUint32(uint32_t* value, uint32_t* timeout_ms) {
+ return RecvFully(value, sizeof(*value), timeout_ms);
+ }
+
+ bool RecvChars(char* chars, size_t size, uint32_t* timeout_ms) {
+ return RecvFully(chars, size, timeout_ms);
+ }
+
+ bool RecvString(std::string* value, uint32_t* timeout_ms) {
+ uint32_t len = 0;
+ if (!RecvUint32(&len, timeout_ms)) {
+ return false;
+ }
+
+ if (len == 0) {
+ *value = "";
+ return true;
+ }
+
+ std::vector<char> chars(len);
+ if (!RecvChars(&chars[0], len, timeout_ms)) {
+ return false;
+ }
+
+ *value = std::string(&chars[0], len);
+ return true;
+ }
+
+ bool SendUint32(uint32_t value) {
+ int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0));
+ return result == sizeof(value);
+ }
+
+ int socket() {
+ return socket_;
+ }
+
+ const struct ucred& cred() {
+ return cred_;
+ }
+
+ private:
+ bool PollIn(uint32_t* timeout_ms) {
+ struct pollfd ufds[1];
+ ufds[0].fd = socket_;
+ ufds[0].events = POLLIN;
+ ufds[0].revents = 0;
+ while (*timeout_ms > 0) {
+ Timer timer;
+ int nr = poll(ufds, 1, *timeout_ms);
+ uint64_t millis = timer.duration_ns()/1000000;
+ *timeout_ms = (millis > *timeout_ms) ? 0 : *timeout_ms - millis;
+
+ if (nr > 0) {
+ return true;
+ }
+
+ if (nr == 0) {
+ // Timeout
+ break;
+ }
+
+ if (nr < 0 && errno != EINTR) {
+ PLOG(ERROR) << "sys_prop: error waiting for uid " << cred_.uid << " to send property message";
+ return false;
+ } else { // errno == EINTR
+ // Timer rounds milliseconds down in case of EINTR we want it to be rounded up
+ // to avoid slowing init down by causing EINTR with under millisecond timeout.
+ if (*timeout_ms > 0) {
+ --(*timeout_ms);
+ }
+ }
+ }
+
+ LOG(ERROR) << "sys_prop: timeout waiting for uid " << cred_.uid << " to send property message.";
+ return false;
+ }
+
+ bool RecvFully(void* data_ptr, size_t size, uint32_t* timeout_ms) {
+ size_t bytes_left = size;
+ char* data = static_cast<char*>(data_ptr);
+ while (*timeout_ms > 0 && bytes_left > 0) {
+ if (!PollIn(timeout_ms)) {
+ return false;
+ }
+
+ int result = TEMP_FAILURE_RETRY(recv(socket_, data, bytes_left, MSG_DONTWAIT));
+ if (result <= 0) {
+ return false;
+ }
+
+ bytes_left -= result;
+ data += result;
+ }
+
+ return bytes_left == 0;
+ }
+
+ int socket_;
+ struct ucred cred_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection);
+};
+
+static void handle_property_set(SocketConnection& socket,
+ const std::string& name,
+ const std::string& value,
+ bool legacy_protocol) {
+ const char* cmd_name = legacy_protocol ? "PROP_MSG_SETPROP" : "PROP_MSG_SETPROP2";
+ if (!is_legal_property_name(name)) {
+ LOG(ERROR) << "sys_prop(" << cmd_name << "): illegal property name \"" << name << "\"";
+ socket.SendUint32(PROP_ERROR_INVALID_NAME);
+ return;
+ }
+
+ struct ucred cr = socket.cred();
+ char* source_ctx = nullptr;
+ getpeercon(socket.socket(), &source_ctx);
+
+ if (android::base::StartsWith(name, "ctl.")) {
+ if (check_control_mac_perms(value.c_str(), source_ctx, &cr)) {
+ handle_control_message(name.c_str() + 4, value.c_str());
+ if (!legacy_protocol) {
+ socket.SendUint32(PROP_SUCCESS);
+ }
+ } else {
+ LOG(ERROR) << "sys_prop(" << cmd_name << "): Unable to " << (name.c_str() + 4)
+ << " service ctl [" << value << "]"
+ << " uid:" << cr.uid
+ << " gid:" << cr.gid
+ << " pid:" << cr.pid;
+ if (!legacy_protocol) {
+ socket.SendUint32(PROP_ERROR_HANDLE_CONTROL_MESSAGE);
+ }
+ }
+ } else {
+ if (check_mac_perms(name, source_ctx, &cr)) {
+ uint32_t result = property_set(name, value);
+ if (!legacy_protocol) {
+ socket.SendUint32(result);
+ }
+ } else {
+ LOG(ERROR) << "sys_prop(" << cmd_name << "): permission denied uid:" << cr.uid << " name:" << name;
+ if (!legacy_protocol) {
+ socket.SendUint32(PROP_ERROR_PERMISSION_DENIED);
+ }
+ }
+ }
+
+ freecon(source_ctx);
+}
+
+static void handle_property_set_fd() {
+ static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */
+
+ int s = accept4(property_set_fd, nullptr, nullptr, SOCK_CLOEXEC);
if (s == -1) {
return;
}
@@ -236,72 +395,50 @@
return;
}
- static constexpr int timeout_ms = 2 * 1000; /* Default 2 sec timeout for caller to send property. */
- struct pollfd ufds[1];
- ufds[0].fd = s;
- ufds[0].events = POLLIN;
- ufds[0].revents = 0;
- int nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms));
- if (nr == 0) {
- LOG(ERROR) << "sys_prop: timeout waiting for uid " << cr.uid << " to send property message.";
- close(s);
- return;
- } else if (nr < 0) {
- PLOG(ERROR) << "sys_prop: error waiting for uid " << cr.uid << " to send property message";
- close(s);
+ SocketConnection socket(s, cr);
+ uint32_t timeout_ms = kDefaultSocketTimeout;
+
+ uint32_t cmd = 0;
+
+ if (!socket.RecvUint32(&cmd, &timeout_ms)) {
+ PLOG(ERROR) << "sys_prop: error while reading command from the socket";
+ socket.SendUint32(PROP_ERROR_READ_CMD);
return;
}
- r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), MSG_DONTWAIT));
- if(r != sizeof(prop_msg)) {
- PLOG(ERROR) << "sys_prop: mis-match msg size received: " << r << " expected: " << sizeof(prop_msg);
- close(s);
- return;
- }
+ switch(cmd) {
+ case PROP_MSG_SETPROP: {
+ char prop_name[PROP_NAME_MAX];
+ char prop_value[PROP_VALUE_MAX];
- switch(msg.cmd) {
- case PROP_MSG_SETPROP:
- msg.name[PROP_NAME_MAX-1] = 0;
- msg.value[PROP_VALUE_MAX-1] = 0;
-
- if (!is_legal_property_name(msg.name)) {
- LOG(ERROR) << "sys_prop: illegal property name \"" << msg.name << "\"";
- close(s);
- return;
+ if (!socket.RecvChars(prop_name, PROP_NAME_MAX, &timeout_ms) ||
+ !socket.RecvChars(prop_value, PROP_VALUE_MAX, &timeout_ms)) {
+ PLOG(ERROR) << "sys_prop(PROP_MSG_SETPROP): error while reading name/value from the socket";
+ return;
}
- getpeercon(s, &source_ctx);
+ prop_name[PROP_NAME_MAX-1] = 0;
+ prop_value[PROP_VALUE_MAX-1] = 0;
- if(memcmp(msg.name,"ctl.",4) == 0) {
- // Keep the old close-socket-early behavior when handling
- // ctl.* properties.
- close(s);
- if (check_control_mac_perms(msg.value, source_ctx, &cr)) {
- handle_control_message((char*) msg.name + 4, (char*) msg.value);
- } else {
- LOG(ERROR) << "sys_prop: Unable to " << (msg.name + 4)
- << " service ctl [" << msg.value << "]"
- << " uid:" << cr.uid
- << " gid:" << cr.gid
- << " pid:" << cr.pid;
- }
- } else {
- if (check_mac_perms(msg.name, source_ctx, &cr)) {
- property_set((char*) msg.name, (char*) msg.value);
- } else {
- LOG(ERROR) << "sys_prop: permission denied uid:" << cr.uid << " name:" << msg.name;
- }
-
- // Note: bionic's property client code assumes that the
- // property server will not close the socket until *AFTER*
- // the property is written to memory.
- close(s);
- }
- freecon(source_ctx);
+ handle_property_set(socket, prop_value, prop_value, true);
break;
+ }
+ case PROP_MSG_SETPROP2: {
+ std::string name;
+ std::string value;
+ if (!socket.RecvString(&name, &timeout_ms) ||
+ !socket.RecvString(&value, &timeout_ms)) {
+ PLOG(ERROR) << "sys_prop(PROP_MSG_SETPROP2): error while reading name/value from the socket";
+ socket.SendUint32(PROP_ERROR_READ_DATA);
+ return;
+ }
+
+ handle_property_set(socket, name, value, false);
+ break;
+ }
default:
- close(s);
+ socket.SendUint32(PROP_ERROR_INVALID_CMD);
break;
}
}
@@ -510,6 +647,8 @@
}
void start_property_service() {
+ property_set("ro.property_service.version", "2");
+
property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
0666, 0, 0, NULL);
if (property_set_fd == -1) {
diff --git a/init/property_service.h b/init/property_service.h
index e3a2acb..5d59473 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -27,14 +27,14 @@
const char* name;
};
-extern void property_init(void);
-extern void property_load_boot_defaults(void);
-extern void load_persist_props(void);
-extern void load_system_props(void);
-extern void start_property_service(void);
+void property_init(void);
+void property_load_boot_defaults(void);
+void load_persist_props(void);
+void load_system_props(void);
+void start_property_service(void);
std::string property_get(const char* name);
-extern int property_set(const char *name, const char *value);
-extern bool is_legal_property_name(const std::string &name);
+uint32_t property_set(const std::string& name, const std::string& value);
+bool is_legal_property_name(const std::string& name);
#endif /* _INIT_PROPERTY_H */
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index f6c0f0e..b96e3ae 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -30,23 +30,6 @@
"str_parms.c",
]
-cc_library_headers {
- name: "libcutils_vndk_headers",
- host_supported: true,
- export_include_dirs: ["include_vndk"],
-}
-
-cc_library_headers {
- name: "libcutils_headers",
- host_supported: true,
- export_include_dirs: ["include"],
- target: {
- windows: {
- enabled: true,
- },
- },
-}
-
cc_library {
name: "libcutils",
host_supported: true,
@@ -68,7 +51,6 @@
"threads.c",
],
-
target: {
host: {
srcs: ["dlmalloc_stubs.c"],
@@ -135,9 +117,6 @@
},
shared_libs: ["liblog"],
- header_libs: ["libcutils_headers"],
- export_header_lib_headers: ["libcutils_headers"],
-
product_variables: {
cpusets: {
cflags: ["-DUSE_CPUSETS"],
diff --git a/libcutils/include_vndk/cutils/android_get_control_file.h b/libcutils/include_vndk/cutils/android_get_control_file.h
deleted file mode 120000
index 70d6a3b..0000000
--- a/libcutils/include_vndk/cutils/android_get_control_file.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/android_get_control_file.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/android_reboot.h b/libcutils/include_vndk/cutils/android_reboot.h
deleted file mode 120000
index 9e1bf4c..0000000
--- a/libcutils/include_vndk/cutils/android_reboot.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/android_reboot.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/ashmem.h b/libcutils/include_vndk/cutils/ashmem.h
deleted file mode 120000
index 5c07beb..0000000
--- a/libcutils/include_vndk/cutils/ashmem.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/ashmem.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/atomic.h b/libcutils/include_vndk/cutils/atomic.h
deleted file mode 120000
index f4f14fe..0000000
--- a/libcutils/include_vndk/cutils/atomic.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/atomic.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/bitops.h b/libcutils/include_vndk/cutils/bitops.h
deleted file mode 120000
index edbd60c..0000000
--- a/libcutils/include_vndk/cutils/bitops.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/bitops.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/compiler.h b/libcutils/include_vndk/cutils/compiler.h
deleted file mode 120000
index 08ebc10..0000000
--- a/libcutils/include_vndk/cutils/compiler.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/compiler.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/config_utils.h b/libcutils/include_vndk/cutils/config_utils.h
deleted file mode 120000
index e011738..0000000
--- a/libcutils/include_vndk/cutils/config_utils.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/config_utils.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/fs.h b/libcutils/include_vndk/cutils/fs.h
deleted file mode 120000
index 576bfa3..0000000
--- a/libcutils/include_vndk/cutils/fs.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/fs.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/hashmap.h b/libcutils/include_vndk/cutils/hashmap.h
deleted file mode 120000
index 6b18406..0000000
--- a/libcutils/include_vndk/cutils/hashmap.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/hashmap.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/iosched_policy.h b/libcutils/include_vndk/cutils/iosched_policy.h
deleted file mode 120000
index 26cf333..0000000
--- a/libcutils/include_vndk/cutils/iosched_policy.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/iosched_policy.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/jstring.h b/libcutils/include_vndk/cutils/jstring.h
deleted file mode 120000
index f3fd546..0000000
--- a/libcutils/include_vndk/cutils/jstring.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/jstring.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/klog.h b/libcutils/include_vndk/cutils/klog.h
deleted file mode 120000
index 8ca85ff..0000000
--- a/libcutils/include_vndk/cutils/klog.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/klog.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/list.h b/libcutils/include_vndk/cutils/list.h
deleted file mode 120000
index 9fa4c90..0000000
--- a/libcutils/include_vndk/cutils/list.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/list.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/log.h b/libcutils/include_vndk/cutils/log.h
deleted file mode 100644
index ae74024..0000000
--- a/libcutils/include_vndk/cutils/log.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*Special log.h file for VNDK linking modules*/
-/*
- * Copyright (C) 2005-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.
-*/
-#ifndef _LIBS_CUTIL_LOG_H
-#define _LIBS_CUTIL_LOG_H
-#warning "Deprecated: don't include cutils/log.h, use either android/log.h or log/log.h"
-#include <log/log.h>
-#endif /* _LIBS_CUTIL_LOG_H */
diff --git a/libcutils/include_vndk/cutils/memory.h b/libcutils/include_vndk/cutils/memory.h
deleted file mode 120000
index e0e7abc..0000000
--- a/libcutils/include_vndk/cutils/memory.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/memory.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/misc.h b/libcutils/include_vndk/cutils/misc.h
deleted file mode 120000
index db09eb5..0000000
--- a/libcutils/include_vndk/cutils/misc.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/misc.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/multiuser.h b/libcutils/include_vndk/cutils/multiuser.h
deleted file mode 120000
index 524111f..0000000
--- a/libcutils/include_vndk/cutils/multiuser.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/multiuser.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/native_handle.h b/libcutils/include_vndk/cutils/native_handle.h
deleted file mode 120000
index e324d4e..0000000
--- a/libcutils/include_vndk/cutils/native_handle.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/native_handle.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/open_memstream.h b/libcutils/include_vndk/cutils/open_memstream.h
deleted file mode 120000
index c894084..0000000
--- a/libcutils/include_vndk/cutils/open_memstream.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/open_memstream.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/partition_utils.h b/libcutils/include_vndk/cutils/partition_utils.h
deleted file mode 120000
index d9734c8..0000000
--- a/libcutils/include_vndk/cutils/partition_utils.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/partition_utils.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/properties.h b/libcutils/include_vndk/cutils/properties.h
deleted file mode 120000
index d56118e..0000000
--- a/libcutils/include_vndk/cutils/properties.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/properties.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/qtaguid.h b/libcutils/include_vndk/cutils/qtaguid.h
deleted file mode 120000
index bc02441..0000000
--- a/libcutils/include_vndk/cutils/qtaguid.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/qtaguid.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/record_stream.h b/libcutils/include_vndk/cutils/record_stream.h
deleted file mode 120000
index 8de6494..0000000
--- a/libcutils/include_vndk/cutils/record_stream.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/record_stream.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/sched_policy.h b/libcutils/include_vndk/cutils/sched_policy.h
deleted file mode 120000
index ddebdd0..0000000
--- a/libcutils/include_vndk/cutils/sched_policy.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/sched_policy.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/sockets.h b/libcutils/include_vndk/cutils/sockets.h
deleted file mode 120000
index 585250c..0000000
--- a/libcutils/include_vndk/cutils/sockets.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/sockets.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/str_parms.h b/libcutils/include_vndk/cutils/str_parms.h
deleted file mode 120000
index 9c79a8f..0000000
--- a/libcutils/include_vndk/cutils/str_parms.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/str_parms.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/threads.h b/libcutils/include_vndk/cutils/threads.h
deleted file mode 120000
index 99330ff..0000000
--- a/libcutils/include_vndk/cutils/threads.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/threads.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/trace.h b/libcutils/include_vndk/cutils/trace.h
deleted file mode 120000
index b12e140..0000000
--- a/libcutils/include_vndk/cutils/trace.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/trace.h
\ No newline at end of file
diff --git a/libcutils/include_vndk/cutils/uevent.h b/libcutils/include_vndk/cutils/uevent.h
deleted file mode 120000
index 451283a..0000000
--- a/libcutils/include_vndk/cutils/uevent.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/cutils/uevent.h
\ No newline at end of file
diff --git a/libcutils/klog.cpp b/libcutils/klog.cpp
index 15adf6b..d301276 100644
--- a/libcutils/klog.cpp
+++ b/libcutils/klog.cpp
@@ -29,10 +29,6 @@
static int klog_level = KLOG_INFO_LEVEL;
-int klog_get_level(void) {
- return klog_level;
-}
-
void klog_set_level(int level) {
klog_level = level;
}
diff --git a/liblog/Android.bp b/liblog/Android.bp
index dce316d..40cdcee 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -79,8 +79,6 @@
},
},
- export_include_dirs: ["include"],
-
cflags: [
"-Werror",
"-fvisibility=hidden",
@@ -113,11 +111,6 @@
license: "NOTICE",
}
-cc_library_headers {
- name: "liblog_vndk_headers",
- export_include_dirs: ["include_vndk"],
-}
-
ndk_library {
name: "liblog.ndk",
symbol_file: "liblog.map.txt",
diff --git a/liblog/include/log/logd.h b/liblog/include/log/logd.h
deleted file mode 100644
index 77400ca..0000000
--- a/liblog/include/log/logd.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef _LIBS_LOG_LOGD_H
-#define _LIBS_LOG_LOGD_H
-#include <log/log.h>
-#warning "Deprecated: do not include log/logd.h, use log/log.h instead"
-#endif /*_LIBS_LOG_LOGD_H*/
diff --git a/liblog/include/log/logger.h b/liblog/include/log/logger.h
deleted file mode 100644
index 1bf2d17..0000000
--- a/liblog/include/log/logger.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef _LIBS_LOG_LOGGER_H
-#define _LIBS_LOG_LOGGER_H
-#include <log/log.h>
-#warning "Deprecated: do not include log/logger.h, use log/log.h instead"
-#endif /*_LIBS_LOG_LOGGER_H*/
diff --git a/liblog/include_vndk/android b/liblog/include_vndk/android
deleted file mode 120000
index 69fbc09..0000000
--- a/liblog/include_vndk/android
+++ /dev/null
@@ -1 +0,0 @@
-../../include/android/
\ No newline at end of file
diff --git a/liblog/include_vndk/log/log.h b/liblog/include_vndk/log/log.h
deleted file mode 100644
index f3eb3fe..0000000
--- a/liblog/include_vndk/log/log.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*Special log.h file for VNDK linking modules*/
-
-#ifndef _LIBS_LOG_LOG_H
-#define _LIBS_LOG_LOG_H
-
-#include <android/log.h>
-
-/*The following files will be included once they are available*/
-/*#include <log/log_id.h>*/
-/*#include <log/log_radio.h>*/
-
-/*
- * LOG_TAG is the local tag used for the following simplified
- * logging macros. You can change this preprocessor definition
- * before using the other macros to change the tag.
- */
-
-#ifndef LOG_TAG
-#define LOG_TAG NULL
-#endif
-
-#endif /*_LIBS_LOG_LOG_H*/