status_t BnOMX::onTransact(
 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
 switch (code) {
 case LIVES_LOCALLY:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);
            node_id node = (node_id)data.readInt32();
 pid_t pid = (pid_t)data.readInt32();
            reply->writeInt32(livesLocally(node, pid));

 return OK;
 }

 case LIST_NODES:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

 List<ComponentInfo> list;
            listNodes(&list);

            reply->writeInt32(list.size());
 for (List<ComponentInfo>::iterator it = list.begin();
                 it != list.end(); ++it) {
 ComponentInfo &cur = *it;

                reply->writeString8(cur.mName);
                reply->writeInt32(cur.mRoles.size());
 for (List<String8>::iterator role_it = cur.mRoles.begin();
                     role_it != cur.mRoles.end(); ++role_it) {
                    reply->writeString8(*role_it);
 }
 }

 return NO_ERROR;
 }

 case ALLOCATE_NODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

 const char *name = data.readCString();

            sp<IOMXObserver> observer =
                interface_cast<IOMXObserver>(data.readStrongBinder());

            node_id node;

 status_t err = allocateNode(name, observer, &node);
            reply->writeInt32(err);
 if (err == OK) {
                reply->writeInt32((int32_t)node);
 }

 return NO_ERROR;
 }

 case FREE_NODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

            reply->writeInt32(freeNode(node));

 return NO_ERROR;
 }

 case SEND_COMMAND:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

            OMX_COMMANDTYPE cmd =
 static_cast<OMX_COMMANDTYPE>(data.readInt32());

            OMX_S32 param = data.readInt32();
            reply->writeInt32(sendCommand(node, cmd, param));

 return NO_ERROR;
 }

 case GET_PARAMETER:
 case SET_PARAMETER:
 case GET_CONFIG:
 case SET_CONFIG:
 case SET_INTERNAL_OPTION:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

 size_t size = data.readInt64();

 status_t err = NOT_ENOUGH_DATA;

             void *params = NULL;
             size_t pageSize = 0;
             size_t allocSize = 0;
            bool isUsageBits = (index == (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits);
            if ((isUsageBits && size < 4) ||
                    (!isUsageBits && code != SET_INTERNAL_OPTION && size < 8)) {
                ALOGE("b/27207275 (%zu) (%d/%d)", size, int(index), int(code));
                 android_errorWriteLog(0x534e4554, "27207275");
             } else {
                 err = NO_MEMORY;
                pageSize = (size_t) sysconf(_SC_PAGE_SIZE);
 if (size > SIZE_MAX - (pageSize * 2)) {
                    ALOGE("requested param size too big");
 } else {
                    allocSize = (size + pageSize * 2) & ~(pageSize - 1);
                    params = mmap(NULL, allocSize, PROT_READ | PROT_WRITE,
                            MAP_PRIVATE | MAP_ANONYMOUS, -1 /* fd */, 0 /* offset */);
 }
 if (params != MAP_FAILED) {
                    err = data.read(params, size);
 if (err != OK) {
                        android_errorWriteLog(0x534e4554, "26914474");
 } else {
                        err = NOT_ENOUGH_DATA;
                        OMX_U32 declaredSize = *(OMX_U32*)params;
 if (code != SET_INTERNAL_OPTION &&
                                index != (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits &&
                                declaredSize > size) {
                            ALOGE("b/27207275 (%u/%zu)", declaredSize, size);
                            android_errorWriteLog(0x534e4554, "27207275");
 } else {
                            mprotect((char*)params + allocSize - pageSize, pageSize, PROT_NONE);
 switch (code) {
 case GET_PARAMETER:
                                    err = getParameter(node, index, params, size);
 break;
 case SET_PARAMETER:
                                    err = setParameter(node, index, params, size);
 break;
 case GET_CONFIG:
                                    err = getConfig(node, index, params, size);
 break;
 case SET_CONFIG:
                                    err = setConfig(node, index, params, size);
 break;
 case SET_INTERNAL_OPTION:
 {
 InternalOptionType type =
 (InternalOptionType)data.readInt32();

                                    err = setInternalOption(node, index, type, params, size);
 break;
 }

 default:
                                    TRESPASS();
 }
 }
 }
 } else {
                    ALOGE("couldn't map: %s", strerror(errno));
 }
 }

            reply->writeInt32(err);

 if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
                reply->write(params, size);
 }

 if (params) {
                munmap(params, allocSize);
 }
            params = NULL;

 return NO_ERROR;
 }

 case GET_STATE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_STATETYPE state = OMX_StateInvalid;

 status_t err = getState(node, &state);
            reply->writeInt32(state);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case ENABLE_GRAPHIC_BUFFERS:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();

 status_t err = enableGraphicBuffers(node, port_index, enable);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case GET_GRAPHIC_BUFFER_USAGE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

            OMX_U32 usage = 0;
 status_t err = getGraphicBufferUsage(node, port_index, &usage);
            reply->writeInt32(err);
            reply->writeInt32(usage);

 return NO_ERROR;
 }

 case USE_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());
            OMX_U32 allottedSize = data.readInt32();

            buffer_id buffer;
 status_t err = useBuffer(node, port_index, params, &buffer, allottedSize);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case USE_GRAPHIC_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);

            buffer_id buffer;
 status_t err = useGraphicBuffer(
                    node, port_index, graphicBuffer, &buffer);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case UPDATE_GRAPHIC_BUFFER_IN_META:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);
            buffer_id buffer = (buffer_id)data.readInt32();

 status_t err = updateGraphicBufferInMeta(
                    node, port_index, graphicBuffer, buffer);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case CREATE_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

            sp<IGraphicBufferProducer> bufferProducer;
 MetadataBufferType type = kMetadataBufferTypeInvalid;
 status_t err = createInputSurface(node, port_index, &bufferProducer, &type);

 if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
                android_errorWriteLog(0x534e4554, "26324358");
 }

            reply->writeInt32(type);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
 }

 return NO_ERROR;
 }

 case CREATE_PERSISTENT_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            sp<IGraphicBufferProducer> bufferProducer;
            sp<IGraphicBufferConsumer> bufferConsumer;
 status_t err = createPersistentInputSurface(
 &bufferProducer, &bufferConsumer);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
                reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
 }

 return NO_ERROR;
 }

 case SET_INPUT_SURFACE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();

            sp<IGraphicBufferConsumer> bufferConsumer =
                    interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());

 MetadataBufferType type = kMetadataBufferTypeInvalid;
 status_t err = setInputSurface(node, port_index, bufferConsumer, &type);

 if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
                android_errorWriteLog(0x534e4554, "26324358");
 }

            reply->writeInt32(type);
            reply->writeInt32(err);
 return NO_ERROR;
 }

 case SIGNAL_END_OF_INPUT_STREAM:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();

 status_t err = signalEndOfInputStream(node);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case STORE_META_DATA_IN_BUFFERS:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();

 MetadataBufferType type = kMetadataBufferTypeInvalid;
 status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);

            reply->writeInt32(type);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case PREPARE_FOR_ADAPTIVE_PLAYBACK:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();
            OMX_U32 max_width = data.readInt32();
            OMX_U32 max_height = data.readInt32();

 status_t err = prepareForAdaptivePlayback(
                    node, port_index, enable, max_width, max_height);
            reply->writeInt32(err);

 return NO_ERROR;
 }

 case CONFIGURE_VIDEO_TUNNEL_MODE:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL tunneled = (OMX_BOOL)data.readInt32();
            OMX_U32 audio_hw_sync = data.readInt32();

 native_handle_t *sideband_handle = NULL;
 status_t err = configureVideoTunnelMode(
                    node, port_index, tunneled, audio_hw_sync, &sideband_handle);
            reply->writeInt32(err);
 if(err == OK){
                reply->writeNativeHandle(sideband_handle);
 }

 return NO_ERROR;
 }

 case ALLOC_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
 if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) {
                ALOGE("b/24310423");
                reply->writeInt32(INVALID_OPERATION);
 return NO_ERROR;
 }

 size_t size = data.readInt64();

            buffer_id buffer;
 void *buffer_data;
 status_t err = allocateBuffer(
                    node, port_index, size, &buffer, &buffer_data);
            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
                reply->writeInt64((uintptr_t)buffer_data);
 }

 return NO_ERROR;
 }

 case ALLOC_BUFFER_WITH_BACKUP:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());
            OMX_U32 allottedSize = data.readInt32();

            buffer_id buffer;
 status_t err = allocateBufferWithBackup(
                    node, port_index, params, &buffer, allottedSize);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32((int32_t)buffer);
 }

 return NO_ERROR;
 }

 case FREE_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            OMX_U32 port_index = data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            reply->writeInt32(freeBuffer(node, port_index, buffer));

 return NO_ERROR;
 }

 case FILL_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
 bool haveFence = data.readInt32();
 int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
            reply->writeInt32(fillBuffer(node, buffer, fenceFd));

 return NO_ERROR;
 }

 case EMPTY_BUFFER:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
            buffer_id buffer = (buffer_id)data.readInt32();
            OMX_U32 range_offset = data.readInt32();
            OMX_U32 range_length = data.readInt32();
            OMX_U32 flags = data.readInt32();
            OMX_TICKS timestamp = data.readInt64();
 bool haveFence = data.readInt32();
 int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
            reply->writeInt32(emptyBuffer(
                    node, buffer, range_offset, range_length, flags, timestamp, fenceFd));

 return NO_ERROR;
 }

 case GET_EXTENSION_INDEX:
 {
            CHECK_OMX_INTERFACE(IOMX, data, reply);

            node_id node = (node_id)data.readInt32();
 const char *parameter_name = data.readCString();

            OMX_INDEXTYPE index;
 status_t err = getExtensionIndex(node, parameter_name, &index);

            reply->writeInt32(err);

 if (err == OK) {
                reply->writeInt32(index);
 }

 return OK;
 }

 default:
 return BBinder::onTransact(code, data, reply, flags);
 }
}


