Commit message: None
CVE: CVE-2017-0402
CWE: CWE-200
Vulnerability description: 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.

Project: Android

int Effect_command(effect_handle_t  self,
 uint32_t            cmdCode,
 uint32_t            cmdSize,
 void *pCmdData,
 uint32_t *replySize,
 void *pReplyData){
 EffectContext * pContext = (EffectContext *) self;
 int retsize;


 if(pContext->EffectType == LVM_BASS_BOOST){
 }
 if(pContext->EffectType == LVM_VIRTUALIZER){
 }
 if(pContext->EffectType == LVM_EQUALIZER){
 }
 if(pContext->EffectType == LVM_VOLUME){
 }

 if (pContext == NULL){
        ALOGV("\tLVM_ERROR : Effect_command ERROR pContext == NULL");
 return -EINVAL;
 }




 switch (cmdCode){
 case EFFECT_CMD_INIT:
 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)){
                ALOGV("\tLVM_ERROR, EFFECT_CMD_INIT: ERROR for effect type %d",
                        pContext->EffectType);
 return -EINVAL;
 }
 *(int *) pReplyData = 0;
 if(pContext->EffectType == LVM_BASS_BOOST){
                android::BassSetStrength(pContext, 0);
 }
 if(pContext->EffectType == LVM_VIRTUALIZER){
                android::VirtualizerSetStrength(pContext, 0);
 }
 if(pContext->EffectType == LVM_EQUALIZER){
                android::EqualizerSetPreset(pContext, 0);
 }
 if(pContext->EffectType == LVM_VOLUME){
 *(int *) pReplyData = android::VolumeSetVolumeLevel(pContext, 0);
 }
 break;

 case EFFECT_CMD_SET_CONFIG:
 if (pCmdData    == NULL || cmdSize     != sizeof(effect_config_t) ||
                    pReplyData  == NULL || replySize == NULL || *replySize  != sizeof(int)) {
                ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
 "EFFECT_CMD_SET_CONFIG: ERROR");
 return -EINVAL;
 }
 *(int *) pReplyData = android::Effect_setConfig(pContext, (effect_config_t *) pCmdData);
 break;

 case EFFECT_CMD_GET_CONFIG:
 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(effect_config_t)) {
                ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
 "EFFECT_CMD_GET_CONFIG: ERROR");
 return -EINVAL;
 }

            android::Effect_getConfig(pContext, (effect_config_t *)pReplyData);
 break;

 case EFFECT_CMD_RESET:
            android::Effect_setConfig(pContext, &pContext->config);
 break;

 case EFFECT_CMD_GET_PARAM:{

 effect_param_t *p = (effect_param_t *)pCmdData;
 if (SIZE_MAX - sizeof(effect_param_t) < (size_t)p->psize) {
                android_errorWriteLog(0x534e4554, "26347509");
 return -EINVAL;
 }
 if (pCmdData == NULL || cmdSize < sizeof(effect_param_t) ||
                    cmdSize < (sizeof(effect_param_t) + p->psize) ||
                    pReplyData == NULL || replySize == NULL ||
 *replySize < (sizeof(effect_param_t) + p->psize)) {
                ALOGV("\tLVM_ERROR : EFFECT_CMD_GET_PARAM: ERROR");
 return -EINVAL;
 }

            memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);

            p = (effect_param_t *)pReplyData;

 int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);

 if(pContext->EffectType == LVM_BASS_BOOST){
                p->status = android::BassBoost_getParameter(pContext,
                                                            p->data,
 &p->vsize,
                                                            p->data + voffset);
 }

 if(pContext->EffectType == LVM_VIRTUALIZER){
                p->status = android::Virtualizer_getParameter(pContext,
 (void *)p->data,
 &p->vsize,
                                                              p->data + voffset);

 }
 if(pContext->EffectType == LVM_EQUALIZER){
                p->status = android::Equalizer_getParameter(pContext,
                                                            p->data,
 &p->vsize,
                                                            p->data + voffset);

 }
 if(pContext->EffectType == LVM_VOLUME){
                p->status = android::Volume_getParameter(pContext,
 (void *)p->data,
 &p->vsize,
                                                         p->data + voffset);

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

 } break;
 case EFFECT_CMD_SET_PARAM:{
 if(pContext->EffectType == LVM_BASS_BOOST){

 if (pCmdData   == NULL ||
                        cmdSize    != (sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t)) ||
                        pReplyData == NULL || replySize == NULL || *replySize != sizeof(int32_t)) {
                    ALOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
 "EFFECT_CMD_SET_PARAM: ERROR");
 return -EINVAL;
 }
 effect_param_t *p = (effect_param_t *) pCmdData;

 if (p->psize != sizeof(int32_t)){
                    ALOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
 return -EINVAL;
 }


 *(int *)pReplyData = android::BassBoost_setParameter(pContext,
 (void *)p->data,
                                                                    p->data + p->psize);
 }
 if(pContext->EffectType == LVM_VIRTUALIZER){

 if (pCmdData   == NULL ||
                        cmdSize    > (sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int32_t)) ||
                        cmdSize    < (sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t)) ||
                        pReplyData == NULL || replySize == NULL || *replySize != sizeof(int32_t)) {
                    ALOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
 "EFFECT_CMD_SET_PARAM: ERROR");
 return -EINVAL;
 }
 effect_param_t *p = (effect_param_t *) pCmdData;

 if (p->psize != sizeof(int32_t)){
                    ALOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
 "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
 return -EINVAL;
 }


 *(int *)pReplyData = android::Virtualizer_setParameter(pContext,
 (void *)p->data,
                                                                       p->data + p->psize);
 }
 if(pContext->EffectType == LVM_EQUALIZER){

 if (pCmdData == NULL || cmdSize < (sizeof(effect_param_t) + sizeof(int32_t)) ||
                        pReplyData == NULL || replySize == NULL || *replySize != sizeof(int32_t)) {
                    ALOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
 "EFFECT_CMD_SET_PARAM: ERROR");
 return -EINVAL;
 }
 effect_param_t *p = (effect_param_t *) pCmdData;

 *(int *)pReplyData = android::Equalizer_setParameter(pContext,
 (void *)p->data,
                                                                     p->data + p->psize);
 }
 if(pContext->EffectType == LVM_VOLUME){

 if (pCmdData   == NULL ||
                        cmdSize    < (sizeof(effect_param_t) + sizeof(int32_t)) ||
                        pReplyData == NULL || replySize == NULL ||
 *replySize != sizeof(int32_t)) {
                    ALOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
 "EFFECT_CMD_SET_PARAM: ERROR");
 return -EINVAL;
 }
 effect_param_t *p = (effect_param_t *) pCmdData;

 *(int *)pReplyData = android::Volume_setParameter(pContext,
 (void *)p->data,
                                                                 p->data + p->psize);
 }
 } break;

 case EFFECT_CMD_ENABLE:
            ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE start");
 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
                ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
 return -EINVAL;
 }

 *(int *)pReplyData = android::Effect_setEnabled(pContext, LVM_TRUE);
 break;

 case EFFECT_CMD_DISABLE:
 if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
                ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
 return -EINVAL;
 }
 *(int *)pReplyData = android::Effect_setEnabled(pContext, LVM_FALSE);
 break;

 case EFFECT_CMD_SET_DEVICE:
 {
            ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE start");
 if (pCmdData   == NULL){
                ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_SET_DEVICE: ERROR");
 return -EINVAL;
 }

 uint32_t device = *(uint32_t *)pCmdData;
            pContext->pBundledContext->nOutputDevice = (audio_devices_t) device;

 if (pContext->EffectType == LVM_BASS_BOOST) {
 if((device == AUDIO_DEVICE_OUT_SPEAKER) ||
 (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) ||
 (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
                    ALOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_BASS_BOOST %d",
 *(int32_t *)pCmdData);
                    ALOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_BAS_BOOST");


 if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
                        ALOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_BASS_BOOST %d",
 *(int32_t *)pCmdData);
                        android::LvmEffect_disable(pContext);
 }
                    pContext->pBundledContext->bBassTempDisabled = LVM_TRUE;
 } else {
                    ALOGV("\tEFFECT_CMD_SET_DEVICE device is valid for LVM_BASS_BOOST %d",
 *(int32_t *)pCmdData);


 if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
                        ALOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_BASS_BOOST %d",
 *(int32_t *)pCmdData);
                        android::LvmEffect_enable(pContext);
 }
                    pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
 }
 }
 if (pContext->EffectType == LVM_VIRTUALIZER) {
 if (pContext->pBundledContext->nVirtualizerForcedDevice == AUDIO_DEVICE_NONE) {
 if (android::VirtualizerIsDeviceSupported(device) != 0) {
                        ALOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_VIRTUALIZER %d",
 *(int32_t *)pCmdData);
                        ALOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_VIRTUALIZER");


 if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
                            ALOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_VIRTUALIZER %d",
 *(int32_t *)pCmdData);
                            android::LvmEffect_disable(pContext);
 }
                        pContext->pBundledContext->bVirtualizerTempDisabled = LVM_TRUE;
 } else {
                        ALOGV("\tEFFECT_CMD_SET_DEVICE device is valid for LVM_VIRTUALIZER %d",
 *(int32_t *)pCmdData);


 if(pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE){
                            ALOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_VIRTUALIZER %d",
 *(int32_t *)pCmdData);
                            android::LvmEffect_enable(pContext);
 }
                        pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
 }
 } // else virtualization mode is forced to a certain device, nothing to do
 }
            ALOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE end");
 break;
 }
 case EFFECT_CMD_SET_VOLUME:
 {
 uint32_t leftVolume, rightVolume;
 int16_t  leftdB, rightdB;
 int16_t  maxdB, pandB;
 int32_t  vol_ret[2] = {1<<24,1<<24}; // Apply no volume
 int      status = 0;
 LVM_ControlParams_t ActiveParams; /* Current control Parameters */
            LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS; /* Function call status */

 if(pReplyData == LVM_NULL){
 break;
 }

 if (pCmdData == NULL || cmdSize != 2 * sizeof(uint32_t) || pReplyData == NULL ||
                    replySize == NULL || *replySize < 2*sizeof(int32_t)) {
                ALOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
 "EFFECT_CMD_SET_VOLUME: ERROR");
 return -EINVAL;
 }

            leftVolume  = ((*(uint32_t *)pCmdData));
            rightVolume = ((*((uint32_t *)pCmdData + 1)));

 if(leftVolume == 0x1000000){
                leftVolume -= 1;
 }
 if(rightVolume == 0x1000000){
                rightVolume -= 1;
 }

            leftdB  = android::LVC_Convert_VolToDb(leftVolume);
            rightdB = android::LVC_Convert_VolToDb(rightVolume);

            pandB = rightdB - leftdB;

            maxdB = leftdB;
 if(rightdB > maxdB){
                maxdB = rightdB;
 }

            memcpy(pReplyData, vol_ret, sizeof(int32_t)*2);
            android::VolumeSetVolumeLevel(pContext, (int16_t)(maxdB*100));

 /* Get the current settings */
 LvmStatus =LVM_GetControlParameters(pContext->pBundledContext->hInstance,&ActiveParams);
            LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetStereoPosition")
 if(LvmStatus != LVM_SUCCESS) return -EINVAL;

 /* Volume parameters */
 ActiveParams.VC_Balance  = pandB;
            ALOGV("\t\tVolumeSetStereoPosition() (-96dB -> +96dB)-> %d\n", ActiveParams.VC_Balance );

 /* Activate the initial settings */
 LvmStatus =LVM_SetControlParameters(pContext->pBundledContext->hInstance,&ActiveParams);
            LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeSetStereoPosition")
 if(LvmStatus != LVM_SUCCESS) return -EINVAL;
 break;
 }
 case EFFECT_CMD_SET_AUDIO_MODE:
 break;
 default:
 return -EINVAL;
 }

 return 0;
} /* end Effect_command */

