Loading camera/CameraMetadata.cpp +107 −30 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,9 @@ namespace android { namespace android { #define ALIGN_TO(val, alignment) \ (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1)) typedef Parcel::WritableBlob WritableBlob; typedef Parcel::WritableBlob WritableBlob; typedef Parcel::ReadableBlob ReadableBlob; typedef Parcel::ReadableBlob ReadableBlob; Loading Loading @@ -431,40 +434,70 @@ status_t CameraMetadata::readFromParcel(const Parcel& data, *out = NULL; *out = NULL; } } // arg0 = metadataSize (int32) // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation. int32_t metadataSizeTmp = -1; // arg0 = blobSize (int32) if ((err = data.readInt32(&metadataSizeTmp)) != OK) { int32_t blobSizeTmp = -1; if ((err = data.readInt32(&blobSizeTmp)) != OK) { ALOGE("%s: Failed to read metadata size (error %d %s)", ALOGE("%s: Failed to read metadata size (error %d %s)", __FUNCTION__, err, strerror(-err)); __FUNCTION__, err, strerror(-err)); return err; return err; } } const size_t metadataSize = static_cast<size_t>(metadataSizeTmp); const size_t blobSize = static_cast<size_t>(blobSizeTmp); const size_t alignment = get_camera_metadata_alignment(); if (metadataSize == 0) { // Special case: zero blob size means zero sized (NULL) metadata. if (blobSize == 0) { ALOGV("%s: Read 0-sized metadata", __FUNCTION__); ALOGV("%s: Read 0-sized metadata", __FUNCTION__); return OK; return OK; } } // NOTE: this doesn't make sense to me. shouldnt the blob if (blobSize <= alignment) { ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)", __FUNCTION__, blobSize, alignment); return BAD_VALUE; } const size_t metadataSize = blobSize - alignment; // NOTE: this doesn't make sense to me. shouldn't the blob // know how big it is? why do we have to specify the size // know how big it is? why do we have to specify the size // to Parcel::readBlob ? // to Parcel::readBlob ? ReadableBlob blob; ReadableBlob blob; // arg1 = metadata (blob) // arg1 = metadata (blob) do { do { if ((err = data.readBlob(metadataSize, &blob)) != OK) { if ((err = data.readBlob(blobSize, &blob)) != OK) { ALOGE("%s: Failed to read metadata blob (sized %d). Possible " ALOGE("%s: Failed to read metadata blob (sized %zu). Possible " " serialization bug. Error %d %s", " serialization bug. Error %d %s", __FUNCTION__, metadataSize, err, strerror(-err)); __FUNCTION__, blobSize, err, strerror(-err)); break; break; } } const camera_metadata_t* tmp = reinterpret_cast<const camera_metadata_t*>(blob.data()); // arg2 = offset (blob) // Must be after blob since we don't know offset until after writeBlob. int32_t offsetTmp; if ((err = data.readInt32(&offsetTmp)) != OK) { ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)", __FUNCTION__, err, strerror(-err)); break; } const size_t offset = static_cast<size_t>(offsetTmp); if (offset >= alignment) { ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)", __FUNCTION__, blobSize, alignment); err = BAD_VALUE; break; } const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset; const camera_metadata_t* tmp = reinterpret_cast<const camera_metadata_t*>(metadataStart); ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu", __FUNCTION__, alignment, tmp, offset); metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize); metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize); if (metadata == NULL) { if (metadata == NULL) { // We consider that allocation only fails if the validation // We consider that allocation only fails if the validation // also failed, therefore the readFromParcel was a failure. // also failed, therefore the readFromParcel was a failure. ALOGE("%s: metadata allocation and copy failed", __FUNCTION__); err = BAD_VALUE; err = BAD_VALUE; } } } while(0); } while(0); Loading @@ -485,38 +518,79 @@ status_t CameraMetadata::writeToParcel(Parcel& data, const camera_metadata_t* metadata) { const camera_metadata_t* metadata) { status_t res = OK; status_t res = OK; // arg0 = metadataSize (int32) /** * Below is the camera metadata parcel layout: * * |--------------------------------------------| * | arg0: blobSize | * | (length = 4) | * |--------------------------------------------|<--Skip the rest if blobSize == 0. * | | * | | * | arg1: blob | * | (length = variable, see arg1 layout below) | * | | * | | * |--------------------------------------------| * | arg2: offset | * | (length = 4) | * |--------------------------------------------| */ // arg0 = blobSize (int32) if (metadata == NULL) { if (metadata == NULL) { // Write zero blobSize for null metadata. return data.writeInt32(0); return data.writeInt32(0); } } /** * Always make the blob size sufficiently larger, as we need put alignment * padding and metadata into the blob. Since we don't know the alignment * offset before writeBlob. Then write the metadata to aligned offset. */ const size_t metadataSize = get_camera_metadata_compact_size(metadata); const size_t metadataSize = get_camera_metadata_compact_size(metadata); res = data.writeInt32(static_cast<int32_t>(metadataSize)); const size_t alignment = get_camera_metadata_alignment(); const size_t blobSize = metadataSize + alignment; res = data.writeInt32(static_cast<int32_t>(blobSize)); if (res != OK) { if (res != OK) { return res; return res; } } // arg1 = metadata (blob) size_t offset = 0; /** * arg1 = metadata (blob). * * The blob size is the sum of front padding size, metadata size and back padding * size, which is equal to metadataSize + alignment. * * The blob layout is: * |------------------------------------|<----Start address of the blob (unaligned). * | front padding | * | (size = offset) | * |------------------------------------|<----Aligned start address of metadata. * | | * | | * | metadata | * | (size = metadataSize) | * | | * | | * |------------------------------------| * | back padding | * | (size = alignment - offset) | * |------------------------------------|<----End address of blob. * (Blob start address + blob size). */ WritableBlob blob; WritableBlob blob; do { do { res = data.writeBlob(metadataSize, &blob); res = data.writeBlob(blobSize, &blob); if (res != OK) { if (res != OK) { break; break; } } copy_camera_metadata(blob.data(), metadataSize, metadata); const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment); offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data()); IF_ALOGV() { ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu", if (validate_camera_metadata_structure( __FUNCTION__, alignment, metadataStart, offset); (const camera_metadata_t*)blob.data(), copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata); &metadataSize) != OK) { ALOGV("%s: Failed to validate metadata %p after writing blob", __FUNCTION__, blob.data()); } else { ALOGV("%s: Metadata written to blob. Validation success", __FUNCTION__); } } // Not too big of a problem since receiving side does hard validation // Not too big of a problem since receiving side does hard validation // Don't check the size since the compact size could be larger // Don't check the size since the compact size could be larger Loading @@ -528,6 +602,9 @@ status_t CameraMetadata::writeToParcel(Parcel& data, } while(false); } while(false); blob.release(); blob.release(); // arg2 = offset (int32) res = data.writeInt32(static_cast<int32_t>(offset)); return res; return res; } } Loading Loading
camera/CameraMetadata.cpp +107 −30 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,9 @@ namespace android { namespace android { #define ALIGN_TO(val, alignment) \ (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1)) typedef Parcel::WritableBlob WritableBlob; typedef Parcel::WritableBlob WritableBlob; typedef Parcel::ReadableBlob ReadableBlob; typedef Parcel::ReadableBlob ReadableBlob; Loading Loading @@ -431,40 +434,70 @@ status_t CameraMetadata::readFromParcel(const Parcel& data, *out = NULL; *out = NULL; } } // arg0 = metadataSize (int32) // See CameraMetadata::writeToParcel for parcel data layout diagram and explanation. int32_t metadataSizeTmp = -1; // arg0 = blobSize (int32) if ((err = data.readInt32(&metadataSizeTmp)) != OK) { int32_t blobSizeTmp = -1; if ((err = data.readInt32(&blobSizeTmp)) != OK) { ALOGE("%s: Failed to read metadata size (error %d %s)", ALOGE("%s: Failed to read metadata size (error %d %s)", __FUNCTION__, err, strerror(-err)); __FUNCTION__, err, strerror(-err)); return err; return err; } } const size_t metadataSize = static_cast<size_t>(metadataSizeTmp); const size_t blobSize = static_cast<size_t>(blobSizeTmp); const size_t alignment = get_camera_metadata_alignment(); if (metadataSize == 0) { // Special case: zero blob size means zero sized (NULL) metadata. if (blobSize == 0) { ALOGV("%s: Read 0-sized metadata", __FUNCTION__); ALOGV("%s: Read 0-sized metadata", __FUNCTION__); return OK; return OK; } } // NOTE: this doesn't make sense to me. shouldnt the blob if (blobSize <= alignment) { ALOGE("%s: metadata blob is malformed, blobSize(%zu) should be larger than alignment(%zu)", __FUNCTION__, blobSize, alignment); return BAD_VALUE; } const size_t metadataSize = blobSize - alignment; // NOTE: this doesn't make sense to me. shouldn't the blob // know how big it is? why do we have to specify the size // know how big it is? why do we have to specify the size // to Parcel::readBlob ? // to Parcel::readBlob ? ReadableBlob blob; ReadableBlob blob; // arg1 = metadata (blob) // arg1 = metadata (blob) do { do { if ((err = data.readBlob(metadataSize, &blob)) != OK) { if ((err = data.readBlob(blobSize, &blob)) != OK) { ALOGE("%s: Failed to read metadata blob (sized %d). Possible " ALOGE("%s: Failed to read metadata blob (sized %zu). Possible " " serialization bug. Error %d %s", " serialization bug. Error %d %s", __FUNCTION__, metadataSize, err, strerror(-err)); __FUNCTION__, blobSize, err, strerror(-err)); break; break; } } const camera_metadata_t* tmp = reinterpret_cast<const camera_metadata_t*>(blob.data()); // arg2 = offset (blob) // Must be after blob since we don't know offset until after writeBlob. int32_t offsetTmp; if ((err = data.readInt32(&offsetTmp)) != OK) { ALOGE("%s: Failed to read metadata offsetTmp (error %d %s)", __FUNCTION__, err, strerror(-err)); break; } const size_t offset = static_cast<size_t>(offsetTmp); if (offset >= alignment) { ALOGE("%s: metadata offset(%zu) should be less than alignment(%zu)", __FUNCTION__, blobSize, alignment); err = BAD_VALUE; break; } const uintptr_t metadataStart = reinterpret_cast<uintptr_t>(blob.data()) + offset; const camera_metadata_t* tmp = reinterpret_cast<const camera_metadata_t*>(metadataStart); ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu", __FUNCTION__, alignment, tmp, offset); metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize); metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize); if (metadata == NULL) { if (metadata == NULL) { // We consider that allocation only fails if the validation // We consider that allocation only fails if the validation // also failed, therefore the readFromParcel was a failure. // also failed, therefore the readFromParcel was a failure. ALOGE("%s: metadata allocation and copy failed", __FUNCTION__); err = BAD_VALUE; err = BAD_VALUE; } } } while(0); } while(0); Loading @@ -485,38 +518,79 @@ status_t CameraMetadata::writeToParcel(Parcel& data, const camera_metadata_t* metadata) { const camera_metadata_t* metadata) { status_t res = OK; status_t res = OK; // arg0 = metadataSize (int32) /** * Below is the camera metadata parcel layout: * * |--------------------------------------------| * | arg0: blobSize | * | (length = 4) | * |--------------------------------------------|<--Skip the rest if blobSize == 0. * | | * | | * | arg1: blob | * | (length = variable, see arg1 layout below) | * | | * | | * |--------------------------------------------| * | arg2: offset | * | (length = 4) | * |--------------------------------------------| */ // arg0 = blobSize (int32) if (metadata == NULL) { if (metadata == NULL) { // Write zero blobSize for null metadata. return data.writeInt32(0); return data.writeInt32(0); } } /** * Always make the blob size sufficiently larger, as we need put alignment * padding and metadata into the blob. Since we don't know the alignment * offset before writeBlob. Then write the metadata to aligned offset. */ const size_t metadataSize = get_camera_metadata_compact_size(metadata); const size_t metadataSize = get_camera_metadata_compact_size(metadata); res = data.writeInt32(static_cast<int32_t>(metadataSize)); const size_t alignment = get_camera_metadata_alignment(); const size_t blobSize = metadataSize + alignment; res = data.writeInt32(static_cast<int32_t>(blobSize)); if (res != OK) { if (res != OK) { return res; return res; } } // arg1 = metadata (blob) size_t offset = 0; /** * arg1 = metadata (blob). * * The blob size is the sum of front padding size, metadata size and back padding * size, which is equal to metadataSize + alignment. * * The blob layout is: * |------------------------------------|<----Start address of the blob (unaligned). * | front padding | * | (size = offset) | * |------------------------------------|<----Aligned start address of metadata. * | | * | | * | metadata | * | (size = metadataSize) | * | | * | | * |------------------------------------| * | back padding | * | (size = alignment - offset) | * |------------------------------------|<----End address of blob. * (Blob start address + blob size). */ WritableBlob blob; WritableBlob blob; do { do { res = data.writeBlob(metadataSize, &blob); res = data.writeBlob(blobSize, &blob); if (res != OK) { if (res != OK) { break; break; } } copy_camera_metadata(blob.data(), metadataSize, metadata); const uintptr_t metadataStart = ALIGN_TO(blob.data(), alignment); offset = metadataStart - reinterpret_cast<uintptr_t>(blob.data()); IF_ALOGV() { ALOGV("%s: alignment is: %zu, metadata start: %p, offset: %zu", if (validate_camera_metadata_structure( __FUNCTION__, alignment, metadataStart, offset); (const camera_metadata_t*)blob.data(), copy_camera_metadata(reinterpret_cast<void*>(metadataStart), metadataSize, metadata); &metadataSize) != OK) { ALOGV("%s: Failed to validate metadata %p after writing blob", __FUNCTION__, blob.data()); } else { ALOGV("%s: Metadata written to blob. Validation success", __FUNCTION__); } } // Not too big of a problem since receiving side does hard validation // Not too big of a problem since receiving side does hard validation // Don't check the size since the compact size could be larger // Don't check the size since the compact size could be larger Loading @@ -528,6 +602,9 @@ status_t CameraMetadata::writeToParcel(Parcel& data, } while(false); } while(false); blob.release(); blob.release(); // arg2 = offset (int32) res = data.writeInt32(static_cast<int32_t>(offset)); return res; return res; } } Loading