status_t ACodec::setupAACCodec(
 bool encoder, int32_t numChannels, int32_t sampleRate,
 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
 int32_t maxOutputChannelCount, const drcParams_t& drc,
 int32_t pcmLimiterEnable) {
 if (encoder && isADTS) {
 return -EINVAL;
 }

 status_t err = setupRawAudioFormat(
            encoder ? kPortIndexInput : kPortIndexOutput,
            sampleRate,
            numChannels);

 if (err != OK) {
 return err;
 }

 if (encoder) {
        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);

 if (err != OK) {
 return err;
 }

        OMX_PARAM_PORTDEFINITIONTYPE def;
 InitOMXParams(&def);
        def.nPortIndex = kPortIndexOutput;

        err = mOMX->getParameter(
                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));

 if (err != OK) {
 return err;
 }

        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;

        err = mOMX->setParameter(
                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));

 if (err != OK) {
 return err;
 }

        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
 InitOMXParams(&profile);
        profile.nPortIndex = kPortIndexOutput;

        err = mOMX->getParameter(
                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));

 if (err != OK) {
 return err;
 }

        profile.nChannels = numChannels;

        profile.eChannelMode =
 (numChannels == 1)
 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;

        profile.nSampleRate = sampleRate;
        profile.nBitRate = bitRate;
        profile.nAudioBandWidth = 0;
        profile.nFrameLength = 0;
        profile.nAACtools = OMX_AUDIO_AACToolAll;
        profile.nAACERtools = OMX_AUDIO_AACERNone;
        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
 switch (sbrMode) {
 case 0:
            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
 break;
 case 1:
            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
 break;
 case 2:
            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
 break;
 case -1:
            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
 break;
 default:
 return BAD_VALUE;
 }

        err = mOMX->setParameter(
                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));

 if (err != OK) {
 return err;
 }

 return err;
 }

    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
 InitOMXParams(&profile);
    profile.nPortIndex = kPortIndexInput;

    err = mOMX->getParameter(
            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));

 if (err != OK) {
 return err;
 }

    profile.nChannels = numChannels;
    profile.nSampleRate = sampleRate;

    profile.eAACStreamFormat =
        isADTS
 ? OMX_AUDIO_AACStreamFormatMP4ADTS

             : OMX_AUDIO_AACStreamFormatMP4FF;

     OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
     presentation.nMaxOutputChannels = maxOutputChannelCount;
     presentation.nDrcCut = drc.drcCut;
     presentation.nDrcBoost = drc.drcBoost;
    presentation.nHeavyCompression = drc.heavyCompression;
    presentation.nTargetReferenceLevel = drc.targetRefLevel;
    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
    presentation.nPCMLimiterEnable = pcmLimiterEnable;

 status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
 if (res == OK) {
        mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
 &presentation, sizeof(presentation));
 } else {
        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
 }
 return res;
}

mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, and 6.x before 2016-06-01 does not validate OMX buffer sizes, which allows attackers to gain privileges via a crafted application, as demonstrated by obtaining Signature or SignatureOrSystem access, aka internal bug 27207275.


status_t ACodec::setupAACCodec(
 bool encoder, int32_t numChannels, int32_t sampleRate,
 int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
 int32_t maxOutputChannelCount, const drcParams_t& drc,
 int32_t pcmLimiterEnable) {
 if (encoder && isADTS) {
 return -EINVAL;
 }

 status_t err = setupRawAudioFormat(
            encoder ? kPortIndexInput : kPortIndexOutput,
            sampleRate,
            numChannels);

 if (err != OK) {
 return err;
 }

 if (encoder) {
        err = selectAudioPortFormat(kPortIndexOutput, OMX_AUDIO_CodingAAC);

 if (err != OK) {
 return err;
 }

        OMX_PARAM_PORTDEFINITIONTYPE def;
 InitOMXParams(&def);
        def.nPortIndex = kPortIndexOutput;

        err = mOMX->getParameter(
                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));

 if (err != OK) {
 return err;
 }

        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;

        err = mOMX->setParameter(
                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));

 if (err != OK) {
 return err;
 }

        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
 InitOMXParams(&profile);
        profile.nPortIndex = kPortIndexOutput;

        err = mOMX->getParameter(
                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));

 if (err != OK) {
 return err;
 }

        profile.nChannels = numChannels;

        profile.eChannelMode =
 (numChannels == 1)
 ? OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo;

        profile.nSampleRate = sampleRate;
        profile.nBitRate = bitRate;
        profile.nAudioBandWidth = 0;
        profile.nFrameLength = 0;
        profile.nAACtools = OMX_AUDIO_AACToolAll;
        profile.nAACERtools = OMX_AUDIO_AACERNone;
        profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
 switch (sbrMode) {
 case 0:
            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
 break;
 case 1:
            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
 break;
 case 2:
            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
 break;
 case -1:
            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
 break;
 default:
 return BAD_VALUE;
 }

        err = mOMX->setParameter(
                mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));

 if (err != OK) {
 return err;
 }

 return err;
 }

    OMX_AUDIO_PARAM_AACPROFILETYPE profile;
 InitOMXParams(&profile);
    profile.nPortIndex = kPortIndexInput;

    err = mOMX->getParameter(
            mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));

 if (err != OK) {
 return err;
 }

    profile.nChannels = numChannels;
    profile.nSampleRate = sampleRate;

    profile.eAACStreamFormat =
        isADTS
 ? OMX_AUDIO_AACStreamFormatMP4ADTS

             : OMX_AUDIO_AACStreamFormatMP4FF;

     OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
    InitOMXParams(&presentation);
     presentation.nMaxOutputChannels = maxOutputChannelCount;
     presentation.nDrcCut = drc.drcCut;
     presentation.nDrcBoost = drc.drcBoost;
    presentation.nHeavyCompression = drc.heavyCompression;
    presentation.nTargetReferenceLevel = drc.targetRefLevel;
    presentation.nEncodedTargetLevel = drc.encodedTargetLevel;
    presentation.nPCMLimiterEnable = pcmLimiterEnable;

 status_t res = mOMX->setParameter(mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
 if (res == OK) {
        mOMX->setParameter(mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAacPresentation,
 &presentation, sizeof(presentation));
 } else {
        ALOGW("did not set AudioAndroidAacPresentation due to error %d when setting AudioAac", res);
 }
 return res;
}


long ParseElementHeader(IMkvReader* pReader, long long& pos,
 long long stop, long long& id,
 long long& size) {
 if (stop >= 0 && pos >= stop)
 return E_FILE_FORMAT_INVALID;

 long len;

  id = ReadID(pReader, pos, len);

 if (id < 0)
 return E_FILE_FORMAT_INVALID;

  pos += len; // consume id

 if (stop >= 0 && pos >= stop)
 return E_FILE_FORMAT_INVALID;

  size = ReadUInt(pReader, pos, len);

 if (size < 0 || len < 1 || len > 8) {
 return E_FILE_FORMAT_INVALID;
 }

 const unsigned long long rollover_check =
 static_cast<unsigned long long>(pos) + len;
 if (rollover_check > LONG_LONG_MAX)
 return E_FILE_FORMAT_INVALID;

  pos += len; // consume length of size

  if (stop >= 0 && pos >= stop)
     return E_FILE_FORMAT_INVALID;

   return 0;  // success
}

libvpx in libwebm in mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, and 6.x before 2016-06-01 allows remote attackers to execute arbitrary code or cause a denial of service (memory corruption) via a crafted mkv file, aka internal bug 23167726.


long ParseElementHeader(IMkvReader* pReader, long long& pos,
 long long stop, long long& id,
 long long& size) {
 if (stop >= 0 && pos >= stop)
 return E_FILE_FORMAT_INVALID;

 long len;

  id = ReadID(pReader, pos, len);

 if (id < 0)
 return E_FILE_FORMAT_INVALID;

  pos += len; // consume id

 if (stop >= 0 && pos >= stop)
 return E_FILE_FORMAT_INVALID;

  size = ReadUInt(pReader, pos, len);

 if (size < 0 || len < 1 || len > 8) {
 return E_FILE_FORMAT_INVALID;
 }

 const unsigned long long rollover_check =
 static_cast<unsigned long long>(pos) + len;
 if (rollover_check > LONG_LONG_MAX)
 return E_FILE_FORMAT_INVALID;

  pos += len; // consume length of size

  if (stop >= 0 && pos > stop)
     return E_FILE_FORMAT_INVALID;

   return 0;  // success
}


