/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "camera2common.h" #include using namespace std; using namespace android; using namespace android::hardware; constexpr int32_t kFrameRateMin = 1; constexpr int32_t kFrameRateMax = 120; constexpr int32_t kCamIdMin = 0; constexpr int32_t kCamIdMax = 1; constexpr int32_t kNumMin = 0; constexpr int32_t kNumMax = 1024; constexpr int32_t kMemoryDealerSize = 1000; constexpr int32_t kRangeMin = 0; constexpr int32_t kRangeMax = 1000; constexpr int32_t kSizeMin = 0; constexpr int32_t kSizeMax = 1000; constexpr int32_t kValidCMD[] = {CAMERA_CMD_START_SMOOTH_ZOOM, CAMERA_CMD_STOP_SMOOTH_ZOOM, CAMERA_CMD_SET_DISPLAY_ORIENTATION, CAMERA_CMD_ENABLE_SHUTTER_SOUND, CAMERA_CMD_PLAY_RECORDING_SOUND, CAMERA_CMD_START_FACE_DETECTION, CAMERA_CMD_STOP_FACE_DETECTION, CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG, CAMERA_CMD_PING, CAMERA_CMD_SET_VIDEO_BUFFER_COUNT, CAMERA_CMD_SET_VIDEO_FORMAT}; constexpr int32_t kValidVideoBufferMode[] = {ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV, ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_METADATA, ICamera::VIDEO_BUFFER_MODE_BUFFER_QUEUE}; constexpr int32_t kValidPreviewCallbackFlag[] = { CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK, CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK, CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK, CAMERA_FRAME_CALLBACK_FLAG_NOOP, CAMERA_FRAME_CALLBACK_FLAG_CAMCORDER, CAMERA_FRAME_CALLBACK_FLAG_CAMERA, CAMERA_FRAME_CALLBACK_FLAG_BARCODE_SCANNER}; constexpr int32_t kValidFacing[] = {android::hardware::CAMERA_FACING_BACK, android::hardware::CAMERA_FACING_FRONT}; constexpr int32_t kValidOrientation[] = {0, 90, 180, 270}; class TestCameraListener : public CameraListener { public: virtual ~TestCameraListener() = default; void notify(int32_t /*msgType*/, int32_t /*ext1*/, int32_t /*ext2*/) override { return; }; void postData(int32_t /*msgType*/, const sp& /*dataPtr*/, camera_frame_metadata_t* /*metadata*/) override { return; }; void postDataTimestamp(nsecs_t /*timestamp*/, int32_t /*msgType*/, const sp& /*dataPtr*/) override { return; }; void postRecordingFrameHandleTimestamp(nsecs_t /*timestamp*/, native_handle_t* /*handle*/) override { return; }; void postRecordingFrameHandleTimestampBatch( const std::vector& /*timestamps*/, const std::vector& /*handles*/) override { return; }; }; class CameraFuzzer : public ::android::hardware::BnCameraClient { public: void process(const uint8_t* data, size_t size); ~CameraFuzzer() { delete mCameraMetadata; mComposerClient.clear(); mSurfaceControl.clear(); mSurface.clear(); mCamera.clear(); mMemoryDealer.clear(); mIMem.clear(); mCameraListener.clear(); mCameraService.clear(); } private: bool initCamera(); void initCameraMetadata(); void invokeCamera(); void invokeCameraUtils(); void invokeCameraBase(); void invokeCameraMetadata(); void invokeSetParameters(); sp mCamera = nullptr; CameraMetadata* mCameraMetadata = nullptr; sp mComposerClient = nullptr; sp mSurfaceControl = nullptr; sp mSurface = nullptr; sp mMemoryDealer = nullptr; sp mIMem = nullptr; sp mCameraListener = nullptr; sp mCameraService = nullptr; sp cameraDevice = nullptr; FuzzedDataProvider* mFDP = nullptr; // CameraClient interface void notifyCallback(int32_t, int32_t, int32_t) override { return; }; void dataCallback(int32_t, const sp&, camera_frame_metadata_t*) override { return; }; void dataCallbackTimestamp(nsecs_t, int32_t, const sp&) override { return; }; void recordingFrameHandleCallbackTimestamp(nsecs_t, native_handle_t*) override { return; }; void recordingFrameHandleCallbackTimestampBatch(const std::vector&, const std::vector&) override { return; }; }; bool CameraFuzzer::initCamera() { ProcessState::self()->startThreadPool(); sp sm = defaultServiceManager(); sp binder = sm->getService(String16("media.camera")); mCameraService = interface_cast(binder); mCameraService->connect(this, mFDP->ConsumeIntegral() /* cameraId */, String16("CAMERAFUZZ"), hardware::ICameraService::USE_CALLING_UID, hardware::ICameraService::USE_CALLING_PID, /*targetSdkVersion*/ __ANDROID_API_FUTURE__, /*overrideToPortrait*/false, /*forceSlowJpegMode*/false, &cameraDevice); mCamera = Camera::create(cameraDevice); if (!mCamera) { return false; } return true; } void CameraFuzzer::invokeSetParameters() { String8 s = mCamera->getParameters(); CameraParameters params(s); int32_t width = mFDP->ConsumeIntegral(); int32_t height = mFDP->ConsumeIntegral(); params.setVideoSize(width, height); int32_t frameRate = mFDP->ConsumeIntegralInRange(kFrameRateMin, kFrameRateMax); params.setPreviewFrameRate(frameRate); mCamera->setParameters(params.flatten()); } void CameraFuzzer::invokeCamera() { if (!initCamera()) { return; } int32_t cameraId = mFDP->ConsumeIntegralInRange(kCamIdMin, kCamIdMax); Camera::getNumberOfCameras(); CameraInfo cameraInfo; cameraInfo.facing = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFacing) : mFDP->ConsumeIntegral(); cameraInfo.orientation = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidOrientation) : mFDP->ConsumeIntegral(); Camera::getCameraInfo(cameraId, /*overrideToPortrait*/false, &cameraInfo); mCamera->reconnect(); mComposerClient = new SurfaceComposerClient; mSurfaceControl = mComposerClient->createSurface( static_cast(mFDP->ConsumeRandomLengthString().c_str()) /* name */, mFDP->ConsumeIntegral() /* width */, mFDP->ConsumeIntegral() /* height */, mFDP->ConsumeIntegral() /* format */, mFDP->ConsumeIntegral() /* flags */); if (mSurfaceControl) { mSurface = mSurfaceControl->getSurface(); mCamera->setPreviewTarget(mSurface->getIGraphicBufferProducer()); mCamera->startPreview(); mCamera->stopPreview(); mCamera->previewEnabled(); mCamera->startRecording(); mCamera->stopRecording(); } mCamera->lock(); mCamera->unlock(); mCamera->autoFocus(); mCamera->cancelAutoFocus(); int32_t msgType = mFDP->ConsumeIntegral(); mCamera->takePicture(msgType); invokeSetParameters(); int32_t cmd; if (mFDP->ConsumeBool()) { cmd = mFDP->PickValueInArray(kValidCMD); } else { cmd = mFDP->ConsumeIntegral(); } int32_t arg1 = mFDP->ConsumeIntegral(); int32_t arg2 = mFDP->ConsumeIntegral(); mCamera->sendCommand(cmd, arg1, arg2); int32_t videoBufferMode = mFDP->PickValueInArray(kValidVideoBufferMode); mCamera->setVideoBufferMode(videoBufferMode); if (mSurfaceControl) { mSurface = mSurfaceControl->getSurface(); mCamera->setVideoTarget(mSurface->getIGraphicBufferProducer()); } mCameraListener = sp::make(); mCamera->setListener(mCameraListener); int32_t previewCallbackFlag; if (mFDP->ConsumeBool()) { previewCallbackFlag = mFDP->PickValueInArray(kValidPreviewCallbackFlag); } else { previewCallbackFlag = mFDP->ConsumeIntegral(); } mCamera->setPreviewCallbackFlags(previewCallbackFlag); if (mSurfaceControl) { mSurface = mSurfaceControl->getSurface(); mCamera->setPreviewCallbackTarget(mSurface->getIGraphicBufferProducer()); } mCamera->getRecordingProxy(); int32_t mode = mFDP->ConsumeIntegral(); mCamera->setAudioRestriction(mode); mCamera->getGlobalAudioRestriction(); mCamera->recordingEnabled(); mMemoryDealer = new MemoryDealer(kMemoryDealerSize); mIMem = mMemoryDealer->allocate(kMemoryDealerSize); mCamera->releaseRecordingFrame(mIMem); int32_t numFds = mFDP->ConsumeIntegralInRange(kNumMin, kNumMax); int32_t numInts = mFDP->ConsumeIntegralInRange(kNumMin, kNumMax); native_handle_t* handle = native_handle_create(numFds, numInts); mCamera->releaseRecordingFrameHandle(handle); int32_t msgTypeNC = mFDP->ConsumeIntegral(); int32_t ext = mFDP->ConsumeIntegral(); int32_t ext2 = mFDP->ConsumeIntegral(); mCamera->notifyCallback(msgTypeNC, ext, ext2); int64_t timestamp = mFDP->ConsumeIntegral(); mCamera->dataCallbackTimestamp(timestamp, msgTypeNC, mIMem); mCamera->recordingFrameHandleCallbackTimestamp(timestamp, handle); } void CameraFuzzer::invokeCameraUtils() { CameraMetadata staticMetadata; int32_t orientVal = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidOrientation) : mFDP->ConsumeIntegral(); uint8_t facingVal = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFacing) : mFDP->ConsumeIntegral(); staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1); staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1); int32_t transform = 0; CameraUtils::getRotationTransform( staticMetadata, mFDP->ConsumeIntegral() /* mirrorMode */, &transform /*out*/); CameraUtils::isCameraServiceDisabled(); } void CameraFuzzer::invokeCameraBase() { CameraInfo cameraInfo; cameraInfo.facing = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidFacing) : mFDP->ConsumeIntegral(); cameraInfo.orientation = mFDP->ConsumeBool() ? mFDP->PickValueInArray(kValidOrientation) : mFDP->ConsumeIntegral(); invokeReadWriteParcel(&cameraInfo); CameraStatus* cameraStatus = nullptr; if (mFDP->ConsumeBool()) { cameraStatus = new CameraStatus(); } else { string cid = mFDP->ConsumeRandomLengthString(); String8 id(cid.c_str()); int32_t status = mFDP->ConsumeIntegral(); size_t unavailSubIdsSize = mFDP->ConsumeIntegralInRange(kSizeMin, kSizeMax); vector unavailSubIds; for (size_t idx = 0; idx < unavailSubIdsSize; ++idx) { string subId = mFDP->ConsumeRandomLengthString(); String8 unavailSubId(subId.c_str()); unavailSubIds.push_back(unavailSubId); } string clientPkg = mFDP->ConsumeRandomLengthString(); String8 clientPackage(clientPkg.c_str()); cameraStatus = new CameraStatus(id, status, unavailSubIds, clientPackage); } invokeReadWriteParcel(cameraStatus); delete cameraStatus; } void CameraFuzzer::initCameraMetadata() { if (mFDP->ConsumeBool()) { mCameraMetadata = new CameraMetadata(); } else { size_t entryCapacity = mFDP->ConsumeIntegralInRange(kSizeMin, kSizeMax); size_t dataCapacity = mFDP->ConsumeIntegralInRange(kSizeMin, kSizeMax); mCameraMetadata = new CameraMetadata(entryCapacity, dataCapacity); } } void CameraFuzzer::invokeCameraMetadata() { initCameraMetadata(); const camera_metadata_t* metadataBuffer = nullptr; if (mFDP->ConsumeBool()) { metadataBuffer = mCameraMetadata->getAndLock(); } mCameraMetadata->entryCount(); mCameraMetadata->isEmpty(); mCameraMetadata->bufferSize(); mCameraMetadata->sort(); uint32_t tag = mFDP->ConsumeIntegral(); uint8_t dataUint8 = mFDP->ConsumeIntegral(); int32_t dataInt32 = mFDP->ConsumeIntegral(); int64_t dataInt64 = mFDP->ConsumeIntegral(); float dataFloat = mFDP->ConsumeFloatingPoint(); double dataDouble = mFDP->ConsumeFloatingPoint(); camera_metadata_rational dataRational; dataRational.numerator = mFDP->ConsumeIntegral(); dataRational.denominator = mFDP->ConsumeIntegral(); string dataStr = mFDP->ConsumeRandomLengthString(); String8 dataString(dataStr.c_str()); size_t data_count = 1; mCameraMetadata->update(tag, &dataUint8, data_count); mCameraMetadata->update(tag, &dataInt32, data_count); mCameraMetadata->update(tag, &dataFloat, data_count); mCameraMetadata->update(tag, &dataInt64, data_count); mCameraMetadata->update(tag, &dataRational, data_count); mCameraMetadata->update(tag, &dataDouble, data_count); mCameraMetadata->update(tag, dataString); uint32_t tagExists = mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral(); mCameraMetadata->exists(tagExists); uint32_t tagFind = mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral(); mCameraMetadata->find(tagFind); uint32_t tagErase = mFDP->ConsumeBool() ? tag : mFDP->ConsumeIntegral(); mCameraMetadata->erase(tagErase); mCameraMetadata->unlock(metadataBuffer); std::vector tagsRemoved; uint64_t vendorId = mFDP->ConsumeIntegral(); mCameraMetadata->removePermissionEntries(vendorId, &tagsRemoved); string name = mFDP->ConsumeRandomLengthString(); VendorTagDescriptor vTags; uint32_t tagName = mFDP->ConsumeIntegral(); mCameraMetadata->getTagFromName(name.c_str(), &vTags, &tagName); invokeReadWriteNullParcel(mCameraMetadata); invokeReadWriteParcel(mCameraMetadata); int32_t fd = open("/dev/null", O_CLOEXEC | O_RDWR | O_CREAT); int32_t verbosity = mFDP->ConsumeIntegralInRange(kRangeMin, kRangeMax); int32_t indentation = mFDP->ConsumeIntegralInRange(kRangeMin, kRangeMax); mCameraMetadata->dump(fd, verbosity, indentation); CameraMetadata metadataCopy(mCameraMetadata->release()); CameraMetadata otherCameraMetadata; mCameraMetadata->swap(otherCameraMetadata); close(fd); } void CameraFuzzer::process(const uint8_t* data, size_t size) { mFDP = new FuzzedDataProvider(data, size); invokeCamera(); invokeCameraUtils(); invokeCameraBase(); invokeCameraMetadata(); delete mFDP; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { sp cameraFuzzer = new CameraFuzzer(); cameraFuzzer->process(data, size); cameraFuzzer.clear(); return 0; }