Fix security vulnerability: potential OOB write in audioserver am: e275907e57 am: 01e854056a am: 3e8ab60b7f am: 9161586309 am: ad29b47d91 am: 8b9b199891 am: 72729c449d am: 97bb7fe084 am: 3d6aada999 am: ffe82a3b4a am: ec601622f8 am: f50635bdc4 am: f1e829a54e
am: a2e95f5c9b
Change-Id: Ib06632143709a83ed37633dc6be6a40eb5955582
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index 8fc410d..2ec89a4 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -87,7 +87,6 @@
int64_t mStartTimeUs;
int16_t mMaxAmplitude;
int64_t mPrevSampleTimeUs;
- int64_t mFirstSampleTimeUs;
int64_t mInitialReadTimeUs;
int64_t mNumFramesReceived;
int64_t mNumClientOwnedBuffers;
diff --git a/include/media/stagefright/SimpleDecodingSource.h b/include/media/stagefright/SimpleDecodingSource.h
index 534097b..e6aee6a 100644
--- a/include/media/stagefright/SimpleDecodingSource.h
+++ b/include/media/stagefright/SimpleDecodingSource.h
@@ -71,12 +71,13 @@
// Construct this using a codec, source and looper.
SimpleDecodingSource(
const sp<MediaCodec> &codec, const sp<IMediaSource> &source, const sp<ALooper> &looper,
- bool usingSurface, const sp<AMessage> &format);
+ bool usingSurface, bool isVorbis, const sp<AMessage> &format);
sp<MediaCodec> mCodec;
sp<IMediaSource> mSource;
sp<ALooper> mLooper;
bool mUsingSurface;
+ bool mIsVorbis;
enum State {
INIT,
STARTED,
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 790c6da..efdee77 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -60,7 +60,6 @@
mStartTimeUs(0),
mMaxAmplitude(0),
mPrevSampleTimeUs(0),
- mFirstSampleTimeUs(-1ll),
mInitialReadTimeUs(0),
mNumFramesReceived(0),
mNumClientOwnedBuffers(0) {
@@ -277,12 +276,8 @@
}
if (mSampleRate != mOutSampleRate) {
- if (mFirstSampleTimeUs < 0) {
- mFirstSampleTimeUs = timeUs;
- }
- timeUs = mFirstSampleTimeUs + (timeUs - mFirstSampleTimeUs)
- * (int64_t)mSampleRate / (int64_t)mOutSampleRate;
- buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ timeUs *= (int64_t)mSampleRate / (int64_t)mOutSampleRate;
+ buffer->meta_data()->setInt64(kKeyTime, timeUs);
}
*out = buffer;
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index eb1f193..770681a 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -567,6 +567,10 @@
}
for (size_t i = 0; i < mNumSyncSamples; ++i) {
+ if (mSyncSamples[i] == 0) {
+ ALOGE("b/32423862, unexpected zero value in stss");
+ continue;
+ }
mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
}
diff --git a/media/libstagefright/SimpleDecodingSource.cpp b/media/libstagefright/SimpleDecodingSource.cpp
index de21c5e..2503a32 100644
--- a/media/libstagefright/SimpleDecodingSource.cpp
+++ b/media/libstagefright/SimpleDecodingSource.cpp
@@ -18,6 +18,7 @@
#include <media/ICrypto.h>
#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
@@ -74,7 +75,10 @@
err = codec->getOutputFormat(&format);
}
if (err == OK) {
- return new SimpleDecodingSource(codec, source, looper, surface != NULL, format);
+ return new SimpleDecodingSource(codec, source, looper,
+ surface != NULL,
+ strcmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS) == 0,
+ format);
}
ALOGD("Failed to configure codec '%s'", componentName.c_str());
@@ -90,11 +94,12 @@
SimpleDecodingSource::SimpleDecodingSource(
const sp<MediaCodec> &codec, const sp<IMediaSource> &source, const sp<ALooper> &looper,
- bool usingSurface, const sp<AMessage> &format)
+ bool usingSurface, bool isVorbis, const sp<AMessage> &format)
: mCodec(codec),
mSource(source),
mLooper(looper),
mUsingSurface(usingSurface),
+ mIsVorbis(isVorbis),
mProtectedState(format) {
mCodec->getName(&mComponentName);
}
@@ -280,16 +285,25 @@
if (in_buf != NULL) {
int64_t timestampUs = 0;
CHECK(in_buf->meta_data()->findInt64(kKeyTime, ×tampUs));
- if (in_buf->range_length() > in_buffer->capacity()) {
+ if (in_buf->range_length() + (mIsVorbis ? 4 : 0) > in_buffer->capacity()) {
ALOGW("'%s' received %zu input bytes for buffer of size %zu",
mComponentName.c_str(),
- in_buf->range_length(), in_buffer->capacity());
+ in_buf->range_length() + (mIsVorbis ? 4 : 0), in_buffer->capacity());
}
+ size_t cpLen = min(in_buf->range_length(), in_buffer->capacity());
memcpy(in_buffer->base(), (uint8_t *)in_buf->data() + in_buf->range_offset(),
- min(in_buf->range_length(), in_buffer->capacity()));
+ cpLen );
+
+ if (mIsVorbis) {
+ int32_t numPageSamples;
+ if (!in_buf->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
+ numPageSamples = -1;
+ }
+ memcpy(in_buffer->base() + cpLen, &numPageSamples, sizeof(numPageSamples));
+ }
res = mCodec->queueInputBuffer(
- in_ix, 0 /* offset */, in_buf->range_length(),
+ in_ix, 0 /* offset */, in_buf->range_length() + (mIsVorbis ? 4 : 0),
timestampUs, 0 /* flags */);
if (res != OK) {
ALOGI("[%s] failed to queue input buffer #%zu", mComponentName.c_str(), in_ix);
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 93d6584..0c4056d 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -792,7 +792,8 @@
if (mPrevCaptureUs < 0ll) {
// first capture
mPrevCaptureUs = timeUs;
- mPrevFrameUs = timeUs;
+ // adjust the first sample timestamp.
+ mPrevFrameUs = (timeUs * mTimePerFrameUs) / mTimePerCaptureUs;
} else {
// snap to nearest capture point
int64_t nFrames = (timeUs + mTimePerCaptureUs / 2 - mPrevCaptureUs)
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index be71f43..166e6f1 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -221,8 +221,7 @@
static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
- iter = mObj->mIds.begin();
- while (iter != mObj->mIds.end()) {
+ for (iter = mObj->mIds.begin(); iter != mObj->mIds.end(); ++iter) {
if (iter->array() == id.ptr && iter->size() == id.length) {
return true;
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index d0df6d1..6124fed 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -467,8 +467,8 @@
// CameraInfo is for android.hardware.Camera which does not
// support external camera facing. The closest approximation would be
// front camera.
- if (cameraInfo->orientation == CAMERA_FACING_EXTERNAL) {
- cameraInfo->orientation = CAMERA_FACING_FRONT;
+ if (cameraInfo->facing == CAMERA_FACING_EXTERNAL) {
+ cameraInfo->facing = CAMERA_FACING_FRONT;
}
}
return rc;
@@ -2532,7 +2532,8 @@
write(fd, result.string(), result.size());
} else {
result.appendFormat(" Facing: %s\n",
- info.facing == CAMERA_FACING_BACK ? "BACK" : "FRONT");
+ info.facing == CAMERA_FACING_BACK ? "BACK" :
+ info.facing == CAMERA_FACING_FRONT ? "FRONT" : "EXTERNAL");
result.appendFormat(" Orientation: %d\n", info.orientation);
int deviceVersion;
if (mModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_0) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 48a2a99..eece01b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2222,6 +2222,14 @@
}
}
+void Camera3Device::removeInFlightMapEntryLocked(int idx) {
+ mInFlightMap.removeItemsAt(idx, 1);
+
+ // Indicate idle inFlightMap to the status tracker
+ if (mInFlightMap.size() == 0) {
+ mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
+ }
+}
void Camera3Device::removeInFlightRequestIfReadyLocked(int idx) {
@@ -2257,13 +2265,7 @@
returnOutputBuffers(request.pendingOutputBuffers.array(),
request.pendingOutputBuffers.size(), 0);
- mInFlightMap.removeItemsAt(idx, 1);
-
- // Indicate idle inFlightMap to the status tracker
- if (mInFlightMap.size() == 0) {
- mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
- }
-
+ removeInFlightMapEntryLocked(idx);
ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
}
@@ -3438,6 +3440,20 @@
captureRequest->mResultExtras);
}
}
+
+ // Remove yet-to-be submitted inflight request from inflightMap
+ {
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent != NULL) {
+ Mutex::Autolock l(parent->mInFlightLock);
+ ssize_t idx = parent->mInFlightMap.indexOfKey(captureRequest->mResultExtras.frameNumber);
+ if (idx >= 0) {
+ ALOGV("%s: Remove inflight request from queue: frameNumber %" PRId64,
+ __FUNCTION__, captureRequest->mResultExtras.frameNumber);
+ parent->removeInFlightMapEntryLocked(idx);
+ }
+ }
+ }
}
Mutex::Autolock l(mRequestLock);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 17893a9..f422813 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -849,6 +849,9 @@
/**** Scope for mInFlightLock ****/
+ // Remove the in-flight map entry of the given index from mInFlightMap.
+ // It must only be called with mInFlightLock held.
+ void removeInFlightMapEntryLocked(int idx);
// Remove the in-flight request of the given index from mInFlightMap
// if it's no longer needed. It must only be called with mInFlightLock held.
void removeInFlightRequestIfReadyLocked(int idx);