void SoftAMR::onQueueFilled(OMX_U32 /* portIndex */) {
 List<BufferInfo *> &inQueue = getPortQueue(0);
 List<BufferInfo *> &outQueue = getPortQueue(1);

 if (mSignalledError || mOutputPortSettingsChange != NONE) {
 return;
 }

 while (!inQueue.empty() && !outQueue.empty()) {

         BufferInfo *inInfo = *inQueue.begin();
         OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;

         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
            inQueue.erase(inQueue.begin());
            inInfo->mOwnedByUs = false;
            notifyEmptyBufferDone(inHeader);

            outHeader->nFilledLen = 0;
            outHeader->nFlags = OMX_BUFFERFLAG_EOS;

            outQueue.erase(outQueue.begin());
            outInfo->mOwnedByUs = false;
            notifyFillBufferDone(outHeader);
 return;
 }

 if (inHeader->nOffset == 0) {
            mAnchorTimeUs = inHeader->nTimeStamp;
            mNumSamplesOutput = 0;
 }

 const uint8_t *inputPtr = inHeader->pBuffer + inHeader->nOffset;
 int32_t numBytesRead;

 if (mMode == MODE_NARROW) {
 if (outHeader->nAllocLen < kNumSamplesPerFrameNB * sizeof(int16_t)) {
                ALOGE("b/27662364: NB expected output buffer %zu bytes vs %u",
                       kNumSamplesPerFrameNB * sizeof(int16_t), outHeader->nAllocLen);
                android_errorWriteLog(0x534e4554, "27662364");
                notify(OMX_EventError, OMX_ErrorOverflow, 0, NULL);
                mSignalledError = true;

                 return;
             }

             numBytesRead =
                 AMRDecode(mState,
                   (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
 (UWord8 *)&inputPtr[1],
 reinterpret_cast<int16_t *>(outHeader->pBuffer),
                  MIME_IETF);

 if (numBytesRead == -1) {
                ALOGE("PV AMR decoder AMRDecode() call failed");

                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
                mSignalledError = true;

 return;
 }

 ++numBytesRead; // Include the frame type header byte.

 if (static_cast<size_t>(numBytesRead) > inHeader->nFilledLen) {

                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
                mSignalledError = true;

 return;
 }
 } else {
 if (outHeader->nAllocLen < kNumSamplesPerFrameWB * sizeof(int16_t)) {
                ALOGE("b/27662364: WB expected output buffer %zu bytes vs %u",
                       kNumSamplesPerFrameWB * sizeof(int16_t), outHeader->nAllocLen);
                android_errorWriteLog(0x534e4554, "27662364");
                notify(OMX_EventError, OMX_ErrorOverflow, 0, NULL);
                mSignalledError = true;
 return;
 }

 int16 mode = ((inputPtr[0] >> 3) & 0x0f);

 if (mode >= 10 && mode <= 13) {
                ALOGE("encountered illegal frame type %d in AMR WB content.",
                      mode);

                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
                mSignalledError = true;

 return;

             }

             size_t frameSize = getFrameSize(mode);
            CHECK_GE(inHeader->nFilledLen, frameSize);

             int16_t *outPtr = (int16_t *)outHeader->pBuffer;

 if (mode >= 9) {
                memset(outPtr, 0, kNumSamplesPerFrameWB * sizeof(int16_t));
 } else if (mode < 9) {
 int16 frameType;
                RX_State_wb rx_state;
                mime_unsorting(
 const_cast<uint8_t *>(&inputPtr[1]),
                        mInputSampleBuffer,
 &frameType, &mode, 1, &rx_state);

 int16_t numSamplesOutput;
                pvDecoder_AmrWb(
                        mode, mInputSampleBuffer,
                        outPtr,
 &numSamplesOutput,
                        mDecoderBuf, frameType, mDecoderCookie);

                CHECK_EQ((int)numSamplesOutput, (int)kNumSamplesPerFrameWB);

 for (int i = 0; i < kNumSamplesPerFrameWB; ++i) {
 /* Delete the 2 LSBs (14-bit output) */
                    outPtr[i] &= 0xfffC;
 }
 }

            numBytesRead = frameSize;
 }

        inHeader->nOffset += numBytesRead;
        inHeader->nFilledLen -= numBytesRead;

        outHeader->nFlags = 0;
        outHeader->nOffset = 0;

 if (mMode == MODE_NARROW) {
            outHeader->nFilledLen = kNumSamplesPerFrameNB * sizeof(int16_t);

            outHeader->nTimeStamp =
                mAnchorTimeUs
 + (mNumSamplesOutput * 1000000ll) / kSampleRateNB;

            mNumSamplesOutput += kNumSamplesPerFrameNB;
 } else {
            outHeader->nFilledLen = kNumSamplesPerFrameWB * sizeof(int16_t);

            outHeader->nTimeStamp =
                mAnchorTimeUs
 + (mNumSamplesOutput * 1000000ll) / kSampleRateWB;

            mNumSamplesOutput += kNumSamplesPerFrameWB;
 }

 if (inHeader->nFilledLen == 0) {
            inInfo->mOwnedByUs = false;
            inQueue.erase(inQueue.begin());
            inInfo = NULL;
            notifyEmptyBufferDone(inHeader);
            inHeader = NULL;
 }

        outInfo->mOwnedByUs = false;
        outQueue.erase(outQueue.begin());
        outInfo = NULL;
        notifyFillBufferDone(outHeader);
        outHeader = NULL;

 ++mInputBufferCount;
 }
}

codecs/amrnb/dec/SoftAMR.cpp in libstagefright in mediaserver in Android 4.x before 4.4.4, 5.0.x before 5.0.2, 5.1.x before 5.1.1, and 6.x before 2016-05-01 does not validate buffer sizes, which allows attackers to gain privileges via a crafted application, as demonstrated by obtaining Signature or SignatureOrSystem access, aka internal bugs 27662364 and 27843673.


void SoftAMR::onQueueFilled(OMX_U32 /* portIndex */) {
 List<BufferInfo *> &inQueue = getPortQueue(0);
 List<BufferInfo *> &outQueue = getPortQueue(1);

 if (mSignalledError || mOutputPortSettingsChange != NONE) {
 return;
 }

 while (!inQueue.empty() && !outQueue.empty()) {

         BufferInfo *inInfo = *inQueue.begin();
         OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;

        if (inHeader->nFilledLen == 0) {
            inInfo->mOwnedByUs = false;
            inQueue.erase(inQueue.begin());
            notifyEmptyBufferDone(inHeader);
            continue;
        }

         BufferInfo *outInfo = *outQueue.begin();
         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
            inQueue.erase(inQueue.begin());
            inInfo->mOwnedByUs = false;
            notifyEmptyBufferDone(inHeader);

            outHeader->nFilledLen = 0;
            outHeader->nFlags = OMX_BUFFERFLAG_EOS;

            outQueue.erase(outQueue.begin());
            outInfo->mOwnedByUs = false;
            notifyFillBufferDone(outHeader);
 return;
 }

 if (inHeader->nOffset == 0) {
            mAnchorTimeUs = inHeader->nTimeStamp;
            mNumSamplesOutput = 0;
 }

 const uint8_t *inputPtr = inHeader->pBuffer + inHeader->nOffset;
 int32_t numBytesRead;

 if (mMode == MODE_NARROW) {
 if (outHeader->nAllocLen < kNumSamplesPerFrameNB * sizeof(int16_t)) {
                ALOGE("b/27662364: NB expected output buffer %zu bytes vs %u",
                       kNumSamplesPerFrameNB * sizeof(int16_t), outHeader->nAllocLen);
                android_errorWriteLog(0x534e4554, "27662364");
                notify(OMX_EventError, OMX_ErrorOverflow, 0, NULL);
                mSignalledError = true;

                 return;
             }

            int16 mode = ((inputPtr[0] >> 3) & 0x0f);
            // for WMF since MIME_IETF is used when calling AMRDecode.
            size_t frameSize = WmfDecBytesPerFrame[mode] + 1;

            if (inHeader->nFilledLen < frameSize) {
                ALOGE("b/27662364: expected %zu bytes vs %u", frameSize, inHeader->nFilledLen);
                notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
                mSignalledError = true;
                return;
            }

             numBytesRead =
                 AMRDecode(mState,
                   (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
 (UWord8 *)&inputPtr[1],
 reinterpret_cast<int16_t *>(outHeader->pBuffer),
                  MIME_IETF);

 if (numBytesRead == -1) {
                ALOGE("PV AMR decoder AMRDecode() call failed");

                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
                mSignalledError = true;

 return;
 }

 ++numBytesRead; // Include the frame type header byte.

 if (static_cast<size_t>(numBytesRead) > inHeader->nFilledLen) {

                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
                mSignalledError = true;

 return;
 }
 } else {
 if (outHeader->nAllocLen < kNumSamplesPerFrameWB * sizeof(int16_t)) {
                ALOGE("b/27662364: WB expected output buffer %zu bytes vs %u",
                       kNumSamplesPerFrameWB * sizeof(int16_t), outHeader->nAllocLen);
                android_errorWriteLog(0x534e4554, "27662364");
                notify(OMX_EventError, OMX_ErrorOverflow, 0, NULL);
                mSignalledError = true;
 return;
 }

 int16 mode = ((inputPtr[0] >> 3) & 0x0f);

 if (mode >= 10 && mode <= 13) {
                ALOGE("encountered illegal frame type %d in AMR WB content.",
                      mode);

                notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
                mSignalledError = true;

 return;

             }

             size_t frameSize = getFrameSize(mode);
            if (inHeader->nFilledLen < frameSize) {
                ALOGE("b/27662364: expected %zu bytes vs %u", frameSize, inHeader->nFilledLen);
                notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
                mSignalledError = true;
                return;
            }

             int16_t *outPtr = (int16_t *)outHeader->pBuffer;

 if (mode >= 9) {
                memset(outPtr, 0, kNumSamplesPerFrameWB * sizeof(int16_t));
 } else if (mode < 9) {
 int16 frameType;
                RX_State_wb rx_state;
                mime_unsorting(
 const_cast<uint8_t *>(&inputPtr[1]),
                        mInputSampleBuffer,
 &frameType, &mode, 1, &rx_state);

 int16_t numSamplesOutput;
                pvDecoder_AmrWb(
                        mode, mInputSampleBuffer,
                        outPtr,
 &numSamplesOutput,
                        mDecoderBuf, frameType, mDecoderCookie);

                CHECK_EQ((int)numSamplesOutput, (int)kNumSamplesPerFrameWB);

 for (int i = 0; i < kNumSamplesPerFrameWB; ++i) {
 /* Delete the 2 LSBs (14-bit output) */
                    outPtr[i] &= 0xfffC;
 }
 }

            numBytesRead = frameSize;
 }

        inHeader->nOffset += numBytesRead;
        inHeader->nFilledLen -= numBytesRead;

        outHeader->nFlags = 0;
        outHeader->nOffset = 0;

 if (mMode == MODE_NARROW) {
            outHeader->nFilledLen = kNumSamplesPerFrameNB * sizeof(int16_t);

            outHeader->nTimeStamp =
                mAnchorTimeUs
 + (mNumSamplesOutput * 1000000ll) / kSampleRateNB;

            mNumSamplesOutput += kNumSamplesPerFrameNB;
 } else {
            outHeader->nFilledLen = kNumSamplesPerFrameWB * sizeof(int16_t);

            outHeader->nTimeStamp =
                mAnchorTimeUs
 + (mNumSamplesOutput * 1000000ll) / kSampleRateWB;

            mNumSamplesOutput += kNumSamplesPerFrameWB;
 }

 if (inHeader->nFilledLen == 0) {
            inInfo->mOwnedByUs = false;
            inQueue.erase(inQueue.begin());
            inInfo = NULL;
            notifyEmptyBufferDone(inHeader);
            inHeader = NULL;
 }

        outInfo->mOwnedByUs = false;
        outQueue.erase(outQueue.begin());
        outInfo = NULL;
        notifyFillBufferDone(outHeader);
        outHeader = NULL;

 ++mInputBufferCount;
 }
}


