Hold a lock while we access the preview heap.
copyFrameAndPostCopiedFrame was not holding a lock while it accessed
the preview heap. If the client process is torn down while the heap
is accessed, the memcpy could access memory that was deallocated.
This patch creates a local sp reference to the preview heap while
holding the lock, then releases the lock. This should prevent the
heap from being pulled out from underneath us.
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 29531ca..e548524 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -1215,20 +1215,27 @@
// the callback. For efficiency, reuse the same MemoryHeapBase
// provided it's big enough. Don't allocate the memory or
// perform the copy if there's no callback.
- if (mPreviewBuffer == 0) {
- mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
- } else if (size > mPreviewBuffer->virtualSize()) {
- mPreviewBuffer.clear();
- mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+
+ // hold the lock while we grab a reference to the preview buffer
+ sp<MemoryHeapBase> previewBuffer;
+ {
+ Mutex::Autolock lock(mLock);
+ if (mPreviewBuffer == 0) {
+ mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+ } else if (size > mPreviewBuffer->virtualSize()) {
+ mPreviewBuffer.clear();
+ mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+ }
if (mPreviewBuffer == 0) {
LOGE("failed to allocate space for preview buffer");
return;
}
+ previewBuffer = mPreviewBuffer;
}
- memcpy(mPreviewBuffer->base(),
+ memcpy(previewBuffer->base(),
(uint8_t *)heap->base() + offset, size);
- sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
+ sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
if (frame == 0) {
LOGE("failed to allocate space for frame callback");
return;