Project: Android

int LvmBundle_process(LVM_INT16        *pIn,
                      LVM_INT16        *pOut,
 int              frameCount,
 EffectContext *pContext){

 LVM_ControlParams_t ActiveParams; /* Current control Parameters */
    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS; /* Function call status */
    LVM_INT16               *pOutTmp;

 if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE){
        pOutTmp = pOut;
 } else if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
 if (pContext->pBundledContext->frameCount != frameCount) {
 if (pContext->pBundledContext->workBuffer != NULL) {
                free(pContext->pBundledContext->workBuffer);
 }
            pContext->pBundledContext->workBuffer =
 (LVM_INT16 *)calloc(frameCount, sizeof(LVM_INT16) * 2);
 if (pContext->pBundledContext->workBuffer == NULL) {
 return -ENOMEM;
 }
            pContext->pBundledContext->frameCount = frameCount;
 }
        pOutTmp = pContext->pBundledContext->workBuffer;
 } else {
        ALOGV("LVM_ERROR : LvmBundle_process invalid access mode");
 return -EINVAL;
 }

 #ifdef LVM_PCM
    fwrite(pIn, frameCount*sizeof(LVM_INT16)*2, 1, pContext->pBundledContext->PcmInPtr);
    fflush(pContext->pBundledContext->PcmInPtr);
 #endif


 /* Process the samples */
 LvmStatus = LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
                            pIn, /* Input buffer */
                            pOutTmp, /* Output buffer */
 (LVM_UINT16)frameCount, /* Number of samples to read */
 0); /* Audo Time */

    LVM_ERROR_CHECK(LvmStatus, "LVM_Process", "LvmBundle_process")
 if(LvmStatus != LVM_SUCCESS) return -EINVAL;

 #ifdef LVM_PCM
    fwrite(pOutTmp, frameCount*sizeof(LVM_INT16)*2, 1, pContext->pBundledContext->PcmOutPtr);
    fflush(pContext->pBundledContext->PcmOutPtr);
 #endif

 if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
 for (int i=0; i<frameCount*2; i++){
            pOut[i] = clamp16((LVM_INT32)pOut[i] + (LVM_INT32)pOutTmp[i]);
 }
 }
 return 0;
} /* end LvmBundle_process */