int equalizer_get_parameter(effect_context_t *context, effect_param_t *p,
 uint32_t *size)
{
 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context;
 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
 int32_t *param_tmp = (int32_t *)p->data;
 int32_t param = *param_tmp++;
 int32_t param2;
 char *name;
 void *value = p->data + voffset;
 int i;

    ALOGV("%s", __func__);

    p->status = 0;

 switch (param) {
 case EQ_PARAM_NUM_BANDS:
 case EQ_PARAM_CUR_PRESET:
 case EQ_PARAM_GET_NUM_OF_PRESETS:
 case EQ_PARAM_BAND_LEVEL:
 case EQ_PARAM_GET_BAND:
 if (p->vsize < sizeof(int16_t))
           p->status = -EINVAL;
        p->vsize = sizeof(int16_t);
 break;

 case EQ_PARAM_LEVEL_RANGE:
 if (p->vsize < 2 * sizeof(int16_t))
            p->status = -EINVAL;
        p->vsize = 2 * sizeof(int16_t);
 break;
 case EQ_PARAM_BAND_FREQ_RANGE:
 if (p->vsize < 2 * sizeof(int32_t))
            p->status = -EINVAL;
        p->vsize = 2 * sizeof(int32_t);
 break;

 case EQ_PARAM_CENTER_FREQ:
 if (p->vsize < sizeof(int32_t))
            p->status = -EINVAL;
        p->vsize = sizeof(int32_t);
 break;

 case EQ_PARAM_GET_PRESET_NAME:
 break;

 case EQ_PARAM_PROPERTIES:
 if (p->vsize < (2 + NUM_EQ_BANDS) * sizeof(uint16_t))
            p->status = -EINVAL;
        p->vsize = (2 + NUM_EQ_BANDS) * sizeof(uint16_t);
 break;

 default:
        p->status = -EINVAL;
 }

 *size = sizeof(effect_param_t) + voffset + p->vsize;

 if (p->status != 0)
 return 0;

 switch (param) {
 case EQ_PARAM_NUM_BANDS:
	ALOGV("%s: EQ_PARAM_NUM_BANDS", __func__);
 *(uint16_t *)value = (uint16_t)NUM_EQ_BANDS;
 break;

 case EQ_PARAM_LEVEL_RANGE:
	ALOGV("%s: EQ_PARAM_LEVEL_RANGE", __func__);
 *(int16_t *)value = -1500;
 *((int16_t *)value + 1) = 1500;
 break;

     case EQ_PARAM_BAND_LEVEL:
 	ALOGV("%s: EQ_PARAM_BAND_LEVEL", __func__);
         param2 = *param_tmp;
        if (param2 >= NUM_EQ_BANDS) {
             p->status = -EINVAL;
             break;
         }
         *(int16_t *)value = (int16_t)equalizer_get_band_level(eq_ctxt, param2);
 break;

     case EQ_PARAM_CENTER_FREQ:
 	ALOGV("%s: EQ_PARAM_CENTER_FREQ", __func__);
         param2 = *param_tmp;
        if (param2 >= NUM_EQ_BANDS) {
           p->status = -EINVAL;
             break;
         }
         *(int32_t *)value = equalizer_get_center_frequency(eq_ctxt, param2);
 break;

     case EQ_PARAM_BAND_FREQ_RANGE:
 	ALOGV("%s: EQ_PARAM_BAND_FREQ_RANGE", __func__);
         param2 = *param_tmp;
        if (param2 >= NUM_EQ_BANDS) {
             p->status = -EINVAL;
            break;
         }
        equalizer_get_band_freq_range(eq_ctxt, param2, (uint32_t *)value,
 ((uint32_t *)value + 1));
 break;

 case EQ_PARAM_GET_BAND:
	ALOGV("%s: EQ_PARAM_GET_BAND", __func__);
        param2 = *param_tmp;
 *(uint16_t *)value = (uint16_t)equalizer_get_band(eq_ctxt, param2);
 break;

 case EQ_PARAM_CUR_PRESET:
	ALOGV("%s: EQ_PARAM_CUR_PRESET", __func__);
 *(uint16_t *)value = (uint16_t)equalizer_get_preset(eq_ctxt);
 break;

 case EQ_PARAM_GET_NUM_OF_PRESETS:
	ALOGV("%s: EQ_PARAM_GET_NUM_OF_PRESETS", __func__);
 *(uint16_t *)value = (uint16_t)equalizer_get_num_presets(eq_ctxt);
 break;

 case EQ_PARAM_GET_PRESET_NAME:
	ALOGV("%s: EQ_PARAM_GET_PRESET_NAME", __func__);
        param2 = *param_tmp;
	ALOGV("param2: %d", param2);
 if (param2 >= equalizer_get_num_presets(eq_ctxt)) {
            p->status = -EINVAL;
 break;
 }
        name = (char *)value;
        strlcpy(name, equalizer_get_preset_name(eq_ctxt, param2), p->vsize - 1);
        name[p->vsize - 1] = 0;
        p->vsize = strlen(name) + 1;
 break;

 case EQ_PARAM_PROPERTIES: {
	ALOGV("%s: EQ_PARAM_PROPERTIES", __func__);
 int16_t *prop = (int16_t *)value;
        prop[0] = (int16_t)equalizer_get_preset(eq_ctxt);
        prop[1] = (int16_t)NUM_EQ_BANDS;
 for (i = 0; i < NUM_EQ_BANDS; i++) {
            prop[2 + i] = (int16_t)equalizer_get_band_level(eq_ctxt, i);
 }
 } break;

 default:
        p->status = -EINVAL;
 break;
 }

 return 0;
}

An information disclosure vulnerability in lvm/wrapper/Bundle/EffectBundle.cpp in libeffects in Audioserver could enable a local malicious application to access data outside of its permission levels. This issue is rated as Moderate because it could be used to access sensitive data without permission. Product: Android. Versions: 4.4.4, 5.0.2, 5.1.1, 6.0, 6.0.1, 7.0, 7.1. Android ID: A-32436341.


int equalizer_get_parameter(effect_context_t *context, effect_param_t *p,
 uint32_t *size)
{
 equalizer_context_t *eq_ctxt = (equalizer_context_t *)context;
 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
 int32_t *param_tmp = (int32_t *)p->data;
 int32_t param = *param_tmp++;
 int32_t param2;
 char *name;
 void *value = p->data + voffset;
 int i;

    ALOGV("%s", __func__);

    p->status = 0;

 switch (param) {
 case EQ_PARAM_NUM_BANDS:
 case EQ_PARAM_CUR_PRESET:
 case EQ_PARAM_GET_NUM_OF_PRESETS:
 case EQ_PARAM_BAND_LEVEL:
 case EQ_PARAM_GET_BAND:
 if (p->vsize < sizeof(int16_t))
           p->status = -EINVAL;
        p->vsize = sizeof(int16_t);
 break;

 case EQ_PARAM_LEVEL_RANGE:
 if (p->vsize < 2 * sizeof(int16_t))
            p->status = -EINVAL;
        p->vsize = 2 * sizeof(int16_t);
 break;
 case EQ_PARAM_BAND_FREQ_RANGE:
 if (p->vsize < 2 * sizeof(int32_t))
            p->status = -EINVAL;
        p->vsize = 2 * sizeof(int32_t);
 break;

 case EQ_PARAM_CENTER_FREQ:
 if (p->vsize < sizeof(int32_t))
            p->status = -EINVAL;
        p->vsize = sizeof(int32_t);
 break;

 case EQ_PARAM_GET_PRESET_NAME:
 break;

 case EQ_PARAM_PROPERTIES:
 if (p->vsize < (2 + NUM_EQ_BANDS) * sizeof(uint16_t))
            p->status = -EINVAL;
        p->vsize = (2 + NUM_EQ_BANDS) * sizeof(uint16_t);
 break;

 default:
        p->status = -EINVAL;
 }

 *size = sizeof(effect_param_t) + voffset + p->vsize;

 if (p->status != 0)
 return 0;

 switch (param) {
 case EQ_PARAM_NUM_BANDS:
	ALOGV("%s: EQ_PARAM_NUM_BANDS", __func__);
 *(uint16_t *)value = (uint16_t)NUM_EQ_BANDS;
 break;

 case EQ_PARAM_LEVEL_RANGE:
	ALOGV("%s: EQ_PARAM_LEVEL_RANGE", __func__);
 *(int16_t *)value = -1500;
 *((int16_t *)value + 1) = 1500;
 break;

     case EQ_PARAM_BAND_LEVEL:
 	ALOGV("%s: EQ_PARAM_BAND_LEVEL", __func__);
         param2 = *param_tmp;
        if (param2 < 0 || param2 >= NUM_EQ_BANDS) {
             p->status = -EINVAL;
            if (param2 < 0) {
                android_errorWriteLog(0x534e4554, "32438598");
                ALOGW("\tERROR EQ_PARAM_BAND_LEVEL band %d", param2);
            }
             break;
         }
         *(int16_t *)value = (int16_t)equalizer_get_band_level(eq_ctxt, param2);
 break;

     case EQ_PARAM_CENTER_FREQ:
 	ALOGV("%s: EQ_PARAM_CENTER_FREQ", __func__);
         param2 = *param_tmp;
        if (param2 < 0 || param2 >= NUM_EQ_BANDS) {
            p->status = -EINVAL;
            if (param2 < 0) {
                android_errorWriteLog(0x534e4554, "32436341");
                ALOGW("\tERROR EQ_PARAM_CENTER_FREQ band %d", param2);
            }
             break;
         }
         *(int32_t *)value = equalizer_get_center_frequency(eq_ctxt, param2);
 break;

     case EQ_PARAM_BAND_FREQ_RANGE:
 	ALOGV("%s: EQ_PARAM_BAND_FREQ_RANGE", __func__);
         param2 = *param_tmp;
        if (param2 < 0 || param2 >= NUM_EQ_BANDS) {
             p->status = -EINVAL;
            if (param2 < 0) {
                android_errorWriteLog(0x534e4554, "32247948");
                ALOGW("\tERROR EQ_PARAM_BAND_FREQ_RANGE band %d", param2);
            }
            break;
         }
        equalizer_get_band_freq_range(eq_ctxt, param2, (uint32_t *)value,
 ((uint32_t *)value + 1));
 break;

 case EQ_PARAM_GET_BAND:
	ALOGV("%s: EQ_PARAM_GET_BAND", __func__);
        param2 = *param_tmp;
 *(uint16_t *)value = (uint16_t)equalizer_get_band(eq_ctxt, param2);
 break;

 case EQ_PARAM_CUR_PRESET:
	ALOGV("%s: EQ_PARAM_CUR_PRESET", __func__);
 *(uint16_t *)value = (uint16_t)equalizer_get_preset(eq_ctxt);
 break;

 case EQ_PARAM_GET_NUM_OF_PRESETS:
	ALOGV("%s: EQ_PARAM_GET_NUM_OF_PRESETS", __func__);
 *(uint16_t *)value = (uint16_t)equalizer_get_num_presets(eq_ctxt);
 break;

 case EQ_PARAM_GET_PRESET_NAME:
	ALOGV("%s: EQ_PARAM_GET_PRESET_NAME", __func__);
        param2 = *param_tmp;
	ALOGV("param2: %d", param2);
 if (param2 >= equalizer_get_num_presets(eq_ctxt)) {
            p->status = -EINVAL;
 break;
 }
        name = (char *)value;
        strlcpy(name, equalizer_get_preset_name(eq_ctxt, param2), p->vsize - 1);
        name[p->vsize - 1] = 0;
        p->vsize = strlen(name) + 1;
 break;

 case EQ_PARAM_PROPERTIES: {
	ALOGV("%s: EQ_PARAM_PROPERTIES", __func__);
 int16_t *prop = (int16_t *)value;
        prop[0] = (int16_t)equalizer_get_preset(eq_ctxt);
        prop[1] = (int16_t)NUM_EQ_BANDS;
 for (i = 0; i < NUM_EQ_BANDS; i++) {
            prop[2 + i] = (int16_t)equalizer_get_band_level(eq_ctxt, i);
 }
 } break;

 default:
        p->status = -EINVAL;
 break;
 }

 return 0;
}


