libavb: Allow AvbOps functions to fail with OOM.
am: 507752b2b5
Change-Id: Iaac1990c30e73cd46880496b48313371990b1451
diff --git a/boot_control/boot_control_avb.c b/boot_control/boot_control_avb.c
index 403476c..96f445f 100644
--- a/boot_control/boot_control_avb.c
+++ b/boot_control/boot_control_avb.c
@@ -62,7 +62,8 @@
}
static int module_markBootSuccessful(boot_control_module_t* module) {
- if (avb_ab_mark_slot_successful(ops, module_getCurrentSlot(module))) {
+ if (avb_ab_mark_slot_successful(ops, module_getCurrentSlot(module)) ==
+ AVB_IO_RESULT_OK) {
return 0;
} else {
return -EIO;
@@ -71,7 +72,7 @@
static int module_setActiveBootSlot(boot_control_module_t* module,
unsigned int slot) {
- if (avb_ab_mark_slot_active(ops, slot)) {
+ if (avb_ab_mark_slot_active(ops, slot) == AVB_IO_RESULT_OK) {
return 0;
} else {
return -EIO;
@@ -80,7 +81,7 @@
static int module_setSlotAsUnbootable(struct boot_control_module* module,
unsigned int slot) {
- if (avb_ab_mark_slot_unbootable(ops, slot)) {
+ if (avb_ab_mark_slot_unbootable(ops, slot) == AVB_IO_RESULT_OK) {
return 0;
} else {
return -EIO;
@@ -94,7 +95,7 @@
avb_assert(slot < 2);
- if (!avb_ab_data_read(ops, &ab_data)) {
+ if (avb_ab_data_read(ops, &ab_data) != AVB_IO_RESULT_OK) {
return -EIO;
}
diff --git a/libavb/avb_ab_flow.c b/libavb/avb_ab_flow.c
index de90a81..7e11e27 100644
--- a/libavb/avb_ab_flow.c
+++ b/libavb/avb_ab_flow.c
@@ -81,17 +81,20 @@
*/
#define AB_METADATA_MISC_PARTITION_OFFSET 2048
-bool avb_ab_data_read(AvbOps* ops, AvbABData* data) {
+AvbIOResult avb_ab_data_read(AvbOps* ops, AvbABData* data) {
AvbABData serialized;
- AvbIOResult io_result;
+ AvbIOResult io_ret;
size_t num_bytes_read;
- io_result =
+ io_ret =
ops->read_from_partition(ops, "misc", AB_METADATA_MISC_PARTITION_OFFSET,
sizeof(AvbABData), &serialized, &num_bytes_read);
- if (io_result != AVB_IO_RESULT_OK || num_bytes_read != sizeof(AvbABData)) {
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return AVB_IO_RESULT_ERROR_OOM;
+ } else if (io_ret != AVB_IO_RESULT_OK ||
+ num_bytes_read != sizeof(AvbABData)) {
avb_error("Error reading A/B metadata.\n");
- return false;
+ return AVB_IO_RESULT_ERROR_IO;
}
if (!avb_ab_data_verify_and_byteswap(&serialized, data)) {
@@ -102,22 +105,24 @@
return avb_ab_data_write(ops, data);
}
- return true;
+ return AVB_IO_RESULT_OK;
}
-bool avb_ab_data_write(AvbOps* ops, const AvbABData* data) {
+AvbIOResult avb_ab_data_write(AvbOps* ops, const AvbABData* data) {
AvbABData serialized;
- AvbIOResult io_result;
+ AvbIOResult io_ret;
avb_ab_data_update_crc_and_byteswap(data, &serialized);
- io_result =
+ io_ret =
ops->write_to_partition(ops, "misc", AB_METADATA_MISC_PARTITION_OFFSET,
sizeof(AvbABData), &serialized);
- if (io_result != AVB_IO_RESULT_OK) {
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return AVB_IO_RESULT_ERROR_OOM;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
avb_error("Error writing A/B metadata.\n");
- return false;
+ return AVB_IO_RESULT_ERROR_IO;
}
- return true;
+ return AVB_IO_RESULT_OK;
}
static bool slot_is_bootable(AvbABSlotData* slot) {
@@ -154,12 +159,17 @@
static const char* slot_suffixes[2] = {"_a", "_b"};
-/* Helper function to metadata - returns false if an I/O error occurs. */
-static bool load_metadata(AvbOps* ops, AvbABData* ab_data,
- AvbABData* ab_data_orig) {
- if (!avb_ab_data_read(ops, ab_data)) {
+/* Helper function to load metadata - returns AVB_IO_RESULT_OK on
+ * success, error code otherwise.
+ */
+static AvbIOResult load_metadata(AvbOps* ops, AvbABData* ab_data,
+ AvbABData* ab_data_orig) {
+ AvbIOResult io_ret;
+
+ io_ret = avb_ab_data_read(ops, ab_data);
+ if (io_ret != AVB_IO_RESULT_OK) {
avb_error("I/O error while loading A/B metadata.\n");
- return false;
+ return io_ret;
}
*ab_data_orig = *ab_data;
@@ -169,22 +179,19 @@
*/
slot_normalize(&ab_data->slots[0]);
slot_normalize(&ab_data->slots[1]);
- return true;
+ return AVB_IO_RESULT_OK;
}
-/* Writes A/B metadata to disk only if it has changed - returns false
- * if an I/O error occurs.
+/* Writes A/B metadata to disk only if it has changed - returns
+ * AVB_IO_RESULT_OK on success, error code otherwise.
*/
-static bool save_metadata_if_changed(AvbOps* ops, AvbABData* ab_data,
- AvbABData* ab_data_orig) {
+static AvbIOResult save_metadata_if_changed(AvbOps* ops, AvbABData* ab_data,
+ AvbABData* ab_data_orig) {
if (avb_safe_memcmp(ab_data, ab_data_orig, sizeof(AvbABData)) != 0) {
avb_debug("Writing A/B metadata to disk.\n");
- if (!avb_ab_data_write(ops, ab_data)) {
- avb_error("Error writing A/B metadata to disk.\n");
- return false;
- }
+ return avb_ab_data_write(ops, ab_data);
}
- return true;
+ return AVB_IO_RESULT_OK;
}
AvbABFlowResult avb_ab_flow(AvbOps* ops, AvbSlotVerifyData** out_data) {
@@ -193,8 +200,13 @@
AvbABFlowResult ret;
AvbABData ab_data, ab_data_orig;
size_t slot_index_to_boot, n;
+ AvbIOResult io_ret;
- if (!load_metadata(ops, &ab_data, &ab_data_orig)) {
+ io_ret = load_metadata(ops, &ab_data, &ab_data_orig);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
ret = AVB_AB_FLOW_RESULT_ERROR_IO;
goto out;
}
@@ -205,11 +217,11 @@
AvbSlotVerifyResult verify_result;
verify_result = avb_slot_verify(ops, slot_suffixes[n], &slot_data[n]);
if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) {
- if (verify_result == AVB_AB_FLOW_RESULT_ERROR_OOM) {
+ if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_OOM) {
ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
goto out;
}
- if (verify_result == AVB_AB_FLOW_RESULT_ERROR_IO) {
+ if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_IO) {
ret = AVB_AB_FLOW_RESULT_ERROR_IO;
goto out;
}
@@ -260,13 +272,21 @@
if (rollback_index_value != 0) {
uint64_t current_rollback_index_value;
- if (!ops->read_rollback_index(ops, n, ¤t_rollback_index_value)) {
+ io_ret = ops->read_rollback_index(ops, n, ¤t_rollback_index_value);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
avb_error("Error getting rollback index for slot.\n");
ret = AVB_AB_FLOW_RESULT_ERROR_IO;
goto out;
}
if (current_rollback_index_value != rollback_index_value) {
- if (!ops->write_rollback_index(ops, n, rollback_index_value)) {
+ io_ret = ops->write_rollback_index(ops, n, rollback_index_value);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
avb_error("Error setting stored rollback index.\n");
ret = AVB_AB_FLOW_RESULT_ERROR_IO;
goto out;
@@ -288,8 +308,13 @@
}
out:
- if (!save_metadata_if_changed(ops, &ab_data, &ab_data_orig)) {
- ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+ io_ret = save_metadata_if_changed(ops, &ab_data, &ab_data_orig);
+ if (io_ret != AVB_IO_RESULT_OK) {
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_AB_FLOW_RESULT_ERROR_OOM;
+ } else {
+ ret = AVB_AB_FLOW_RESULT_ERROR_IO;
+ }
if (data != NULL) {
avb_slot_verify_data_free(data);
data = NULL;
@@ -313,14 +338,15 @@
return ret;
}
-bool avb_ab_mark_slot_active(AvbOps* ops, unsigned int slot_number) {
+AvbIOResult avb_ab_mark_slot_active(AvbOps* ops, unsigned int slot_number) {
AvbABData ab_data, ab_data_orig;
- bool ret = false;
unsigned int other_slot_number;
+ AvbIOResult ret;
avb_assert(slot_number < 2);
- if (!load_metadata(ops, &ab_data, &ab_data_orig)) {
+ ret = load_metadata(ops, &ab_data, &ab_data_orig);
+ if (ret != AVB_IO_RESULT_OK) {
goto out;
}
@@ -335,58 +361,62 @@
ab_data.slots[other_slot_number].priority = AVB_AB_MAX_PRIORITY - 1;
}
- ret = true;
+ ret = AVB_IO_RESULT_OK;
out:
- if (!save_metadata_if_changed(ops, &ab_data, &ab_data_orig)) {
- ret = false;
+ if (ret == AVB_IO_RESULT_OK) {
+ ret = save_metadata_if_changed(ops, &ab_data, &ab_data_orig);
}
return ret;
}
-bool avb_ab_mark_slot_unbootable(AvbOps* ops, unsigned int slot_number) {
+AvbIOResult avb_ab_mark_slot_unbootable(AvbOps* ops, unsigned int slot_number) {
AvbABData ab_data, ab_data_orig;
- bool ret = false;
+ AvbIOResult ret;
avb_assert(slot_number < 2);
- if (!load_metadata(ops, &ab_data, &ab_data_orig)) {
+ ret = load_metadata(ops, &ab_data, &ab_data_orig);
+ if (ret != AVB_IO_RESULT_OK) {
goto out;
}
slot_set_unbootable(&ab_data.slots[slot_number]);
- ret = true;
+
+ ret = AVB_IO_RESULT_OK;
out:
- if (!save_metadata_if_changed(ops, &ab_data, &ab_data_orig)) {
- ret = false;
+ if (ret == AVB_IO_RESULT_OK) {
+ ret = save_metadata_if_changed(ops, &ab_data, &ab_data_orig);
}
return ret;
}
-bool avb_ab_mark_slot_successful(AvbOps* ops, unsigned int slot_number) {
+AvbIOResult avb_ab_mark_slot_successful(AvbOps* ops, unsigned int slot_number) {
AvbABData ab_data, ab_data_orig;
- bool ret = false;
+ AvbIOResult ret;
avb_assert(slot_number < 2);
- if (!load_metadata(ops, &ab_data, &ab_data_orig)) {
+ ret = load_metadata(ops, &ab_data, &ab_data_orig);
+ if (ret != AVB_IO_RESULT_OK) {
goto out;
}
if (!slot_is_bootable(&ab_data.slots[slot_number])) {
avb_error("Cannot mark unbootable slot as successful.\n");
+ ret = AVB_IO_RESULT_OK;
goto out;
}
ab_data.slots[slot_number].tries_remaining = 0;
ab_data.slots[slot_number].successful_boot = 1;
- ret = true;
+ ret = AVB_IO_RESULT_OK;
out:
- if (!save_metadata_if_changed(ops, &ab_data, &ab_data_orig)) {
- ret = false;
+ if (ret == AVB_IO_RESULT_OK) {
+ ret = save_metadata_if_changed(ops, &ab_data, &ab_data_orig);
}
return ret;
}
diff --git a/libavb/avb_ab_flow.h b/libavb/avb_ab_flow.h
index 2ea3380..14600a5 100644
--- a/libavb/avb_ab_flow.h
+++ b/libavb/avb_ab_flow.h
@@ -118,20 +118,20 @@
void avb_ab_data_init(AvbABData* data);
/* Reads A/B metadata from the 'misc' partition using |ops|. Returned
- * data is properly byteswapped. Returns false if an I/O operation
- * failed.
+ * data is properly byteswapped. Returns AVB_IO_RESULT_OK on
+ * success, error code otherwise.
*
* If the data read from disk is invalid (e.g. wrong magic or CRC
* checksum failure), the metadata will be reset using
* avb_ab_data_init() and then written to disk.
*/
-bool avb_ab_data_read(AvbOps* ops, AvbABData* data);
+AvbIOResult avb_ab_data_read(AvbOps* ops, AvbABData* data);
/* Writes A/B metadata to the 'misc' partition using |ops|. This will
- * byteswap and update the CRC as needed. Returns false if an I/O
- * error occurs, true otherwise.
+ * byteswap and update the CRC as needed. Returns AVB_IO_RESULT_OK on
+ * success, error code otherwise.
*/
-bool avb_ab_data_write(AvbOps* ops, const AvbABData* data);
+AvbIOResult avb_ab_data_write(AvbOps* ops, const AvbABData* data);
/* Return codes used in avb_ab_flow(), see that function for
* documentation of each value.
@@ -182,31 +182,34 @@
*/
AvbABFlowResult avb_ab_flow(AvbOps* ops, AvbSlotVerifyData** out_data);
-/* Marks the slot with the given slot number as active. Returns false
- * if the operation fails.
+/* Marks the slot with the given slot number as active. Returns
+ * AVB_IO_RESULT_OK on success, error code otherwise.
*
* This function is typically used by the OS updater when completing
* an update. It can also used by the firmware for implementing the
* "set_active" command.
*/
-bool avb_ab_mark_slot_active(AvbOps* ops, unsigned int slot_number);
+AvbIOResult avb_ab_mark_slot_active(AvbOps* ops, unsigned int slot_number);
/* Marks the slot with the given slot number as unbootable. Returns
- * false if the operation fails.
+ * AVB_IO_RESULT_OK on success, error code otherwise.
*
* This function is typically used by the OS updater before writing to
* a slot.
*/
-bool avb_ab_mark_slot_unbootable(AvbOps* ops, unsigned int slot_number);
+AvbIOResult avb_ab_mark_slot_unbootable(AvbOps* ops, unsigned int slot_number);
/* Marks the slot with the given slot number as having booted
- * successfully. This has no effect is the slot is not
- * bootable. Returns false if the operation fails.
+ * successfully. Returns AVB_IO_RESULT_OK on success, error code
+ * otherwise.
+ *
+ * Calling this on an unbootable slot is an error - AVB_IO_RESULT_OK
+ * will be returned yet the function will have no side-effects.
*
* This function is typically used by the OS updater after having
* confirmed that the slot works as intended.
*/
-bool avb_ab_mark_slot_successful(AvbOps* ops, unsigned int slot_number);
+AvbIOResult avb_ab_mark_slot_successful(AvbOps* ops, unsigned int slot_number);
#ifdef __cplusplus
}
diff --git a/libavb/avb_ops.h b/libavb/avb_ops.h
index 5ef658b..f929766 100644
--- a/libavb/avb_ops.h
+++ b/libavb/avb_ops.h
@@ -40,21 +40,24 @@
* AVB_IO_RESULT_OK is returned if the requested operation was
* successful.
*
+ * AVB_IO_RESULT_ERROR_IO is returned if the underlying hardware (disk
+ * or other subsystem) encountered an I/O error.
+ *
+ * AVB_IO_RESULT_ERROR_OOM is returned if unable to allocate memory.
+ *
* AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION is returned if the requested
* partition does not exist.
*
* AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION is returned if the
* range of bytes requested to be read or written is outside the range
* of the partition.
- *
- * AVB_IO_RESULT_ERROR_IO is returned if the underlying disk
- * encountered an I/O error.
*/
typedef enum {
AVB_IO_RESULT_OK,
- AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
- AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION,
+ AVB_IO_RESULT_ERROR_OOM,
AVB_IO_RESULT_ERROR_IO,
+ AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION,
+ AVB_IO_RESULT_ERROR_RANGE_OUTSIDE_PARTITION
} AvbIOResult;
struct AvbOps;
@@ -110,40 +113,44 @@
* embedded key material generated with 'avbtool
* extract_public_key'.
*
- * Return true if trusted or false if untrusted.
+ * If AVB_IO_RESULT_OK is returned then |out_is_trusted| is set -
+ * true if trusted or false if untrusted.
*/
- bool (*validate_vbmeta_public_key)(AvbOps* ops,
- const uint8_t* public_key_data,
- size_t public_key_length);
+ AvbIOResult (*validate_vbmeta_public_key)(AvbOps* ops,
+ const uint8_t* public_key_data,
+ size_t public_key_length,
+ bool* out_is_trusted);
/* Gets the rollback index corresponding to the slot given by
* |rollback_index_slot|. The value is returned in
- * |out_rollback_index|. Returns true if the rollback index was
- * retrieved, false on error.
+ * |out_rollback_index|. Returns AVB_IO_RESULT_OK if the rollback
+ * index was retrieved, otherwise an error code.
*
* A device may have a limited amount of rollback index slots (say,
* one or four) so may error out if |rollback_index_slot| exceeds
* this number.
*/
- bool (*read_rollback_index)(AvbOps* ops, size_t rollback_index_slot,
- uint64_t* out_rollback_index);
+ AvbIOResult (*read_rollback_index)(AvbOps* ops, size_t rollback_index_slot,
+ uint64_t* out_rollback_index);
/* Sets the rollback index corresponding to the slot given by
- * |rollback_index_slot| to |rollback_index|. Returns true if
- * the rollback index was set, false on error.
+ * |rollback_index_slot| to |rollback_index|. Returns
+ * AVB_IO_RESULT_OK if the rollback index was set, otherwise an
+ * error code.
*
* A device may have a limited amount of rollback index slots (say,
* one or four) so may error out if |rollback_index_slot| exceeds
* this number.
*/
- bool (*write_rollback_index)(AvbOps* ops, size_t rollback_index_slot,
- uint64_t rollback_index);
+ AvbIOResult (*write_rollback_index)(AvbOps* ops, size_t rollback_index_slot,
+ uint64_t rollback_index);
/* Gets whether the device is unlocked. The value is returned in
* |out_is_unlocked| (true if unlocked, false otherwise). Returns
- * true if the state was retrieved, false on error.
+ * AVB_IO_RESULT_OK if the state was retrieved, otherwise an error
+ * code.
*/
- bool (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
+ AvbIOResult (*read_is_device_unlocked)(AvbOps* ops, bool* out_is_unlocked);
/* Gets the unique partition GUID for a partition with name in
* |partition| (NUL-terminated UTF-8 string). The GUID is copied as
@@ -153,11 +160,12 @@
*
* 527c1c6d-6361-4593-8842-3c78fcd39219
*
- * Returns false if the operation fails (no such partition or
- * |buf_size| is too small), true if it succeeds.
+ * Returns AVB_IO_RESULT_OK on success, otherwise an error code.
*/
- bool (*get_unique_guid_for_partition)(AvbOps* ops, const char* partition,
- char* guid_buf, size_t guid_buf_size);
+ AvbIOResult (*get_unique_guid_for_partition)(AvbOps* ops,
+ const char* partition,
+ char* guid_buf,
+ size_t guid_buf_size);
};
#ifdef __cplusplus
diff --git a/libavb/avb_slot_verify.c b/libavb/avb_slot_verify.c
index 12f139e..dec65a4 100644
--- a/libavb/avb_slot_verify.c
+++ b/libavb/avb_slot_verify.c
@@ -88,7 +88,10 @@
io_ret =
ops->read_from_partition(ops, part_name, 0 /* offset */,
hash_desc.image_size, image_buf, &part_num_read);
- if (io_ret != AVB_IO_RESULT_OK) {
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
avb_errorv(part_name, ": Error loading data from partition.\n", NULL);
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto out;
@@ -212,7 +215,10 @@
io_ret =
ops->read_from_partition(ops, full_partition_name, -AVB_FOOTER_SIZE,
AVB_FOOTER_SIZE, footer_buf, &footer_num_read);
- if (io_ret != AVB_IO_RESULT_OK) {
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
avb_errorv(full_partition_name, ": Error loading footer.\n", NULL);
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto out;
@@ -246,7 +252,10 @@
io_ret = ops->read_from_partition(ops, full_partition_name, vbmeta_offset,
vbmeta_size, vbmeta_buf, &vbmeta_num_read);
- if (io_ret != AVB_IO_RESULT_OK) {
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
avb_errorv(full_partition_name, ": Error loading vbmeta data.\n", NULL);
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto out;
@@ -277,8 +286,22 @@
goto out;
}
} else {
+ bool key_is_trusted = false;
+
avb_assert(is_main_vbmeta);
- if (!ops->validate_vbmeta_public_key(ops, pk_data, pk_len)) {
+ io_ret =
+ ops->validate_vbmeta_public_key(ops, pk_data, pk_len, &key_is_trusted);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
+ avb_errorv(full_partition_name,
+ ": Error while checking public key used to sign data.\n",
+ NULL);
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
+ goto out;
+ }
+ if (!key_is_trusted) {
avb_errorv(full_partition_name,
": Public key used to sign data rejected.\n", NULL);
ret = AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED;
@@ -290,8 +313,12 @@
&vbmeta_header);
/* Check rollback index. */
- if (!ops->read_rollback_index(ops, rollback_index_slot,
- &stored_rollback_index)) {
+ io_ret = ops->read_rollback_index(ops, rollback_index_slot,
+ &stored_rollback_index);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto out;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
avb_errorv(full_partition_name,
": Error getting rollback index for slot.\n", NULL);
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
@@ -480,17 +507,19 @@
return ret;
}
+#define NUM_GUIDS 2
+
/* Substitutes all variables (e.g. $(ANDROID_SYSTEM_PARTUUID)) with
* values. Returns NULL on OOM, otherwise the cmdline with values
* replaced.
*/
static char* sub_cmdline(AvbOps* ops, const char* cmdline,
const char* ab_suffix) {
- const int NUM_GUIDS = 2;
const char* part_name_str[NUM_GUIDS] = {"system", "boot"};
const char* replace_str[NUM_GUIDS] = {"$(ANDROID_SYSTEM_PARTUUID)",
"$(ANDROID_BOOT_PARTUUID)"};
char* ret = NULL;
+ AvbIOResult io_ret;
/* Replace unique partition GUIDs */
for (size_t n = 0; n < NUM_GUIDS; n++) {
@@ -505,8 +534,11 @@
goto fail;
}
- if (!ops->get_unique_guid_for_partition(ops, part_name, guid_buf,
- sizeof guid_buf)) {
+ io_ret = ops->get_unique_guid_for_partition(ops, part_name, guid_buf,
+ sizeof guid_buf);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ return NULL;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
avb_error("Error getting unique GUID for partition.\n");
goto fail;
}
@@ -615,6 +647,7 @@
AvbSlotVerifyResult ret;
AvbSlotVerifyData* slot_data = NULL;
AvbAlgorithmType algorithm_type = AVB_ALGORITHM_TYPE_NONE;
+ AvbIOResult io_ret;
if (out_data != NULL) {
*out_data = NULL;
@@ -662,7 +695,11 @@
/* Set androidboot.avb.device_state to "locked" or "unlocked". */
bool is_device_unlocked;
- if (!ops->read_is_device_unlocked(ops, &is_device_unlocked)) {
+ io_ret = ops->read_is_device_unlocked(ops, &is_device_unlocked);
+ if (io_ret == AVB_IO_RESULT_ERROR_OOM) {
+ ret = AVB_SLOT_VERIFY_RESULT_ERROR_OOM;
+ goto fail;
+ } else if (io_ret != AVB_IO_RESULT_OK) {
avb_error("Error getting device state.\n");
ret = AVB_SLOT_VERIFY_RESULT_ERROR_IO;
goto fail;
diff --git a/test/avb_ab_flow_unittest.cc b/test/avb_ab_flow_unittest.cc
index fdfbb5f..09ec12c 100644
--- a/test/avb_ab_flow_unittest.cc
+++ b/test/avb_ab_flow_unittest.cc
@@ -202,7 +202,7 @@
data.slots[1].priority = b_pri;
data.slots[1].tries_remaining = b_tries;
data.slots[1].successful_boot = (b_success ? 1 : 0);
- EXPECT_TRUE(avb_ab_data_write(ops_.avb_ops(), &data));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_write(ops_.avb_ops(), &data));
GenerateSlot(0, a_slot_valid, a_rollback_boot, a_rollback_odm);
GenerateSlot(1, b_slot_valid, b_rollback_boot, b_rollback_odm);
ops_.set_stored_rollback_indexes(stored_rollback_indexes);
@@ -211,19 +211,19 @@
FakeAvbOps ops_;
};
-#define ExpMD(a_pri, a_tries, a_success, b_pri, b_tries, b_success, \
- stored_rollback_indexes) \
- do { \
- AvbABData data; \
- EXPECT_TRUE(avb_ab_data_read(ops_.avb_ops(), &data)); \
- EXPECT_EQ(a_pri, data.slots[0].priority); \
- EXPECT_EQ(a_tries, data.slots[0].tries_remaining); \
- EXPECT_EQ(a_success ? 1 : 0, data.slots[0].successful_boot); \
- EXPECT_EQ(b_pri, data.slots[1].priority); \
- EXPECT_EQ(b_tries, data.slots[1].tries_remaining); \
- EXPECT_EQ(b_success ? 1 : 0, data.slots[1].successful_boot); \
- EXPECT_EQ(std::vector<uint64_t>(stored_rollback_indexes), \
- ops_.get_stored_rollback_indexes()); \
+#define ExpMD(a_pri, a_tries, a_success, b_pri, b_tries, b_success, \
+ stored_rollback_indexes) \
+ do { \
+ AvbABData data; \
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_read(ops_.avb_ops(), &data)); \
+ EXPECT_EQ(a_pri, data.slots[0].priority); \
+ EXPECT_EQ(a_tries, data.slots[0].tries_remaining); \
+ EXPECT_EQ(a_success ? 1 : 0, data.slots[0].successful_boot); \
+ EXPECT_EQ(b_pri, data.slots[1].priority); \
+ EXPECT_EQ(b_tries, data.slots[1].tries_remaining); \
+ EXPECT_EQ(b_success ? 1 : 0, data.slots[1].successful_boot); \
+ EXPECT_EQ(std::vector<uint64_t>(stored_rollback_indexes), \
+ ops_.get_stored_rollback_indexes()); \
} while (0);
TEST_F(AvbABFlowTest, MetadataReadAndWrite) {
@@ -232,7 +232,7 @@
// First load from an uninitialized 'misc' partition. This should
// not fail and just returned initialized data.
- EXPECT_TRUE(avb_ab_data_read(ops_.avb_ops(), &loaded));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_read(ops_.avb_ops(), &loaded));
EXPECT_EQ(AVB_AB_MAX_PRIORITY, loaded.slots[0].priority);
EXPECT_EQ(AVB_AB_MAX_TRIES_REMAINING, loaded.slots[0].tries_remaining);
EXPECT_EQ(0, loaded.slots[0].successful_boot);
@@ -245,8 +245,8 @@
avb_ab_data_init(&data);
data.slots[0].priority = 2;
data.slots[0].tries_remaining = 3;
- EXPECT_TRUE(avb_ab_data_write(ops_.avb_ops(), &data));
- EXPECT_TRUE(avb_ab_data_read(ops_.avb_ops(), &loaded));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_write(ops_.avb_ops(), &data));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_read(ops_.avb_ops(), &loaded));
EXPECT_EQ(2, loaded.slots[0].priority);
EXPECT_EQ(3, loaded.slots[0].tries_remaining);
}
@@ -495,7 +495,7 @@
SetMD(15, 0, 1, false, 0, 0, // A: pri, tries, success, slot_valid, RIs
11, 0, 1, true, 0, 0, // B: pri, tries, success, slot_valid, RIs
{0, 0}); // stored_rollback_indexes
- EXPECT_TRUE(avb_ab_mark_slot_active(ops_.avb_ops(), 0));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_active(ops_.avb_ops(), 0));
ExpMD(15, 7, 0, // A: pri, tries, successful
11, 0, 1, // B: pri, tries, successful
std::vector<uint64_t>({0, 0})); // stored_rollback_indexes
@@ -505,7 +505,7 @@
SetMD(15, 0, 1, false, 0, 0, // A: pri, tries, success, slot_valid, RIs
14, 0, 1, true, 0, 0, // B: pri, tries, success, slot_valid, RIs
{0, 0}); // stored_rollback_indexes
- EXPECT_TRUE(avb_ab_mark_slot_active(ops_.avb_ops(), 1));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_active(ops_.avb_ops(), 1));
ExpMD(14, 0, 1, // A: pri, tries, successful
15, 7, 0, // B: pri, tries, successful
std::vector<uint64_t>({0, 0})); // stored_rollback_indexes
@@ -515,7 +515,7 @@
SetMD(15, 0, 1, false, 0, 0, // A: pri, tries, success, slot_valid, RIs
11, 0, 1, true, 0, 0, // B: pri, tries, success, slot_valid, RIs
{0, 0}); // stored_rollback_indexes
- EXPECT_TRUE(avb_ab_mark_slot_unbootable(ops_.avb_ops(), 0));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_unbootable(ops_.avb_ops(), 0));
ExpMD(0, 0, 0, // A: pri, tries, successful
11, 0, 1, // B: pri, tries, successful
std::vector<uint64_t>({0, 0})); // stored_rollback_indexes
@@ -523,7 +523,7 @@
SetMD(15, 0, 1, false, 0, 0, // A: pri, tries, success, slot_valid, RIs
14, 0, 1, true, 0, 0, // B: pri, tries, success, slot_valid, RIs
{0, 0}); // stored_rollback_indexes
- EXPECT_TRUE(avb_ab_mark_slot_unbootable(ops_.avb_ops(), 1));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_unbootable(ops_.avb_ops(), 1));
ExpMD(15, 0, 1, // A: pri, tries, successful
0, 0, 0, // B: pri, tries, successful
std::vector<uint64_t>({0, 0})); // stored_rollback_indexes
@@ -533,7 +533,7 @@
SetMD(15, 5, 0, false, 0, 0, // A: pri, tries, success, slot_valid, RIs
11, 3, 0, true, 0, 0, // B: pri, tries, success, slot_valid, RIs
{0, 0}); // stored_rollback_indexes
- EXPECT_TRUE(avb_ab_mark_slot_successful(ops_.avb_ops(), 0));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_successful(ops_.avb_ops(), 0));
ExpMD(15, 0, 1, // A: pri, tries, successful
11, 3, 0, // B: pri, tries, successful
std::vector<uint64_t>({0, 0})); // stored_rollback_indexes
@@ -541,17 +541,18 @@
SetMD(15, 5, 0, false, 0, 0, // A: pri, tries, success, slot_valid, RIs
14, 0, 1, true, 0, 0, // B: pri, tries, success, slot_valid, RIs
{0, 0}); // stored_rollback_indexes
- EXPECT_TRUE(avb_ab_mark_slot_successful(ops_.avb_ops(), 1));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_successful(ops_.avb_ops(), 1));
ExpMD(15, 5, 0, // A: pri, tries, successful
14, 0, 1, // B: pri, tries, successful
std::vector<uint64_t>({0, 0})); // stored_rollback_indexes
- // Marking an unbootable slot (A) as successful fails. Also note how
- // the unbootable slot is normalized in the process.
+ // Marking an unbootable slot (A) as successful won't work (it's a
+ // programmer error to do so)... notice however that the unbootable
+ // slot is normalized in the process.
SetMD(0, 3, 2, false, 0, 0, // A: pri, tries, success, slot_valid, RIs
14, 0, 1, true, 0, 0, // B: pri, tries, success, slot_valid, RIs
{0, 0}); // stored_rollback_indexes
- EXPECT_FALSE(avb_ab_mark_slot_successful(ops_.avb_ops(), 0));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_mark_slot_successful(ops_.avb_ops(), 0));
ExpMD(0, 0, 0, // A: pri, tries, successful
14, 0, 1, // B: pri, tries, successful
std::vector<uint64_t>({0, 0})); // stored_rollback_indexes
@@ -567,7 +568,7 @@
" --slot_data 13:3:0:11:2:1",
misc_path.value().c_str());
- EXPECT_TRUE(avb_ab_data_read(ops_.avb_ops(), &data));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_read(ops_.avb_ops(), &data));
EXPECT_EQ(13, data.slots[0].priority);
EXPECT_EQ(3, data.slots[0].tries_remaining);
EXPECT_EQ(0, data.slots[0].successful_boot);
@@ -588,7 +589,7 @@
" --slot_data 12:2:1:10:5:0",
misc_path.value().c_str());
- EXPECT_TRUE(avb_ab_data_read(ops_.avb_ops(), &data));
+ EXPECT_EQ(AVB_IO_RESULT_OK, avb_ab_data_read(ops_.avb_ops(), &data));
EXPECT_EQ(12, data.slots[0].priority);
EXPECT_EQ(2, data.slots[0].tries_remaining);
EXPECT_EQ(1, data.slots[0].successful_boot);
diff --git a/test/fake_avb_ops.cc b/test/fake_avb_ops.cc
index 42bc133..193ab27 100644
--- a/test/fake_avb_ops.cc
+++ b/test/fake_avb_ops.cc
@@ -127,52 +127,56 @@
return AVB_IO_RESULT_OK;
}
-int FakeAvbOps::validate_vbmeta_public_key(AvbOps* ops,
- const uint8_t* public_key_data,
- size_t public_key_length) {
- if (public_key_length != expected_public_key_.size()) return 0;
-
- return memcmp(expected_public_key_.c_str(), public_key_data,
- public_key_length) == 0;
+AvbIOResult FakeAvbOps::validate_vbmeta_public_key(
+ AvbOps* ops, const uint8_t* public_key_data, size_t public_key_length,
+ bool* out_key_is_trusted) {
+ if (out_key_is_trusted != NULL) {
+ *out_key_is_trusted = (public_key_length == expected_public_key_.size() &&
+ (memcmp(expected_public_key_.c_str(),
+ public_key_data, public_key_length) == 0));
+ }
+ return AVB_IO_RESULT_OK;
}
-bool FakeAvbOps::read_rollback_index(AvbOps* ops, size_t rollback_index_slot,
- uint64_t* out_rollback_index) {
+AvbIOResult FakeAvbOps::read_rollback_index(AvbOps* ops,
+ size_t rollback_index_slot,
+ uint64_t* out_rollback_index) {
if (rollback_index_slot >= stored_rollback_indexes_.size()) {
fprintf(stderr, "No rollback index for slot %zd (has %zd slots).\n",
rollback_index_slot, stored_rollback_indexes_.size());
- return false;
+ return AVB_IO_RESULT_ERROR_IO;
}
*out_rollback_index = stored_rollback_indexes_[rollback_index_slot];
- return true;
+ return AVB_IO_RESULT_OK;
}
-bool FakeAvbOps::write_rollback_index(AvbOps* ops, size_t rollback_index_slot,
- uint64_t rollback_index) {
+AvbIOResult FakeAvbOps::write_rollback_index(AvbOps* ops,
+ size_t rollback_index_slot,
+ uint64_t rollback_index) {
if (rollback_index_slot >= stored_rollback_indexes_.size()) {
fprintf(stderr, "No rollback index for slot %zd (has %zd slots).\n",
rollback_index_slot, stored_rollback_indexes_.size());
- return false;
+ return AVB_IO_RESULT_ERROR_IO;
}
stored_rollback_indexes_[rollback_index_slot] = rollback_index;
- return true;
+ return AVB_IO_RESULT_OK;
}
-bool FakeAvbOps::read_is_device_unlocked(AvbOps* ops,
- bool* out_is_device_unlocked) {
+AvbIOResult FakeAvbOps::read_is_device_unlocked(AvbOps* ops,
+ bool* out_is_device_unlocked) {
*out_is_device_unlocked = stored_is_device_unlocked_ ? 1 : 0;
- return true;
+ return AVB_IO_RESULT_OK;
}
-bool FakeAvbOps::get_unique_guid_for_partition(AvbOps* ops,
- const char* partition,
- char* guid_buf,
- size_t guid_buf_size) {
+AvbIOResult FakeAvbOps::get_unique_guid_for_partition(AvbOps* ops,
+ const char* partition,
+ char* guid_buf,
+ size_t guid_buf_size) {
// This is faking it a bit but makes testing easy. It works
// because avb_slot_verify.c doesn't check that the returned GUID
// is wellformed.
snprintf(guid_buf, guid_buf_size, "1234-fake-guid-for:%s", partition);
- return true;
+ return AVB_IO_RESULT_OK;
}
struct FakeAvbOpsC {
@@ -197,37 +201,39 @@
->my_ops->write_to_partition(partition, offset, num_bytes, buffer);
}
-static bool my_ops_validate_vbmeta_public_key(AvbOps* ops,
- const uint8_t* public_key_data,
- size_t public_key_length) {
+static AvbIOResult my_ops_validate_vbmeta_public_key(
+ AvbOps* ops, const uint8_t* public_key_data, size_t public_key_length,
+ bool* out_key_is_trusted) {
return ((FakeAvbOpsC*)ops)
- ->my_ops->validate_vbmeta_public_key(ops, public_key_data,
- public_key_length);
+ ->my_ops->validate_vbmeta_public_key(
+ ops, public_key_data, public_key_length, out_key_is_trusted);
}
-static bool my_ops_read_rollback_index(AvbOps* ops, size_t rollback_index_slot,
- uint64_t* out_rollback_index) {
+static AvbIOResult my_ops_read_rollback_index(AvbOps* ops,
+ size_t rollback_index_slot,
+ uint64_t* out_rollback_index) {
return ((FakeAvbOpsC*)ops)
->my_ops->read_rollback_index(ops, rollback_index_slot,
out_rollback_index);
}
-static bool my_ops_write_rollback_index(AvbOps* ops, size_t rollback_index_slot,
- uint64_t rollback_index) {
+static AvbIOResult my_ops_write_rollback_index(AvbOps* ops,
+ size_t rollback_index_slot,
+ uint64_t rollback_index) {
return ((FakeAvbOpsC*)ops)
->my_ops->write_rollback_index(ops, rollback_index_slot, rollback_index);
}
-static bool my_ops_read_is_device_unlocked(AvbOps* ops,
- bool* out_is_device_unlocked) {
+static AvbIOResult my_ops_read_is_device_unlocked(
+ AvbOps* ops, bool* out_is_device_unlocked) {
return ((FakeAvbOpsC*)ops)
->my_ops->read_is_device_unlocked(ops, out_is_device_unlocked);
}
-static bool my_ops_get_unique_guid_for_partition(AvbOps* ops,
- const char* partition,
- char* guid_buf,
- size_t guid_buf_size) {
+static AvbIOResult my_ops_get_unique_guid_for_partition(AvbOps* ops,
+ const char* partition,
+ char* guid_buf,
+ size_t guid_buf_size) {
return ((FakeAvbOpsC*)ops)
->my_ops->get_unique_guid_for_partition(ops, partition, guid_buf,
guid_buf_size);
diff --git a/test/fake_avb_ops.h b/test/fake_avb_ops.h
index 8513cae..42a47d0 100644
--- a/test/fake_avb_ops.h
+++ b/test/fake_avb_ops.h
@@ -69,19 +69,23 @@
AvbIOResult write_to_partition(const char* partition, int64_t offset,
size_t num_bytes, const void* buffer);
- int validate_vbmeta_public_key(AvbOps* ops, const uint8_t* public_key_data,
- size_t public_key_length);
+ AvbIOResult validate_vbmeta_public_key(AvbOps* ops,
+ const uint8_t* public_key_data,
+ size_t public_key_length,
+ bool* out_key_is_trusted);
- bool read_rollback_index(AvbOps* ops, size_t rollback_index_slot,
- uint64_t* out_rollback_index);
+ AvbIOResult read_rollback_index(AvbOps* ops, size_t rollback_index_slot,
+ uint64_t* out_rollback_index);
- bool write_rollback_index(AvbOps* ops, size_t rollback_index_slot,
- uint64_t rollback_index);
+ AvbIOResult write_rollback_index(AvbOps* ops, size_t rollback_index_slot,
+ uint64_t rollback_index);
- bool read_is_device_unlocked(AvbOps* ops, bool* out_is_device_unlocked);
+ AvbIOResult read_is_device_unlocked(AvbOps* ops,
+ bool* out_is_device_unlocked);
- bool get_unique_guid_for_partition(AvbOps* ops, const char* partition,
- char* guid_buf, size_t guid_buf_size);
+ AvbIOResult get_unique_guid_for_partition(AvbOps* ops, const char* partition,
+ char* guid_buf,
+ size_t guid_buf_size);
private:
FakeAvbOpsC* avb_ops_;