Skip to content

Commit f33d55e

Browse files
Chien-Yu Chenandi34
authored andcommitted
Camera: Prevent data size overflow
Add a function to check overflow when calculating metadata data size. Bug: 30741779 Change-Id: I6405fe608567a4f4113674050f826f305ecae030 (cherry picked from commit 97a9cd6)
1 parent 30bf0cc commit f33d55e

File tree

1 file changed

+43
-14
lines changed

1 file changed

+43
-14
lines changed

camera/src/camera_metadata.c

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@
2222
#include <stdlib.h>
2323
#include <errno.h>
2424

25-
#define OK 0
26-
#define ERROR 1
27-
#define NOT_FOUND -ENOENT
25+
#define OK 0
26+
#define ERROR 1
27+
#define NOT_FOUND -ENOENT
28+
#define SN_EVENT_LOG_ID 0x534e4554
2829

2930
#define _Alignas(T) \
3031
({struct _AlignasStruct { char c; T field; }; \
@@ -291,6 +292,38 @@ camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
291292
return metadata;
292293
}
293294

295+
// This method should be used when the camera metadata cannot be trusted. For example, when it's
296+
// read from Parcel.
297+
static int validate_and_calculate_camera_metadata_entry_data_size(size_t *data_size, uint8_t type,
298+
size_t data_count) {
299+
if (type >= NUM_TYPES) return ERROR;
300+
301+
// Check for overflow
302+
if (data_count != 0 &&
303+
camera_metadata_type_size[type] > (SIZE_MAX - DATA_ALIGNMENT + 1) / data_count) {
304+
android_errorWriteLog(SN_EVENT_LOG_ID, "30741779");
305+
return ERROR;
306+
}
307+
308+
size_t data_bytes = data_count * camera_metadata_type_size[type];
309+
310+
if (data_size) {
311+
*data_size = data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
312+
}
313+
314+
return OK;
315+
}
316+
317+
size_t calculate_camera_metadata_entry_data_size(uint8_t type,
318+
size_t data_count) {
319+
if (type >= NUM_TYPES) return 0;
320+
321+
size_t data_bytes = data_count *
322+
camera_metadata_type_size[type];
323+
324+
return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
325+
}
326+
294327
int validate_camera_metadata_structure(const camera_metadata_t *metadata,
295328
const size_t *expected_size) {
296329

@@ -400,9 +433,13 @@ int validate_camera_metadata_structure(const camera_metadata_t *metadata,
400433
return ERROR;
401434
}
402435

403-
size_t data_size =
404-
calculate_camera_metadata_entry_data_size(entry.type,
405-
entry.count);
436+
size_t data_size;
437+
if (validate_and_calculate_camera_metadata_entry_data_size(&data_size, entry.type,
438+
entry.count) != OK) {
439+
ALOGE("%s: Entry data size is invalid. type: %u count: %u", __FUNCTION__, entry.type,
440+
entry.count);
441+
return ERROR;
442+
}
406443

407444
if (data_size != 0) {
408445
camera_metadata_data_t *data =
@@ -492,14 +529,6 @@ camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) {
492529
return clone;
493530
}
494531

495-
size_t calculate_camera_metadata_entry_data_size(uint8_t type,
496-
size_t data_count) {
497-
if (type >= NUM_TYPES) return 0;
498-
size_t data_bytes = data_count *
499-
camera_metadata_type_size[type];
500-
return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
501-
}
502-
503532
static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
504533
uint32_t tag,
505534
uint8_t type,

0 commit comments

Comments
 (0)