uint8_t rfc_parse_data(tRFC_MCB* p_mcb, MX_FRAME* p_frame, BT_HDR* p_buf) {
 uint8_t ead, eal, fcs;
 uint8_t* p_data = (uint8_t*)(p_buf + 1) + p_buf->offset;
 uint8_t* p_start = p_data;
 uint16_t len;

 if (p_buf->len < RFCOMM_CTRL_FRAME_LEN) {
    RFCOMM_TRACE_ERROR("Bad Length1: %d", p_buf->len);
 return (RFC_EVENT_BAD_FRAME);
 }

  RFCOMM_PARSE_CTRL_FIELD(ead, p_frame->cr, p_frame->dlci, p_data);
 if (!ead) {
    RFCOMM_TRACE_ERROR("Bad Address(EA must be 1)");
 return (RFC_EVENT_BAD_FRAME);
 }
  RFCOMM_PARSE_TYPE_FIELD(p_frame->type, p_frame->pf, p_data);

   eal = *(p_data)&RFCOMM_EA;
   len = *(p_data)++ >> RFCOMM_SHIFT_LENGTH1;
  if (eal == 0 && p_buf->len < RFCOMM_CTRL_FRAME_LEN) {
     len += (*(p_data)++ << RFCOMM_SHIFT_LENGTH2);
   } else if (eal == 0) {
     RFCOMM_TRACE_ERROR("Bad Length when EAL = 0: %d", p_buf->len);
    android_errorWriteLog(0x534e4554, "78288018");
 return RFC_EVENT_BAD_FRAME;
 }

  p_buf->len -= (3 + !ead + !eal + 1); /* Additional 1 for FCS */
  p_buf->offset += (3 + !ead + !eal);

 /* handle credit if credit based flow control */
 if ((p_mcb->flow == PORT_FC_CREDIT) && (p_frame->type == RFCOMM_UIH) &&
 (p_frame->dlci != RFCOMM_MX_DLCI) && (p_frame->pf == 1)) {
    p_frame->credit = *p_data++;
    p_buf->len--;
    p_buf->offset++;
 } else
    p_frame->credit = 0;

 if (p_buf->len != len) {
    RFCOMM_TRACE_ERROR("Bad Length2 %d %d", p_buf->len, len);
 return (RFC_EVENT_BAD_FRAME);
 }

  fcs = *(p_data + len);

 /* All control frames that we are sending are sent with P=1, expect */
 /* reply with F=1 */
 /* According to TS 07.10 spec ivalid frames are discarded without */
 /* notification to the sender */
 switch (p_frame->type) {
 case RFCOMM_SABME:
 if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr) ||
 !p_frame->pf || len || !RFCOMM_VALID_DLCI(p_frame->dlci) ||
 !rfc_check_fcs(RFCOMM_CTRL_FRAME_LEN, p_start, fcs)) {
        RFCOMM_TRACE_ERROR("Bad SABME");
 return (RFC_EVENT_BAD_FRAME);
 } else
 return (RFC_EVENT_SABME);

 case RFCOMM_UA:
 if (RFCOMM_FRAME_IS_CMD(p_mcb->is_initiator, p_frame->cr) ||
 !p_frame->pf || len || !RFCOMM_VALID_DLCI(p_frame->dlci) ||
 !rfc_check_fcs(RFCOMM_CTRL_FRAME_LEN, p_start, fcs)) {
        RFCOMM_TRACE_ERROR("Bad UA");
 return (RFC_EVENT_BAD_FRAME);
 } else
 return (RFC_EVENT_UA);

 case RFCOMM_DM:
 if (RFCOMM_FRAME_IS_CMD(p_mcb->is_initiator, p_frame->cr) || len ||
 !RFCOMM_VALID_DLCI(p_frame->dlci) ||
 !rfc_check_fcs(RFCOMM_CTRL_FRAME_LEN, p_start, fcs)) {
        RFCOMM_TRACE_ERROR("Bad DM");
 return (RFC_EVENT_BAD_FRAME);
 } else
 return (RFC_EVENT_DM);

 case RFCOMM_DISC:
 if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr) ||
 !p_frame->pf || len || !RFCOMM_VALID_DLCI(p_frame->dlci) ||
 !rfc_check_fcs(RFCOMM_CTRL_FRAME_LEN, p_start, fcs)) {
        RFCOMM_TRACE_ERROR("Bad DISC");
 return (RFC_EVENT_BAD_FRAME);
 } else
 return (RFC_EVENT_DISC);

 case RFCOMM_UIH:
 if (!RFCOMM_VALID_DLCI(p_frame->dlci)) {
        RFCOMM_TRACE_ERROR("Bad UIH - invalid DLCI");
 return (RFC_EVENT_BAD_FRAME);
 } else if (!rfc_check_fcs(2, p_start, fcs)) {
        RFCOMM_TRACE_ERROR("Bad UIH - FCS");
 return (RFC_EVENT_BAD_FRAME);
 } else if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr)) {
 /* we assume that this is ok to allow bad implementations to work */
        RFCOMM_TRACE_ERROR("Bad UIH - response");
 return (RFC_EVENT_UIH);
 } else
 return (RFC_EVENT_UIH);
 }

 return (RFC_EVENT_BAD_FRAME);
}

In rfc_process_mx_message of rfc_ts_frames.cc, there is a possible out of bounds read due to a missing bounds check. This could lead to remote information disclosure with no additional execution privileges needed. User interaction is not needed for exploitation. Product: Android Versions: Android-7.0 Android-7.1.1 Android-7.1.2 Android-8.0 Android-8.1 Android-9.0 Android ID: A-80432928


uint8_t rfc_parse_data(tRFC_MCB* p_mcb, MX_FRAME* p_frame, BT_HDR* p_buf) {
 uint8_t ead, eal, fcs;
 uint8_t* p_data = (uint8_t*)(p_buf + 1) + p_buf->offset;
 uint8_t* p_start = p_data;
 uint16_t len;

 if (p_buf->len < RFCOMM_CTRL_FRAME_LEN) {
    RFCOMM_TRACE_ERROR("Bad Length1: %d", p_buf->len);
 return (RFC_EVENT_BAD_FRAME);
 }

  RFCOMM_PARSE_CTRL_FIELD(ead, p_frame->cr, p_frame->dlci, p_data);
 if (!ead) {
    RFCOMM_TRACE_ERROR("Bad Address(EA must be 1)");
 return (RFC_EVENT_BAD_FRAME);
 }
  RFCOMM_PARSE_TYPE_FIELD(p_frame->type, p_frame->pf, p_data);

   eal = *(p_data)&RFCOMM_EA;
   len = *(p_data)++ >> RFCOMM_SHIFT_LENGTH1;
  if (eal == 0 && p_buf->len > RFCOMM_CTRL_FRAME_LEN) {
     len += (*(p_data)++ << RFCOMM_SHIFT_LENGTH2);
   } else if (eal == 0) {
     RFCOMM_TRACE_ERROR("Bad Length when EAL = 0: %d", p_buf->len);
    android_errorWriteLog(0x534e4554, "78288018");
 return RFC_EVENT_BAD_FRAME;
 }

  p_buf->len -= (3 + !ead + !eal + 1); /* Additional 1 for FCS */
  p_buf->offset += (3 + !ead + !eal);

 /* handle credit if credit based flow control */
 if ((p_mcb->flow == PORT_FC_CREDIT) && (p_frame->type == RFCOMM_UIH) &&
 (p_frame->dlci != RFCOMM_MX_DLCI) && (p_frame->pf == 1)) {
    p_frame->credit = *p_data++;
    p_buf->len--;
    p_buf->offset++;
 } else
    p_frame->credit = 0;

 if (p_buf->len != len) {
    RFCOMM_TRACE_ERROR("Bad Length2 %d %d", p_buf->len, len);
 return (RFC_EVENT_BAD_FRAME);
 }

  fcs = *(p_data + len);

 /* All control frames that we are sending are sent with P=1, expect */
 /* reply with F=1 */
 /* According to TS 07.10 spec ivalid frames are discarded without */
 /* notification to the sender */
 switch (p_frame->type) {
 case RFCOMM_SABME:
 if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr) ||
 !p_frame->pf || len || !RFCOMM_VALID_DLCI(p_frame->dlci) ||
 !rfc_check_fcs(RFCOMM_CTRL_FRAME_LEN, p_start, fcs)) {
        RFCOMM_TRACE_ERROR("Bad SABME");
 return (RFC_EVENT_BAD_FRAME);
 } else
 return (RFC_EVENT_SABME);

 case RFCOMM_UA:
 if (RFCOMM_FRAME_IS_CMD(p_mcb->is_initiator, p_frame->cr) ||
 !p_frame->pf || len || !RFCOMM_VALID_DLCI(p_frame->dlci) ||
 !rfc_check_fcs(RFCOMM_CTRL_FRAME_LEN, p_start, fcs)) {
        RFCOMM_TRACE_ERROR("Bad UA");
 return (RFC_EVENT_BAD_FRAME);
 } else
 return (RFC_EVENT_UA);

 case RFCOMM_DM:
 if (RFCOMM_FRAME_IS_CMD(p_mcb->is_initiator, p_frame->cr) || len ||
 !RFCOMM_VALID_DLCI(p_frame->dlci) ||
 !rfc_check_fcs(RFCOMM_CTRL_FRAME_LEN, p_start, fcs)) {
        RFCOMM_TRACE_ERROR("Bad DM");
 return (RFC_EVENT_BAD_FRAME);
 } else
 return (RFC_EVENT_DM);

 case RFCOMM_DISC:
 if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr) ||
 !p_frame->pf || len || !RFCOMM_VALID_DLCI(p_frame->dlci) ||
 !rfc_check_fcs(RFCOMM_CTRL_FRAME_LEN, p_start, fcs)) {
        RFCOMM_TRACE_ERROR("Bad DISC");
 return (RFC_EVENT_BAD_FRAME);
 } else
 return (RFC_EVENT_DISC);

 case RFCOMM_UIH:
 if (!RFCOMM_VALID_DLCI(p_frame->dlci)) {
        RFCOMM_TRACE_ERROR("Bad UIH - invalid DLCI");
 return (RFC_EVENT_BAD_FRAME);
 } else if (!rfc_check_fcs(2, p_start, fcs)) {
        RFCOMM_TRACE_ERROR("Bad UIH - FCS");
 return (RFC_EVENT_BAD_FRAME);
 } else if (RFCOMM_FRAME_IS_RSP(p_mcb->is_initiator, p_frame->cr)) {
 /* we assume that this is ok to allow bad implementations to work */
        RFCOMM_TRACE_ERROR("Bad UIH - response");
 return (RFC_EVENT_UIH);
 } else
 return (RFC_EVENT_UIH);
 }

 return (RFC_EVENT_BAD_FRAME);
}


