diff options
author | Chien-Yu Chen <cychen@google.com> | 2016-08-17 18:13:53 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-08-17 18:13:53 +0000 |
commit | 17350b5725246d0d9a134d6b2100446169790487 (patch) | |
tree | e3be43889dd46bd996fc45902a99cd313256c396 | |
parent | 712aefac45dc9eaf8bc9536b63c48ca4d31fe9aa (diff) | |
parent | 62d8d87dd3cef5e06acaf617961db38ec4ea8b73 (diff) | |
download | android_system_media-17350b5725246d0d9a134d6b2100446169790487.tar.gz android_system_media-17350b5725246d0d9a134d6b2100446169790487.tar.bz2 android_system_media-17350b5725246d0d9a134d6b2100446169790487.zip |
Camera: Prevent data size overflow
am: 62d8d87dd3
Change-Id: If61c045cf3629152f4ccef1c11e8be18d04e4233
-rw-r--r-- | camera/src/camera_metadata.c | 57 |
1 files changed, 43 insertions, 14 deletions
diff --git a/camera/src/camera_metadata.c b/camera/src/camera_metadata.c index c58a9669..92926872 100644 --- a/camera/src/camera_metadata.c +++ b/camera/src/camera_metadata.c @@ -25,9 +25,10 @@ #include <stdlib.h> #include <errno.h> -#define OK 0 -#define ERROR 1 -#define NOT_FOUND -ENOENT +#define OK 0 +#define ERROR 1 +#define NOT_FOUND -ENOENT +#define SN_EVENT_LOG_ID 0x534e4554 #define ALIGN_TO(val, alignment) \ (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1)) @@ -299,6 +300,38 @@ camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size, return metadata; } +// This method should be used when the camera metadata cannot be trusted. For example, when it's +// read from Parcel. +static int validate_and_calculate_camera_metadata_entry_data_size(size_t *data_size, uint8_t type, + size_t data_count) { + if (type >= NUM_TYPES) return ERROR; + + // Check for overflow + if (data_count != 0 && + camera_metadata_type_size[type] > (SIZE_MAX - DATA_ALIGNMENT + 1) / data_count) { + android_errorWriteLog(SN_EVENT_LOG_ID, "30741779"); + return ERROR; + } + + size_t data_bytes = data_count * camera_metadata_type_size[type]; + + if (data_size) { + *data_size = data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT); + } + + return OK; +} + +size_t calculate_camera_metadata_entry_data_size(uint8_t type, + size_t data_count) { + if (type >= NUM_TYPES) return 0; + + size_t data_bytes = data_count * + camera_metadata_type_size[type]; + + return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT); +} + int validate_camera_metadata_structure(const camera_metadata_t *metadata, const size_t *expected_size) { @@ -414,9 +447,13 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata, return ERROR; } - size_t data_size = - calculate_camera_metadata_entry_data_size(entry.type, - entry.count); + size_t data_size; + if (validate_and_calculate_camera_metadata_entry_data_size(&data_size, entry.type, + entry.count) != OK) { + ALOGE("%s: Entry data size is invalid. type: %u count: %u", __FUNCTION__, entry.type, + entry.count); + return ERROR; + } if (data_size != 0) { camera_metadata_data_t *data = @@ -508,14 +545,6 @@ camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) { return clone; } -size_t calculate_camera_metadata_entry_data_size(uint8_t type, - size_t data_count) { - if (type >= NUM_TYPES) return 0; - size_t data_bytes = data_count * - camera_metadata_type_size[type]; - return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT); -} - static int add_camera_metadata_entry_raw(camera_metadata_t *dst, uint32_t tag, uint8_t type, |