Project: Android

void LvmEffect_limitLevel(EffectContext *pContext) {
 LVM_ControlParams_t ActiveParams; /* Current control Parameters */
    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS; /* Function call status */

 /* Get the current settings */
 LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "LvmEffect_limitLevel")

 int gainCorrection = 0;
 float energyContribution = 0;
 float energyCross = 0;
 float energyBassBoost = 0;
 float crossCorrection = 0;

 if (pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE) {
 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
 float bandFactor = pContext->pBundledContext->bandGaindB[i]/15.0;
 float bandCoefficient = LimitLevel_bandEnergyCoefficient[i];
 float bandEnergy = bandFactor * bandCoefficient * bandCoefficient;
 if (bandEnergy > 0)
                energyContribution += bandEnergy;
 }

 float bandFactorSum = 0;
 for (int i = 0; i < FIVEBAND_NUMBANDS-1; i++) {
 float bandFactor1 = pContext->pBundledContext->bandGaindB[i]/15.0;
 float bandFactor2 = pContext->pBundledContext->bandGaindB[i+1]/15.0;

 if (bandFactor1 > 0 && bandFactor2 > 0) {
 float crossEnergy = bandFactor1 * bandFactor2 *
 LimitLevel_bandEnergyCrossCoefficient[i];
                bandFactorSum += bandFactor1 * bandFactor2;

 if (crossEnergy > 0)
                    energyCross += crossEnergy;
 }
 }
        bandFactorSum -= 1.0;
 if (bandFactorSum > 0)
            crossCorrection = bandFactorSum * 0.7;
 }

 if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
 float boostFactor = (pContext->pBundledContext->BassStrengthSaved)/1000.0;
 float boostCoefficient = LimitLevel_bassBoostEnergyCoefficient;

        energyContribution += boostFactor * boostCoefficient * boostCoefficient;

 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
 float bandFactor = pContext->pBundledContext->bandGaindB[i]/15.0;
 float bandCrossCoefficient = LimitLevel_bassBoostEnergyCrossCoefficient[i];
 float bandEnergy = boostFactor * bandFactor *
                    bandCrossCoefficient;
 if (bandEnergy > 0)
                energyBassBoost += bandEnergy;
 }
 }

 if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
        energyContribution += LimitLevel_virtualizerContribution *
 LimitLevel_virtualizerContribution;
 }

 double totalEnergyEstimation = sqrt(energyContribution + energyCross + energyBassBoost) -
            crossCorrection;
    ALOGV(" TOTAL energy estimation: %0.2f", totalEnergyEstimation);

 int maxLevelRound = (int)(totalEnergyEstimation + 0.99);
 if (maxLevelRound + pContext->pBundledContext->volume > 0) {
        gainCorrection = maxLevelRound + pContext->pBundledContext->volume;
 }

 ActiveParams.VC_EffectLevel  = pContext->pBundledContext->volume - gainCorrection;
 if (ActiveParams.VC_EffectLevel < -96) {
 ActiveParams.VC_EffectLevel = -96;
 }
    ALOGV("\tVol:%d, GainCorrection: %d, Actual vol: %d", pContext->pBundledContext->volume,
            gainCorrection, ActiveParams.VC_EffectLevel);

 /* Activate the initial settings */
 LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmEffect_limitLevel")

 if (pContext->pBundledContext->firstVolume == LVM_TRUE){
 LvmStatus = LVM_SetVolumeNoSmoothing(pContext->pBundledContext->hInstance, &ActiveParams);
        LVM_ERROR_CHECK(LvmStatus, "LVM_SetVolumeNoSmoothing", "LvmBundle_process")
        ALOGV("\tLVM_VOLUME: Disabling Smoothing for first volume change to remove spikes/clicks");
        pContext->pBundledContext->firstVolume = LVM_FALSE;
 }
}