create_surface_from_thumbnail_data (guchar *data,
				    gint    width,
				    gint    height,
 				    gint    rowstride)
 {
   guchar *cairo_pixels;
   cairo_surface_t *surface;
  static cairo_user_data_key_t key;
   int j;

  cairo_pixels = (guchar *)g_malloc (4 * width * height);
  surface = cairo_image_surface_create_for_data ((unsigned char *)cairo_pixels,
						 CAIRO_FORMAT_RGB24,
						 width, height, 4 * width);
  cairo_surface_set_user_data (surface, &key,
			       cairo_pixels, (cairo_destroy_func_t)g_free);

   for (j = height; j; j--) {
     guchar *p = data;
     guchar *q = cairo_pixels;
     guchar *end = p + 3 * width;
     while (p < end) {
 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
       q[0] = p[2];
       q[1] = p[1];
       q[2] = p[0];
#else
       q[1] = p[0];
       q[2] = p[1];
       q[3] = p[2];
#endif
      p += 3;
      q += 4;
     }

     data += rowstride;
    cairo_pixels += 4 * width;
   }

   return surface;
}

Integer overflow in the create_surface_from_thumbnail_data function in glib/poppler-page.cc in Poppler 0.x allows remote attackers to cause a denial of service (memory corruption) or possibly execute arbitrary code via a crafted PDF document that triggers a heap-based buffer overflow.  NOTE: some of these details are obtained from third party information.


create_surface_from_thumbnail_data (guchar *data,
				    gint    width,
				    gint    height,
 				    gint    rowstride)
 {
   guchar *cairo_pixels;
  gint cairo_stride;
   cairo_surface_t *surface;
   int j;

  surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
  if (cairo_surface_status (surface))
    return NULL;

  cairo_pixels = cairo_image_surface_get_data (surface);
  cairo_stride = cairo_image_surface_get_stride (surface);

   for (j = height; j; j--) {
     guchar *p = data;
     guchar *q = cairo_pixels;
     guchar *end = p + 3 * width;

     while (p < end) {
 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
       q[0] = p[2];
       q[1] = p[1];
       q[2] = p[0];
#else
       q[1] = p[0];
       q[2] = p[1];
       q[3] = p[2];
#endif
      p += 3;
      q += 4;
     }

     data += rowstride;
    cairo_pixels += cairo_stride;
   }

   return surface;
}


 DynamicMetadataProvider::DynamicMetadataProvider(const DOMElement* e)
    : AbstractMetadataProvider(e),
       m_validate(XMLHelper::getAttrBool(e, false, validate)),
         m_id(XMLHelper::getAttrString(e, "Dynamic", id)),
         m_lock(RWLock::create()),
        m_refreshDelayFactor(0.75),
        m_minCacheDuration(XMLHelper::getAttrInt(e, 600, minCacheDuration)),
        m_maxCacheDuration(XMLHelper::getAttrInt(e, 28800, maxCacheDuration)),
        m_shutdown(false),
        m_cleanupInterval(XMLHelper::getAttrInt(e, 1800, cleanupInterval)),
        m_cleanupTimeout(XMLHelper::getAttrInt(e, 1800, cleanupTimeout)),
         m_cleanup_wait(nullptr), m_cleanup_thread(nullptr)
 {
     if (m_minCacheDuration > m_maxCacheDuration) {
        Category::getInstance(SAML_LOGCAT ".MetadataProvider.Dynamic").error(
             "minCacheDuration setting exceeds maxCacheDuration setting, lowering to match it"
             );
         m_minCacheDuration = m_maxCacheDuration;
    }

    const XMLCh* delay = e ? e->getAttributeNS(nullptr, refreshDelayFactor) : nullptr;
    if (delay && *delay) {
        auto_ptr_char temp(delay);
        m_refreshDelayFactor = atof(temp.get());
        if (m_refreshDelayFactor <= 0.0 || m_refreshDelayFactor >= 1.0) {
            Category::getInstance(SAML_LOGCAT ".MetadataProvider.Dynamic").error(
                "invalid refreshDelayFactor setting, using default"
                );
            m_refreshDelayFactor = 0.75;
        }
    }

    if (m_cleanupInterval > 0) {
        if (m_cleanupTimeout < 0)
            m_cleanupTimeout = 0;
        m_cleanup_wait = CondWait::create();
        m_cleanup_thread = Thread::create(&cleanup_fn, this);
    }
}

The DynamicMetadataProvider class in saml/saml2/metadata/impl/DynamicMetadataProvider.cpp in OpenSAML-C in OpenSAML before 2.6.1 fails to properly configure itself with the MetadataFilter plugins and does not perform critical security checks such as signature verification, enforcement of validity periods, and other checks specific to deployments, aka CPPOST-105.


 DynamicMetadataProvider::DynamicMetadataProvider(const DOMElement* e)
    : AbstractMetadataProvider(e), MetadataProvider(e),
       m_validate(XMLHelper::getAttrBool(e, false, validate)),
         m_id(XMLHelper::getAttrString(e, "Dynamic", id)),
         m_lock(RWLock::create()),
        m_refreshDelayFactor(0.75),
        m_minCacheDuration(XMLHelper::getAttrInt(e, 600, minCacheDuration)),
        m_maxCacheDuration(XMLHelper::getAttrInt(e, 28800, maxCacheDuration)),
        m_shutdown(false),
        m_cleanupInterval(XMLHelper::getAttrInt(e, 1800, cleanupInterval)),
        m_cleanupTimeout(XMLHelper::getAttrInt(e, 1800, cleanupTimeout)),
         m_cleanup_wait(nullptr), m_cleanup_thread(nullptr)
 {
     if (m_minCacheDuration > m_maxCacheDuration) {
        Category::getInstance(SAML_LOGCAT ".Metadata.Dynamic").error(
             "minCacheDuration setting exceeds maxCacheDuration setting, lowering to match it"
             );
         m_minCacheDuration = m_maxCacheDuration;
    }

    const XMLCh* delay = e ? e->getAttributeNS(nullptr, refreshDelayFactor) : nullptr;
    if (delay && *delay) {
        auto_ptr_char temp(delay);
        m_refreshDelayFactor = atof(temp.get());
        if (m_refreshDelayFactor <= 0.0 || m_refreshDelayFactor >= 1.0) {
            Category::getInstance(SAML_LOGCAT ".MetadataProvider.Dynamic").error(
                "invalid refreshDelayFactor setting, using default"
                );
            m_refreshDelayFactor = 0.75;
        }
    }

    if (m_cleanupInterval > 0) {
        if (m_cleanupTimeout < 0)
            m_cleanupTimeout = 0;
        m_cleanup_wait = CondWait::create();
        m_cleanup_thread = Thread::create(&cleanup_fn, this);
    }
}


CVE-2015-5330: ldb_dn_escape_value: use known string length, not strlen()

ldb_dn_escape_internal() reports the number of bytes it copied, so
lets use that number, rather than using strlen() and hoping a zero got
in the right place.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=11599

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Pair-programmed-with: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>

 char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value)
 {
        char *dst;
        if (!value.length)
                return NULL;

	/* allocate destination string, it will be at most 3 times the source */
	dst = talloc_array(mem_ctx, char, value.length * 3 + 1);
	if ( ! dst) {
		talloc_free(dst);
                return NULL;
        }

       ldb_dn_escape_internal(dst, (const char *)value.data, value.length);
       dst = talloc_realloc(mem_ctx, dst, char, strlen(dst) + 1);

        return dst;
 }

ldb before 1.1.24, as used in the AD LDAP server in Samba 4.x before 4.1.22, 4.2.x before 4.2.7, and 4.3.x before 4.3.3, mishandles string lengths, which allows remote attackers to obtain sensitive information from daemon heap memory by sending crafted packets and then reading (1) an error message or (2) a database value.


 char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value)
 {
        char *dst;
       size_t len;
        if (!value.length)
                return NULL;

	/* allocate destination string, it will be at most 3 times the source */
	dst = talloc_array(mem_ctx, char, value.length * 3 + 1);
	if ( ! dst) {
		talloc_free(dst);
                return NULL;
        }

       len = ldb_dn_escape_internal(dst, (const char *)value.data, value.length);

       dst = talloc_realloc(mem_ctx, dst, char, len + 1);
       if ( ! dst) {
               talloc_free(dst);
               return NULL;
       }
       dst[len] = '\0';
        return dst;
 }


CVE-2015-5296: libcli/smb: make sure we require signing when we demand encryption on a session

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11536

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>

uint8_t smb2cli_session_security_mode(struct smbXcli_session *session)
{
	struct smbXcli_conn *conn = session->conn;
	uint8_t security_mode = 0;

	if (conn == NULL) {
		return security_mode;
	}

	security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
        if (conn->mandatory_signing) {
                security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
        }

        return security_mode;
 }

Samba 3.x and 4.x before 4.1.22, 4.2.x before 4.2.7, and 4.3.x before 4.3.3 supports connections that are encrypted but unsigned, which allows man-in-the-middle attackers to conduct encrypted-to-unencrypted downgrade attacks by modifying the client-server data stream, related to clidfs.c, libsmb_server.c, and smbXcli_base.c.


uint8_t smb2cli_session_security_mode(struct smbXcli_session *session)
{
	struct smbXcli_conn *conn = session->conn;
	uint8_t security_mode = 0;

	if (conn == NULL) {
		return security_mode;
	}

	security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED;
        if (conn->mandatory_signing) {
                security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
        }
       if (session->smb2->should_sign) {
               security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED;
       }

        return security_mode;
 }


CVE-2015-5296: s3:libsmb: force signing when requiring encryption in SMBC_server_internal()

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11536

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>

SMBC_server_internal(TALLOC_CTX *ctx,
            SMBCCTX *context,
            bool connect_if_not_found,
            const char *server,
            uint16_t port,
            const char *share,
            char **pp_workgroup,
            char **pp_username,
            char **pp_password,
	    bool *in_cache)
{
	SMBCSRV *srv=NULL;
	char *workgroup = NULL;
	struct cli_state *c = NULL;
	const char *server_n = server;
        int is_ipc = (share != NULL && strcmp(share, "IPC$") == 0);
	uint32_t fs_attrs = 0;
        const char *username_used;
 	NTSTATUS status;
        char *newserver, *newshare;
        int flags = 0;
        struct smbXcli_tcon *tcon = NULL;

        ZERO_STRUCT(c);
        *in_cache = false;
	if (server[0] == 0) {
		errno = EPERM;
		return NULL;
	}

        /* Look for a cached connection */
        srv = SMBC_find_server(ctx, context, server, share,
                               pp_workgroup, pp_username, pp_password);

        /*
         * If we found a connection and we're only allowed one share per
         * server...
         */
        if (srv &&
	    share != NULL && *share != '\0' &&
            smbc_getOptionOneSharePerServer(context)) {

                /*
                 * ... then if there's no current connection to the share,
                 * connect to it.  SMBC_find_server(), or rather the function
                 * pointed to by context->get_cached_srv_fn which
                 * was called by SMBC_find_server(), will have issued a tree
                 * disconnect if the requested share is not the same as the
                 * one that was already connected.
                 */

		/*
		 * Use srv->cli->desthost and srv->cli->share instead of
		 * server and share below to connect to the actual share,
		 * i.e., a normal share or a referred share from
		 * 'msdfs proxy' share.
		 */
                if (!cli_state_has_tcon(srv->cli)) {
                        /* Ensure we have accurate auth info */
			SMBC_call_auth_fn(ctx, context,
					  smbXcli_conn_remote_name(srv->cli->conn),
					  srv->cli->share,
                                          pp_workgroup,
                                          pp_username,
                                          pp_password);

			if (!*pp_workgroup || !*pp_username || !*pp_password) {
				errno = ENOMEM;
				cli_shutdown(srv->cli);
				srv->cli = NULL;
				smbc_getFunctionRemoveCachedServer(context)(context,
                                                                            srv);
				return NULL;
			}

			/*
			 * We don't need to renegotiate encryption
			 * here as the encryption context is not per
			 * tid.
			 */

			status = cli_tree_connect(srv->cli,
						  srv->cli->share,
						  "?????",
						  *pp_password,
						  strlen(*pp_password)+1);
			if (!NT_STATUS_IS_OK(status)) {
                                errno = map_errno_from_nt_status(status);
                                cli_shutdown(srv->cli);
				srv->cli = NULL;
                                smbc_getFunctionRemoveCachedServer(context)(context,
                                                                            srv);
                                srv = NULL;
                        }

                        /* Determine if this share supports case sensitivity */
                        if (is_ipc) {
                                DEBUG(4,
                                      ("IPC$ so ignore case sensitivity\n"));
                                status = NT_STATUS_OK;
                        } else {
                                status = cli_get_fs_attr_info(c, &fs_attrs);
                        }

                        if (!NT_STATUS_IS_OK(status)) {
                                DEBUG(4, ("Could not retrieve "
                                          "case sensitivity flag: %s.\n",
                                          nt_errstr(status)));

                                /*
                                 * We can't determine the case sensitivity of
                                 * the share. We have no choice but to use the
                                 * user-specified case sensitivity setting.
                                 */
                                if (smbc_getOptionCaseSensitive(context)) {
                                        cli_set_case_sensitive(c, True);
                                } else {
                                        cli_set_case_sensitive(c, False);
                                }
                        } else if (!is_ipc) {
                                DEBUG(4,
                                      ("Case sensitive: %s\n",
                                       (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                                        ? "True"
                                        : "False")));
                                cli_set_case_sensitive(
                                        c,
                                        (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                                         ? True
                                         : False));
                        }

                        /*
                         * Regenerate the dev value since it's based on both
                         * server and share
                         */
                        if (srv) {
				const char *remote_name =
					smbXcli_conn_remote_name(srv->cli->conn);

				srv->dev = (dev_t)(str_checksum(remote_name) ^
                                                   str_checksum(srv->cli->share));
                        }
                }
        }

        /* If we have a connection... */
        if (srv) {

                /* ... then we're done here.  Give 'em what they came for. */
		*in_cache = true;
                goto done;
        }

        /* If we're not asked to connect when a connection doesn't exist... */
        if (! connect_if_not_found) {
                /* ... then we're done here. */
                return NULL;
        }

	if (!*pp_workgroup || !*pp_username || !*pp_password) {
		errno = ENOMEM;
		return NULL;
	}

	DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server));

	DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));

	status = NT_STATUS_UNSUCCESSFUL;

	if (smbc_getOptionUseKerberos(context)) {
		flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
	}

	if (smbc_getOptionFallbackAfterKerberos(context)) {
		flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
	}

	if (smbc_getOptionUseCCache(context)) {
		flags |= CLI_FULL_CONNECTION_USE_CCACHE;
	}

	if (smbc_getOptionUseNTHash(context)) {
		flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
                flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
        }

        if (port == 0) {
                if (share == NULL || *share == '\0' || is_ipc) {
                        /*
		}
                         */
                        status = cli_connect_nb(server_n, NULL, NBT_SMB_PORT, 0x20,
                                        smbc_getNetbiosName(context),
                                       SMB_SIGNING_DEFAULT, flags, &c);
                }
        }


SMBC_server_internal(TALLOC_CTX *ctx,
            SMBCCTX *context,
            bool connect_if_not_found,
            const char *server,
            uint16_t port,
            const char *share,
            char **pp_workgroup,
            char **pp_username,
            char **pp_password,
	    bool *in_cache)
{
	SMBCSRV *srv=NULL;
	char *workgroup = NULL;
	struct cli_state *c = NULL;
	const char *server_n = server;
        int is_ipc = (share != NULL && strcmp(share, "IPC$") == 0);
	uint32_t fs_attrs = 0;
        const char *username_used;
 	NTSTATUS status;
        char *newserver, *newshare;
        int flags = 0;
        struct smbXcli_tcon *tcon = NULL;
       int signing_state = SMB_SIGNING_DEFAULT;

        ZERO_STRUCT(c);
        *in_cache = false;
	if (server[0] == 0) {
		errno = EPERM;
		return NULL;
	}

        /* Look for a cached connection */
        srv = SMBC_find_server(ctx, context, server, share,
                               pp_workgroup, pp_username, pp_password);

        /*
         * If we found a connection and we're only allowed one share per
         * server...
         */
        if (srv &&
	    share != NULL && *share != '\0' &&
            smbc_getOptionOneSharePerServer(context)) {

                /*
                 * ... then if there's no current connection to the share,
                 * connect to it.  SMBC_find_server(), or rather the function
                 * pointed to by context->get_cached_srv_fn which
                 * was called by SMBC_find_server(), will have issued a tree
                 * disconnect if the requested share is not the same as the
                 * one that was already connected.
                 */

		/*
		 * Use srv->cli->desthost and srv->cli->share instead of
		 * server and share below to connect to the actual share,
		 * i.e., a normal share or a referred share from
		 * 'msdfs proxy' share.
		 */
                if (!cli_state_has_tcon(srv->cli)) {
                        /* Ensure we have accurate auth info */
			SMBC_call_auth_fn(ctx, context,
					  smbXcli_conn_remote_name(srv->cli->conn),
					  srv->cli->share,
                                          pp_workgroup,
                                          pp_username,
                                          pp_password);

			if (!*pp_workgroup || !*pp_username || !*pp_password) {
				errno = ENOMEM;
				cli_shutdown(srv->cli);
				srv->cli = NULL;
				smbc_getFunctionRemoveCachedServer(context)(context,
                                                                            srv);
				return NULL;
			}

			/*
			 * We don't need to renegotiate encryption
			 * here as the encryption context is not per
			 * tid.
			 */

			status = cli_tree_connect(srv->cli,
						  srv->cli->share,
						  "?????",
						  *pp_password,
						  strlen(*pp_password)+1);
			if (!NT_STATUS_IS_OK(status)) {
                                errno = map_errno_from_nt_status(status);
                                cli_shutdown(srv->cli);
				srv->cli = NULL;
                                smbc_getFunctionRemoveCachedServer(context)(context,
                                                                            srv);
                                srv = NULL;
                        }

                        /* Determine if this share supports case sensitivity */
                        if (is_ipc) {
                                DEBUG(4,
                                      ("IPC$ so ignore case sensitivity\n"));
                                status = NT_STATUS_OK;
                        } else {
                                status = cli_get_fs_attr_info(c, &fs_attrs);
                        }

                        if (!NT_STATUS_IS_OK(status)) {
                                DEBUG(4, ("Could not retrieve "
                                          "case sensitivity flag: %s.\n",
                                          nt_errstr(status)));

                                /*
                                 * We can't determine the case sensitivity of
                                 * the share. We have no choice but to use the
                                 * user-specified case sensitivity setting.
                                 */
                                if (smbc_getOptionCaseSensitive(context)) {
                                        cli_set_case_sensitive(c, True);
                                } else {
                                        cli_set_case_sensitive(c, False);
                                }
                        } else if (!is_ipc) {
                                DEBUG(4,
                                      ("Case sensitive: %s\n",
                                       (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                                        ? "True"
                                        : "False")));
                                cli_set_case_sensitive(
                                        c,
                                        (fs_attrs & FILE_CASE_SENSITIVE_SEARCH
                                         ? True
                                         : False));
                        }

                        /*
                         * Regenerate the dev value since it's based on both
                         * server and share
                         */
                        if (srv) {
				const char *remote_name =
					smbXcli_conn_remote_name(srv->cli->conn);

				srv->dev = (dev_t)(str_checksum(remote_name) ^
                                                   str_checksum(srv->cli->share));
                        }
                }
        }

        /* If we have a connection... */
        if (srv) {

                /* ... then we're done here.  Give 'em what they came for. */
		*in_cache = true;
                goto done;
        }

        /* If we're not asked to connect when a connection doesn't exist... */
        if (! connect_if_not_found) {
                /* ... then we're done here. */
                return NULL;
        }

	if (!*pp_workgroup || !*pp_username || !*pp_password) {
		errno = ENOMEM;
		return NULL;
	}

	DEBUG(4,("SMBC_server: server_n=[%s] server=[%s]\n", server_n, server));

	DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));

	status = NT_STATUS_UNSUCCESSFUL;

	if (smbc_getOptionUseKerberos(context)) {
		flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
	}

	if (smbc_getOptionFallbackAfterKerberos(context)) {
		flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
	}

	if (smbc_getOptionUseCCache(context)) {
		flags |= CLI_FULL_CONNECTION_USE_CCACHE;
	}

	if (smbc_getOptionUseNTHash(context)) {
		flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
                flags |= CLI_FULL_CONNECTION_USE_NT_HASH;
        }

       if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) {
               signing_state = SMB_SIGNING_REQUIRED;
       }

        if (port == 0) {
                if (share == NULL || *share == '\0' || is_ipc) {
                        /*
		}
                         */
                        status = cli_connect_nb(server_n, NULL, NBT_SMB_PORT, 0x20,
                                        smbc_getNetbiosName(context),
                                       signing_state, flags, &c);
                }
        }


do_ed_script (char const *inname, char const *outname,
	      bool *outname_needs_removal, FILE *ofp)
{
    static char const editor_program[] = EDITOR_PROGRAM;

    file_offset beginning_of_this_line;
    size_t chars_read;
    FILE *tmpfp = 0;
    char const *tmpname;
    int tmpfd;
    pid_t pid;

    if (! dry_run && ! skip_rest_of_patch)
      {
	/* Write ed script to a temporary file.  This causes ed to abort on
	   invalid commands such as when line numbers or ranges exceed the
	   number of available lines.  When ed reads from a pipe, it rejects
	   invalid commands and treats the next line as a new command, which
	   can lead to arbitrary command execution.  */

	tmpfd = make_tempfile (&tmpname, 'e', NULL, O_RDWR | O_BINARY, 0);
	if (tmpfd == -1)
	  pfatal ("Can't create temporary file %s", quotearg (tmpname));
	tmpfp = fdopen (tmpfd, "w+b");
	if (! tmpfp)
	  pfatal ("Can't open stream for file %s", quotearg (tmpname));
      }

    for (;;) {
	char ed_command_letter;
	beginning_of_this_line = file_tell (pfp);
	chars_read = get_line ();
	if (! chars_read) {
	    next_intuit_at(beginning_of_this_line,p_input_line);
	    break;
	}
	ed_command_letter = get_ed_command_letter (buf);
	if (ed_command_letter) {
	    if (tmpfp)
		if (! fwrite (buf, sizeof *buf, chars_read, tmpfp))
		    write_fatal ();
	    if (ed_command_letter != 'd' && ed_command_letter != 's') {
	        p_pass_comments_through = true;
		while ((chars_read = get_line ()) != 0) {
		    if (tmpfp)
			if (! fwrite (buf, sizeof *buf, chars_read, tmpfp))
			    write_fatal ();
		    if (chars_read == 2  &&  strEQ (buf, ".\n"))
			break;
		}
		p_pass_comments_through = false;
	    }
	}
	else {
	    next_intuit_at(beginning_of_this_line,p_input_line);
	    break;
	}
    }
    if (!tmpfp)
      return;
    if (fwrite ("w\nq\n", sizeof (char), (size_t) 4, tmpfp) == 0
	|| fflush (tmpfp) != 0)
      write_fatal ();

    if (lseek (tmpfd, 0, SEEK_SET) == -1)
      pfatal ("Can't rewind to the beginning of file %s", quotearg (tmpname));

    if (! dry_run && ! skip_rest_of_patch) {
	int exclusive = *outname_needs_removal ? 0 : O_EXCL;
	*outname_needs_removal = true;
	if (inerrno != ENOENT)
	  {
 	    *outname_needs_removal = true;
 	    copy_file (inname, outname, 0, exclusive, instat.st_mode, true);
 	  }
	sprintf (buf, "%s %s%s", editor_program,
		 verbosity == VERBOSE ? "" : "- ",
		 outname);
 	fflush (stdout);

 	pid = fork();
	fflush (stdout);

 	else if (pid == 0)
 	  {
 	    dup2 (tmpfd, 0);
	    execl ("/bin/sh", "sh", "-c", buf, (char *) 0);
 	    _exit (2);
 	  }
 	else
	  }
	else
	  {
	    int wstatus;
	    if (waitpid (pid, &wstatus, 0) == -1
	        || ! WIFEXITED (wstatus)
		|| WEXITSTATUS (wstatus) != 0)
	      fatal ("%s FAILED", editor_program);
	  }
    }

GNU patch through 2.7.6 is vulnerable to OS shell command injection that can be exploited by opening a crafted patch file that contains an ed style diff payload with shell metacharacters. The ed editor does not need to be present on the vulnerable system. This is different from CVE-2018-1000156.


do_ed_script (char const *inname, char const *outname,
	      bool *outname_needs_removal, FILE *ofp)
{
    static char const editor_program[] = EDITOR_PROGRAM;

    file_offset beginning_of_this_line;
    size_t chars_read;
    FILE *tmpfp = 0;
    char const *tmpname;
    int tmpfd;
    pid_t pid;

    if (! dry_run && ! skip_rest_of_patch)
      {
	/* Write ed script to a temporary file.  This causes ed to abort on
	   invalid commands such as when line numbers or ranges exceed the
	   number of available lines.  When ed reads from a pipe, it rejects
	   invalid commands and treats the next line as a new command, which
	   can lead to arbitrary command execution.  */

	tmpfd = make_tempfile (&tmpname, 'e', NULL, O_RDWR | O_BINARY, 0);
	if (tmpfd == -1)
	  pfatal ("Can't create temporary file %s", quotearg (tmpname));
	tmpfp = fdopen (tmpfd, "w+b");
	if (! tmpfp)
	  pfatal ("Can't open stream for file %s", quotearg (tmpname));
      }

    for (;;) {
	char ed_command_letter;
	beginning_of_this_line = file_tell (pfp);
	chars_read = get_line ();
	if (! chars_read) {
	    next_intuit_at(beginning_of_this_line,p_input_line);
	    break;
	}
	ed_command_letter = get_ed_command_letter (buf);
	if (ed_command_letter) {
	    if (tmpfp)
		if (! fwrite (buf, sizeof *buf, chars_read, tmpfp))
		    write_fatal ();
	    if (ed_command_letter != 'd' && ed_command_letter != 's') {
	        p_pass_comments_through = true;
		while ((chars_read = get_line ()) != 0) {
		    if (tmpfp)
			if (! fwrite (buf, sizeof *buf, chars_read, tmpfp))
			    write_fatal ();
		    if (chars_read == 2  &&  strEQ (buf, ".\n"))
			break;
		}
		p_pass_comments_through = false;
	    }
	}
	else {
	    next_intuit_at(beginning_of_this_line,p_input_line);
	    break;
	}
    }
    if (!tmpfp)
      return;
    if (fwrite ("w\nq\n", sizeof (char), (size_t) 4, tmpfp) == 0
	|| fflush (tmpfp) != 0)
      write_fatal ();

    if (lseek (tmpfd, 0, SEEK_SET) == -1)
      pfatal ("Can't rewind to the beginning of file %s", quotearg (tmpname));

    if (! dry_run && ! skip_rest_of_patch) {
	int exclusive = *outname_needs_removal ? 0 : O_EXCL;
	*outname_needs_removal = true;
	if (inerrno != ENOENT)
	  {
 	    *outname_needs_removal = true;
 	    copy_file (inname, outname, 0, exclusive, instat.st_mode, true);
 	  }
 	fflush (stdout);

 	pid = fork();
	fflush (stdout);

 	else if (pid == 0)
 	  {
 	    dup2 (tmpfd, 0);
	    assert (outname[0] != '!' && outname[0] != '-');
	    execlp (editor_program, editor_program, "-", outname, (char  *) NULL);
 	    _exit (2);
 	  }
 	else
	  }
	else
	  {
	    int wstatus;
	    if (waitpid (pid, &wstatus, 0) == -1
	        || ! WIFEXITED (wstatus)
		|| WEXITSTATUS (wstatus) != 0)
	      fatal ("%s FAILED", editor_program);
	  }
    }


xkb: Handle xkb formated string output safely (CVE-2017-13723)

Generating strings for XKB data used a single shared static buffer,
which offered several opportunities for errors. Use a ring of
resizable buffers instead, to avoid problems when strings end up
longer than anticipated.

Reviewed-by: Michal Srb <msrb@suse.com>
Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Julien Cristau <jcristau@debian.org>

 tbGetBuffer(unsigned size)
 {
    char *rtrn;

    if (size >= BUFFER_SIZE)
        return NULL;
    if ((BUFFER_SIZE - tbNext) <= size)
        tbNext = 0;
    rtrn = &textBuffer[tbNext];
    tbNext += size;
    return rtrn;
 }

In X.Org Server (aka xserver and xorg-server) before 1.19.4, a local attacker authenticated to the X server could overflow a global buffer, causing crashes of the X server or potentially other problems by injecting large or malformed XKB related atoms and accessing them via xkbcomp.


 tbGetBuffer(unsigned size)
 {
    struct textBuffer *tb;

    tb = &textBuffer[textBufferIndex];
    textBufferIndex = (textBufferIndex + 1) % NUM_BUFFER;

    if (size > tb->size) {
        free(tb->buffer);
        tb->buffer = xnfalloc(size);
        tb->size = size;
    }
    return tb->buffer;
 }